blob: 516609689f2b9158ffbd3c4d426c51b968872118 [file] [log] [blame]
Daniel Veillard4255d502002-04-16 15:50:10 +00001/*
2 * schemas.c : implementation of the XML Schema handling and
3 * schema validity checking
4 *
5 * See Copyright for the status of this software.
6 *
7 * Daniel Veillard <veillard@redhat.com>
8 */
9
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000010/*
Daniel Veillardb0f397e2003-12-23 23:30:53 +000011 * TODO:
12 * - when types are redefined in includes, check that all
13 * types in the redef list are equal
14 * -> need a type equality operation.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015 * - if we don't intend to use the schema for schemas, we
16 * need to validate all schema attributes (ref, type, name)
17 * against their types.
Daniel Veillardb0f397e2003-12-23 23:30:53 +000018 */
Daniel Veillard4255d502002-04-16 15:50:10 +000019#define IN_LIBXML
20#include "libxml.h"
21
22#ifdef LIBXML_SCHEMAS_ENABLED
23
24#include <string.h>
25#include <libxml/xmlmemory.h>
26#include <libxml/parser.h>
27#include <libxml/parserInternals.h>
28#include <libxml/hash.h>
Daniel Veillard5a872412002-05-22 06:40:27 +000029#include <libxml/uri.h>
Daniel Veillard4255d502002-04-16 15:50:10 +000030
31#include <libxml/xmlschemas.h>
32#include <libxml/schemasInternals.h>
33#include <libxml/xmlschemastypes.h>
34#include <libxml/xmlautomata.h>
35#include <libxml/xmlregexp.h>
Daniel Veillardbe9c6322003-11-22 20:37:51 +000036#include <libxml/dict.h>
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000037#ifdef LIBXML_PATTERN_ENABLED
38#include <libxml/pattern.h>
39#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000040
Daniel Veillarda84c0b32003-06-02 16:58:46 +000041/* #define DEBUG 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000042
Daniel Veillard82bbbd42003-05-11 20:16:09 +000043/* #define DEBUG_CONTENT 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000044
Daniel Veillard82bbbd42003-05-11 20:16:09 +000045/* #define DEBUG_TYPE 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000046
Daniel Veillard118aed72002-09-24 14:13:13 +000047/* #define DEBUG_CONTENT_REGEXP 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000048
Daniel Veillard4255d502002-04-16 15:50:10 +000049/* #define DEBUG_AUTOMATA 1 */
50
Daniel Veillard3646d642004-06-02 19:19:14 +000051/* #define DEBUG_ATTR_VALIDATION 1 */
52
Daniel Veillardc0826a72004-08-10 14:17:33 +000053/* #define DEBUG_UNION_VALIDATION 1 */
54
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000055#define ELEM_INFO_ENABLED 1
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000056
Kasimier T. Buchcik285ebab2005-03-04 18:04:59 +000057#define IDC_ENABLED 1
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000058
Kasimier T. Buchcik285ebab2005-03-04 18:04:59 +000059#define IDC_VALUE_SUPPORT 1
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000060
Kasimier T. Buchcik285ebab2005-03-04 18:04:59 +000061#define IDC_XPATH_SUPPORT 1
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000062
63/* #define DEBUG_IDC 1 */
64
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*/
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000382#define XML_SCHEMA_ELEM_INFO_VALUE_NEEDED 1
383/* #define XML_SCHEMA_ELEM_INFO_ATTR 2 */
384/* #define XML_SCHEMA_ELEM_INFO_ELEM 4 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000385
386/**
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000387 * xmlSchemaNodeInfo:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000388 *
389 * Holds information of an element node.
390 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000391typedef struct _xmlSchemaNodeInfo xmlSchemaNodeInfo;
392typedef xmlSchemaNodeInfo *xmlSchemaNodeInfoPtr;
393struct _xmlSchemaNodeInfo {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000394 int depth;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000395 int flags; /* combination of node info flags */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000396 xmlNodePtr node;
397 const xmlChar *localName;
398 const xmlChar *namespaceName;
399 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +0000400 xmlSchemaTypePtr decl; /* the element/attribute declaration */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000401 xmlSchemaValPtr value; /* the pre-computed value if any */
402 xmlSchemaPSVIIDCBindingPtr idcTable; /* the table of PSVI IDC bindings
403 for the scope element*/
404 xmlSchemaIDCMatcherPtr idcMatchers; /* the IDC matchers for the scope
405 element */
406};
407
Daniel Veillard4255d502002-04-16 15:50:10 +0000408/**
409 * xmlSchemaValidCtxt:
410 *
411 * A Schemas validation context
412 */
413
414struct _xmlSchemaValidCtxt {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000415 void *userData; /* user specific data block */
416 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000417 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000418 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000419
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000420 xmlSchemaPtr schema; /* The schema in use */
421 xmlDocPtr doc;
Daniel Veillard4255d502002-04-16 15:50:10 +0000422 xmlParserInputBufferPtr input;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000423 xmlCharEncoding enc;
424 xmlSAXHandlerPtr sax;
425 void *user_data;
Daniel Veillard4255d502002-04-16 15:50:10 +0000426
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000427 xmlDocPtr myDoc;
428 int err;
429 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +0000430
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000431 xmlNodePtr node;
432 xmlNodePtr cur;
433 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +0000434
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000435 xmlRegExecCtxtPtr regexp;
436 xmlSchemaValPtr value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000437
Daniel Veillard3646d642004-06-02 19:19:14 +0000438 xmlSchemaAttrStatePtr attrTop;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000439 xmlSchemaAttrStatePtr attr;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000440 /* xmlNodePtr scope; not used */
Daniel Veillardc0826a72004-08-10 14:17:33 +0000441 int valueWS;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000442 int options;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000443 xmlNodePtr validationRoot;
444 xmlSchemaParserCtxtPtr pctxt;
445 int xsiAssemble;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000446#ifdef ELEM_INFO_ENABLED
447 int depth;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000448 xmlSchemaNodeInfoPtr *elemInfos; /* array of element informations */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000449 int sizeElemInfos;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000450 xmlSchemaNodeInfoPtr nodeInfo; /* the current element information */
451 xmlSchemaNodeInfoPtr attrInfo; /* node infor for the current attribute */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000452#endif
453#ifdef IDC_ENABLED
454 xmlSchemaIDCAugPtr aidcs; /* a list of augmented IDC informations */
455
456 xmlSchemaIDCStateObjPtr xpathStates; /* first active state object. */
457 xmlSchemaIDCStateObjPtr xpathStatePool; /* first stored state object. */
458
459 xmlSchemaPSVIIDCNodePtr *idcNodes; /* list of all IDC node-table entries*/
460 int nbIdcNodes;
461 int sizeIdcNodes;
462
463 xmlSchemaPSVIIDCKeyPtr *idcKeys; /* list of all IDC node-table entries */
464 int nbIdcKeys;
465 int sizeIdcKeys;
466#endif
Daniel Veillard4255d502002-04-16 15:50:10 +0000467};
468
Daniel Veillard1d913862003-11-21 00:28:39 +0000469/*
470 * These are the entries in the schemas importSchemas hash table
471 */
472typedef struct _xmlSchemaImport xmlSchemaImport;
473typedef xmlSchemaImport *xmlSchemaImportPtr;
474struct _xmlSchemaImport {
475 const xmlChar *schemaLocation;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000476 xmlSchemaPtr schema; /* not used any more */
William M. Brack2f2a6632004-08-20 23:09:47 +0000477 xmlDocPtr doc;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000478 int isMain;
Daniel Veillard1d913862003-11-21 00:28:39 +0000479};
Daniel Veillard4255d502002-04-16 15:50:10 +0000480
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000481/*
482 * These are the entries associated to includes in a schemas
483 */
484typedef struct _xmlSchemaInclude xmlSchemaInclude;
485typedef xmlSchemaInclude *xmlSchemaIncludePtr;
486struct _xmlSchemaInclude {
487 xmlSchemaIncludePtr next;
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000488 const xmlChar *schemaLocation;
489 xmlDocPtr doc;
490};
491
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000492typedef struct _xmlSchemaParticle xmlSchemaParticle;
493typedef xmlSchemaParticle *xmlSchemaParticlePtr;
494struct _xmlSchemaParticle {
495 xmlSchemaTypeType type;
496 xmlSchemaParticlePtr next; /* the next particle if in a list */
497 int minOccurs;
498 int maxOccurs;
499 xmlSchemaTypePtr term;
500};
501
502
503typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup;
504typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr;
505struct _xmlSchemaModelGroup {
506 xmlSchemaTypeType type;
507 int compositor; /* one of all, choice or sequence */
508 xmlSchemaParticlePtr particles; /* list of particles */
509 xmlSchemaAnnotPtr annot;
510};
511
512typedef struct _xmlSchemaModelGroupDef xmlSchemaModelGroupDef;
513typedef xmlSchemaModelGroupDef *xmlSchemaModelGroupDefPtr;
514struct _xmlSchemaModelGroupDef {
515 xmlSchemaTypeType type;
516 const xmlChar *name;
517 const xmlChar *targetNamespace;
518 xmlSchemaModelGroupPtr modelGroup;
519 xmlSchemaAnnotPtr annot;
520};
521
Daniel Veillard4255d502002-04-16 15:50:10 +0000522/************************************************************************
523 * *
524 * Some predeclarations *
525 * *
526 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000527
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000528static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
529 xmlSchemaPtr schema,
530 xmlNodePtr node);
Daniel Veillard01fa6152004-06-29 17:04:39 +0000531static void
532xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
533 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +0000534static const xmlChar *
Daniel Veillard01fa6152004-06-29 17:04:39 +0000535xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
536static int
537xmlSchemaValidateSimpleTypeValue(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000538 xmlSchemaTypePtr type,
Daniel Veillard01fa6152004-06-29 17:04:39 +0000539 const xmlChar *value,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000540 int fireErrors,
Daniel Veillardc0826a72004-08-10 14:17:33 +0000541 int applyFacets,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000542 int normalize,
543 int checkNodes);
544static int
545xmlSchemaValidateElementByDeclaration(xmlSchemaValidCtxtPtr ctxt,
546 xmlSchemaElementPtr elemDecl);
547static int
548xmlSchemaValidateElementByWildcard(xmlSchemaValidCtxtPtr ctxt,
549 xmlSchemaTypePtr type);
550static int
551xmlSchemaHasElemOrCharContent(xmlNodePtr node);
William M. Brack2f2a6632004-08-20 23:09:47 +0000552static int
553xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
554 xmlNodePtr node);
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +0000555static void
556xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
557 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +0000558static void
559xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt);
William M. Brack87640d52004-04-17 14:58:15 +0000560
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000561/************************************************************************
562 * *
563 * Datatype error handlers *
564 * *
565 ************************************************************************/
566
567/**
568 * xmlSchemaPErrMemory:
569 * @node: a context node
570 * @extra: extra informations
571 *
572 * Handle an out of memory condition
573 */
574static void
575xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
576 const char *extra, xmlNodePtr node)
577{
578 if (ctxt != NULL)
579 ctxt->nberrors++;
580 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
581 extra);
582}
583
584/**
585 * xmlSchemaPErr:
586 * @ctxt: the parsing context
587 * @node: the context node
588 * @error: the error code
589 * @msg: the error message
590 * @str1: extra data
591 * @str2: extra data
592 *
593 * Handle a parser error
594 */
595static void
596xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
597 const char *msg, const xmlChar * str1, const xmlChar * str2)
598{
599 xmlGenericErrorFunc channel = NULL;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000600 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000601 void *data = NULL;
602
603 if (ctxt != NULL) {
604 ctxt->nberrors++;
605 channel = ctxt->error;
606 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000607 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000608 }
Daniel Veillard659e71e2003-10-10 14:10:40 +0000609 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000610 error, XML_ERR_ERROR, NULL, 0,
611 (const char *) str1, (const char *) str2, NULL, 0, 0,
612 msg, str1, str2);
613}
614
615/**
616 * xmlSchemaPErr2:
617 * @ctxt: the parsing context
618 * @node: the context node
619 * @node: the current child
620 * @error: the error code
621 * @msg: the error message
622 * @str1: extra data
623 * @str2: extra data
624 *
625 * Handle a parser error
626 */
627static void
628xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
629 xmlNodePtr child, int error,
630 const char *msg, const xmlChar * str1, const xmlChar * str2)
631{
632 if (child != NULL)
633 xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
634 else
635 xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
636}
637
Daniel Veillard01fa6152004-06-29 17:04:39 +0000638
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000639/**
Daniel Veillard3646d642004-06-02 19:19:14 +0000640 * xmlSchemaPErrExt:
641 * @ctxt: the parsing context
642 * @node: the context node
643 * @error: the error code
644 * @strData1: extra data
645 * @strData2: extra data
646 * @strData3: extra data
647 * @msg: the message
648 * @str1: extra parameter for the message display
649 * @str2: extra parameter for the message display
650 * @str3: extra parameter for the message display
651 * @str4: extra parameter for the message display
652 * @str5: extra parameter for the message display
653 *
654 * Handle a parser error
655 */
656static void
657xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
658 const xmlChar * strData1, const xmlChar * strData2,
659 const xmlChar * strData3, const char *msg, const xmlChar * str1,
660 const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
661 const xmlChar * str5)
662{
663
664 xmlGenericErrorFunc channel = NULL;
665 xmlStructuredErrorFunc schannel = NULL;
666 void *data = NULL;
667
668 if (ctxt != NULL) {
669 ctxt->nberrors++;
670 channel = ctxt->error;
671 data = ctxt->userData;
672 schannel = ctxt->serror;
673 }
674 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
675 error, XML_ERR_ERROR, NULL, 0,
676 (const char *) strData1, (const char *) strData2,
William M. Brack803812b2004-06-03 02:11:24 +0000677 (const char *) strData3, 0, 0, msg, str1, str2,
678 str3, str4, str5);
Daniel Veillard3646d642004-06-02 19:19:14 +0000679}
Daniel Veillard01fa6152004-06-29 17:04:39 +0000680
Daniel Veillard3646d642004-06-02 19:19:14 +0000681
682/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000683 * xmlSchemaVTypeErrMemory:
684 * @node: a context node
685 * @extra: extra informations
686 *
687 * Handle an out of memory condition
688 */
689static void
690xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
691 const char *extra, xmlNodePtr node)
692{
693 if (ctxt != NULL) {
694 ctxt->nberrors++;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000695 ctxt->err = XML_SCHEMAV_INTERNAL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000696 }
697 __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
698 extra);
699}
700
701/**
702 * xmlSchemaVErr3:
703 * @ctxt: the validation context
704 * @node: the context node
705 * @error: the error code
706 * @msg: the error message
707 * @str1: extra data
708 * @str2: extra data
709 * @str3: extra data
710 *
711 * Handle a validation error
712 */
713static void
714xmlSchemaVErr3(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
715 const char *msg, const xmlChar *str1, const xmlChar *str2,
716 const xmlChar *str3)
717{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000718 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000719 xmlGenericErrorFunc channel = NULL;
720 void *data = NULL;
721
722 if (ctxt != NULL) {
723 ctxt->nberrors++;
724 ctxt->err = error;
725 channel = ctxt->error;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000726 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000727 data = ctxt->userData;
728 }
729 /* reajust to global error numbers */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000730 /* Removed, since the old schema error codes have been
731 * substituted for the global error codes.
732 *
733 * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
734 */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000735 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000736 error, XML_ERR_ERROR, NULL, 0,
737 (const char *) str1, (const char *) str2,
738 (const char *) str3, 0, 0,
739 msg, str1, str2, str3);
740}
Daniel Veillardc0826a72004-08-10 14:17:33 +0000741
742/**
743 * xmlSchemaVErrExt:
744 * @ctxt: the validation context
745 * @node: the context node
746 * @error: the error code
747 * @msg: the message
748 * @str1: extra parameter for the message display
749 * @str2: extra parameter for the message display
750 * @str3: extra parameter for the message display
751 * @str4: extra parameter for the message display
752 * @str5: extra parameter for the message display
753 *
754 * Handle a validation error
755 */
756static void
757xmlSchemaVErrExt(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
758 const char *msg, const xmlChar * str1,
759 const xmlChar * str2, const xmlChar * str3,
760 const xmlChar * str4, const xmlChar * str5)
761{
762 xmlStructuredErrorFunc schannel = NULL;
763 xmlGenericErrorFunc channel = NULL;
764 void *data = NULL;
765
766 if (ctxt != NULL) {
767 ctxt->nberrors++;
768 ctxt->err = error;
769 channel = ctxt->error;
770 schannel = ctxt->serror;
771 data = ctxt->userData;
772 }
773 /* reajust to global error numbers */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000774 /* Removed, since the old schema error codes have been
775 * substituted for the global error codes.
776 *
777 * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
778 */
Daniel Veillardc0826a72004-08-10 14:17:33 +0000779 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
780 error, XML_ERR_ERROR, NULL, 0, NULL, NULL, NULL, 0, 0,
781 msg, str1, str2, str3, str4, str5);
782}
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000783/**
784 * xmlSchemaVErr:
785 * @ctxt: the validation context
786 * @node: the context node
787 * @error: the error code
788 * @msg: the error message
789 * @str1: extra data
790 * @str2: extra data
791 *
792 * Handle a validation error
793 */
794static void
795xmlSchemaVErr(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
796 const char *msg, const xmlChar * str1, const xmlChar * str2)
797{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000798 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000799 xmlGenericErrorFunc channel = NULL;
800 void *data = NULL;
801
802 if (ctxt != NULL) {
803 ctxt->nberrors++;
804 ctxt->err = error;
805 channel = ctxt->error;
806 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000807 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000808 }
809 /* reajust to global error numbers */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000810 /* Removed, since the old schema error codes have been
811 * substituted for the global error codes.
812 *
813 * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
814 */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000815 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000816 error, XML_ERR_ERROR, NULL, 0,
817 (const char *) str1, (const char *) str2, NULL, 0, 0,
818 msg, str1, str2);
819}
Daniel Veillard4255d502002-04-16 15:50:10 +0000820
Daniel Veillardc0826a72004-08-10 14:17:33 +0000821/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000822 * xmlSchemaGetAttrName:
Daniel Veillardc0826a72004-08-10 14:17:33 +0000823 * @attr: the attribute declaration/use
824 *
825 * Returns the name of the attribute; if the attribute
826 * is a reference, the name of the referenced global type will be returned.
827 */
828static const xmlChar *
829xmlSchemaGetAttrName(xmlSchemaAttributePtr attr)
830{
831 if (attr->ref != NULL)
832 return(attr->ref);
833 else
834 return(attr->name);
835}
836
837/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000838 * xmlSchemaGetAttrTargetNsURI:
Daniel Veillardc0826a72004-08-10 14:17:33 +0000839 * @type: the type (element or attribute)
840 *
841 * Returns the target namespace URI of the type; if the type is a reference,
842 * the target namespace of the referenced type will be returned.
843 */
844static const xmlChar *
845xmlSchemaGetAttrTargetNsURI(xmlSchemaAttributePtr attr)
846{
847 if (attr->ref != NULL)
848 return (attr->refNs);
849 else
850 return(attr->targetNamespace);
851}
852
853/**
854 * xmlSchemaFormatNsUriLocal:
855 * @buf: the string buffer
856 * @uri: the namespace URI
857 * @local: the local name
858 *
859 * Returns a representation of the given URI used
860 * for error reports.
861 *
862 * Returns an empty string, if @ns is NULL, a formatted
863 * string otherwise.
864 */
865static const xmlChar*
866xmlSchemaFormatNsUriLocal(xmlChar **buf,
867 const xmlChar *uri, const xmlChar *local)
868{
869 if (*buf != NULL)
870 xmlFree(*buf);
871 if (uri == NULL) {
872 *buf = xmlStrdup(BAD_CAST "{'");
873 *buf = xmlStrcat(*buf, local);
874 } else {
875 *buf = xmlStrdup(BAD_CAST "{'");
876 *buf = xmlStrcat(*buf, uri);
877 *buf = xmlStrcat(*buf, BAD_CAST "', '");
878 *buf = xmlStrcat(*buf, local);
879 }
880 *buf = xmlStrcat(*buf, BAD_CAST "'}");
881 return ((const xmlChar *) *buf);
882}
883
884/**
885 * xmlSchemaFormatNsPrefixLocal:
886 * @buf: the string buffer
887 * @ns: the namespace
888 * @local: the local name
889 *
890 * Returns a representation of the given URI used
891 * for error reports.
892 *
893 * Returns an empty string, if @ns is NULL, a formatted
894 * string otherwise.
895 */
896static const xmlChar*
897xmlSchemaFormatNsPrefixLocal(xmlChar **buf,
898 xmlNsPtr ns, const xmlChar *local)
899{
900 if (*buf != NULL) {
901 xmlFree(*buf);
902 *buf = NULL;
903 }
904 if ((ns == NULL) || (ns->prefix == NULL))
905 return(local);
906 else {
907 *buf = xmlStrdup(ns->prefix);
908 *buf = xmlStrcat(*buf, BAD_CAST ":");
909 *buf = xmlStrcat(*buf, local);
910 }
911 return ((const xmlChar *) *buf);
912}
913
914/**
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000915 * xmlSchemaFormatQName:
916 * @buf: the string buffer
917 * @namespaceName: the namespace name
918 * @localName: the local name
919 *
920 * Returns the given QName in the format "{namespaceName}localName" or
921 * just "localName" if @namespaceName is NULL.
922 *
923 * Returns the localName if @namespaceName is NULL, a formatted
924 * string otherwise.
925 */
926static const xmlChar*
927xmlSchemaFormatQName(xmlChar **buf,
928 const xmlChar *namespaceName,
929 const xmlChar *localName)
930{
931 FREE_AND_NULL(*buf)
932 if (namespaceName == NULL)
933 return(localName);
934
935 *buf = xmlStrdup(BAD_CAST "{");
936 *buf = xmlStrcat(*buf, namespaceName);
937 *buf = xmlStrcat(*buf, BAD_CAST "}");
938 *buf = xmlStrcat(*buf, localName);
939
940 return ((const xmlChar *) *buf);
941}
942
943/**
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +0000944 * xmlSchemaWildcardPCToString:
945 * @pc: the type of processContents
946 *
947 * Returns a string representation of the type of
948 * processContents.
949 */
950static const xmlChar *
951xmlSchemaWildcardPCToString(int pc)
952{
953 switch (pc) {
954 case XML_SCHEMAS_ANY_SKIP:
955 return (BAD_CAST "skip");
956 case XML_SCHEMAS_ANY_LAX:
957 return (BAD_CAST "lax");
958 case XML_SCHEMAS_ANY_STRICT:
959 return (BAD_CAST "strict");
960 default:
961 return (BAD_CAST "invalid process contents");
962 }
963}
964
965/**
Daniel Veillardc0826a72004-08-10 14:17:33 +0000966 * xmlSchemaFormatItemForReport:
967 * @buf: the string buffer
968 * @itemDes: the designation of the item
969 * @itemName: the name of the item
970 * @item: the item as an object
971 * @itemNode: the node of the item
972 * @local: the local name
973 * @parsing: if the function is used during the parse
974 *
975 * Returns a representation of the given item used
976 * for error reports.
977 *
978 * The following order is used to build the resulting
979 * designation if the arguments are not NULL:
980 * 1a. If itemDes not NULL -> itemDes
981 * 1b. If (itemDes not NULL) and (itemName not NULL)
982 * -> itemDes + itemName
983 * 2. If the preceding was NULL and (item not NULL) -> item
984 * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
985 *
986 * If the itemNode is an attribute node, the name of the attribute
987 * will be appended to the result.
988 *
989 * Returns the formatted string and sets @buf to the resulting value.
990 */
991static xmlChar*
992xmlSchemaFormatItemForReport(xmlChar **buf,
993 const xmlChar *itemDes,
994 xmlSchemaTypePtr item,
995 xmlNodePtr itemNode,
996 int parsing)
997{
998 xmlChar *str = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +0000999 int named = 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001000
1001 if (*buf != NULL) {
1002 xmlFree(*buf);
1003 *buf = NULL;
1004 }
1005
William M. Brack2f2a6632004-08-20 23:09:47 +00001006 if (itemDes != NULL) {
1007 *buf = xmlStrdup(itemDes);
1008 } else if (item != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001009 switch (item->type) {
1010 case XML_SCHEMA_TYPE_BASIC:
Daniel Veillardc0826a72004-08-10 14:17:33 +00001011 if (item->builtInType == XML_SCHEMAS_ANYTYPE)
1012 *buf = xmlStrdup(BAD_CAST "'anyType'");
1013 else if (item->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)
1014 *buf = xmlStrdup(BAD_CAST "'anySimpleType'");
1015 else {
1016 /* *buf = xmlStrdup(BAD_CAST "bi "); */
1017 /* *buf = xmlStrcat(*buf, xmlSchemaElemDesST); */
1018 *buf = xmlStrdup(BAD_CAST "'");
1019 *buf = xmlStrcat(*buf, item->name);
1020 *buf = xmlStrcat(*buf, BAD_CAST "'");
1021 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001022 break;
1023 case XML_SCHEMA_TYPE_SIMPLE:
Daniel Veillardc0826a72004-08-10 14:17:33 +00001024 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1025 *buf = xmlStrdup(xmlSchemaElemDesST);
1026 *buf = xmlStrcat(*buf, BAD_CAST " '");
1027 *buf = xmlStrcat(*buf, item->name);
1028 *buf = xmlStrcat(*buf, BAD_CAST "'");
1029 } else {
1030 *buf = xmlStrdup(xmlSchemaElemDesST);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001031 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001032 break;
1033 case XML_SCHEMA_TYPE_COMPLEX:
Daniel Veillardc0826a72004-08-10 14:17:33 +00001034 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1035 *buf = xmlStrdup(xmlSchemaElemDesCT);
1036 *buf = xmlStrcat(*buf, BAD_CAST " '");
1037 *buf = xmlStrcat(*buf, item->name);
1038 *buf = xmlStrcat(*buf, BAD_CAST "'");
1039 } else {
1040 *buf = xmlStrdup(xmlSchemaElemDesCT);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001041 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001042 break;
1043 case XML_SCHEMA_TYPE_ATTRIBUTE: {
1044 xmlSchemaAttributePtr attr;
1045
1046 attr = (xmlSchemaAttributePtr) item;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001047 if ((attr->flags & XML_SCHEMAS_ATTR_GLOBAL) ||
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001048 (attr->ref == NULL)) {
1049 *buf = xmlStrdup(xmlSchemaElemDesAttrDecl);
1050 *buf = xmlStrcat(*buf, BAD_CAST " '");
1051 *buf = xmlStrcat(*buf, attr->name);
1052 *buf = xmlStrcat(*buf, BAD_CAST "'");
1053 } else {
1054 *buf = xmlStrdup(xmlSchemaElemDesAttrRef);
1055 *buf = xmlStrcat(*buf, BAD_CAST " '");
1056 *buf = xmlStrcat(*buf, attr->refPrefix);
1057 *buf = xmlStrcat(*buf, BAD_CAST ":");
1058 *buf = xmlStrcat(*buf, attr->ref);
1059 *buf = xmlStrcat(*buf, BAD_CAST "'");
1060 }
1061 }
1062 break;
1063 case XML_SCHEMA_TYPE_ELEMENT: {
1064 xmlSchemaElementPtr elem;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001065
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001066 elem = (xmlSchemaElementPtr) item;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001067 if ((elem->flags & XML_SCHEMAS_ELEM_GLOBAL) ||
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001068 (elem->ref == NULL)) {
1069 *buf = xmlStrdup(xmlSchemaElemDesElemDecl);
1070 *buf = xmlStrcat(*buf, BAD_CAST " '");
1071 *buf = xmlStrcat(*buf, elem->name);
1072 *buf = xmlStrcat(*buf, BAD_CAST "'");
1073 } else {
1074 *buf = xmlStrdup(xmlSchemaElemDesElemRef);
1075 *buf = xmlStrcat(*buf, BAD_CAST " '");
1076 *buf = xmlStrcat(*buf, elem->refPrefix);
1077 *buf = xmlStrcat(*buf, BAD_CAST ":");
1078 *buf = xmlStrcat(*buf, elem->ref);
1079 *buf = xmlStrcat(*buf, BAD_CAST "'");
1080 }
1081 }
1082 break;
1083 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1084 case XML_SCHEMA_TYPE_IDC_KEY:
1085 case XML_SCHEMA_TYPE_IDC_KEYREF:
1086 if (item->type == XML_SCHEMA_TYPE_IDC_UNIQUE)
1087 *buf = xmlStrdup(BAD_CAST "unique '");
1088 else if (item->type == XML_SCHEMA_TYPE_IDC_KEY)
1089 *buf = xmlStrdup(BAD_CAST "key '");
1090 else
1091 *buf = xmlStrdup(BAD_CAST "keyRef '");
1092 *buf = xmlStrcat(*buf, ((xmlSchemaIDCPtr) item)->name);
1093 *buf = xmlStrcat(*buf, BAD_CAST "'");
1094 break;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00001095 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001096 *buf = xmlStrdup(xmlSchemaWildcardPCToString(
1097 ((xmlSchemaWildcardPtr) item)->processContents));
1098 *buf = xmlStrcat(*buf, BAD_CAST " wildcard");
1099 break;
1100 case XML_SCHEMA_FACET_MININCLUSIVE:
1101 case XML_SCHEMA_FACET_MINEXCLUSIVE:
1102 case XML_SCHEMA_FACET_MAXINCLUSIVE:
1103 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
1104 case XML_SCHEMA_FACET_TOTALDIGITS:
1105 case XML_SCHEMA_FACET_FRACTIONDIGITS:
1106 case XML_SCHEMA_FACET_PATTERN:
1107 case XML_SCHEMA_FACET_ENUMERATION:
1108 case XML_SCHEMA_FACET_WHITESPACE:
1109 case XML_SCHEMA_FACET_LENGTH:
1110 case XML_SCHEMA_FACET_MAXLENGTH:
1111 case XML_SCHEMA_FACET_MINLENGTH:
1112 *buf = xmlStrdup(BAD_CAST "facet '");
1113 *buf = xmlStrcat(*buf, xmlSchemaFacetTypeToString(item->type));
1114 *buf = xmlStrcat(*buf, BAD_CAST "'");
1115 break;
1116 case XML_SCHEMA_TYPE_NOTATION:
1117 *buf = xmlStrdup(BAD_CAST "notation");
1118 break;
1119 case XML_SCHEMA_TYPE_GROUP:
1120 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1121 *buf = xmlStrdup(xmlSchemaElemModelGrDef);
1122 *buf = xmlStrcat(*buf, BAD_CAST " '");
1123 *buf = xmlStrcat(*buf, item->name);
1124 *buf = xmlStrcat(*buf, BAD_CAST "'");
1125 } else {
1126 *buf = xmlStrdup(xmlSchemaElemModelGrRef);
1127 *buf = xmlStrcat(*buf, BAD_CAST " '");
1128 *buf = xmlStrcat(*buf, item->ref);
1129 *buf = xmlStrcat(*buf, BAD_CAST "'");
1130 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00001131 break;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001132 default:
William M. Brack2f2a6632004-08-20 23:09:47 +00001133 named = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001134 }
William M. Brack2f2a6632004-08-20 23:09:47 +00001135 } else
1136 named = 0;
1137
1138 if ((named == 0) && (itemNode != NULL)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00001139 xmlNodePtr elem;
1140
1141 if (itemNode->type == XML_ATTRIBUTE_NODE)
1142 elem = itemNode->parent;
1143 else
1144 elem = itemNode;
1145 *buf = xmlStrdup(BAD_CAST "Element '");
1146 if (parsing)
1147 *buf = xmlStrcat(*buf, elem->name);
1148 else
1149 *buf = xmlStrcat(*buf,
1150 xmlSchemaFormatNsPrefixLocal(&str, elem->ns, elem->name));
1151 *buf = xmlStrcat(*buf, BAD_CAST "'");
1152 }
1153 if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
1154 *buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
1155 *buf = xmlStrcat(*buf, xmlSchemaFormatNsPrefixLocal(&str,
1156 itemNode->ns, itemNode->name));
1157 *buf = xmlStrcat(*buf, BAD_CAST "'");
1158 }
1159 FREE_AND_NULL(str);
1160
1161 return (*buf);
1162}
1163
1164/**
1165 * xmlSchemaPFormatItemDes:
1166 * @buf: the string buffer
1167 * @item: the item as a schema object
1168 * @itemNode: the item as a node
1169 *
1170 * If the pointer to @buf is not NULL and @but holds no value,
1171 * the value is set to a item designation using
1172 * xmlSchemaFormatItemForReport. This one avoids adding
1173 * an attribute designation postfix.
1174 *
1175 * Returns a string of all enumeration elements.
1176 */
1177static void
1178xmlSchemaPRequestItemDes(xmlChar **buf,
1179 xmlSchemaTypePtr item,
1180 xmlNodePtr itemNode)
1181{
1182 if ((buf == 0) || (*buf != NULL))
1183 return;
1184 if (itemNode->type == XML_ATTRIBUTE_NODE)
1185 itemNode = itemNode->parent;
1186 xmlSchemaFormatItemForReport(buf, NULL, item, itemNode, 1);
1187}
1188
1189/**
1190 * xmlSchemaFormatFacetEnumSet:
1191 * @buf: the string buffer
1192 * @type: the type holding the enumeration facets
1193 *
1194 * Builds a string consisting of all enumeration elements.
1195 *
1196 * Returns a string of all enumeration elements.
1197 */
1198static const xmlChar *
1199xmlSchemaFormatFacetEnumSet(xmlChar **buf, xmlSchemaTypePtr type)
1200{
1201 xmlSchemaFacetLinkPtr link;
1202
1203 if (*buf != NULL)
1204 xmlFree(*buf);
1205 *buf = NULL;
1206 for (link = type->facetSet; link != NULL; link = link->next) {
1207 if (link->facet->type == XML_SCHEMA_FACET_ENUMERATION) {
1208 if (*buf == NULL) {
1209 *buf = xmlStrdup(BAD_CAST "'");
1210 *buf = xmlStrcat(*buf, link->facet->value);
1211 *buf = xmlStrcat(*buf, BAD_CAST "'");
1212 } else {
1213 *buf = xmlStrcat(*buf, BAD_CAST ", '");
1214 *buf = xmlStrcat(*buf, link->facet->value);
1215 *buf = xmlStrcat(*buf, BAD_CAST "'");
1216 }
1217 }
1218 }
1219 return ((const xmlChar *) *buf);
1220}
1221
1222/**
1223 * xmlSchemaVFacetErr:
1224 * @ctxt: the schema validation context
1225 * @error: the error code
1226 * @node: the node to be validated
1227 * @value: the value of the node
1228 * @type: the type holding the facet
1229 * @facet: the facet
1230 * @message: the error message of NULL
1231 * @str1: extra data
1232 * @str2: extra data
1233 * @str3: extra data
1234 *
1235 * Reports a facet validation error.
1236 * TODO: Should this report the value of an element as well?
1237 */
1238static void
1239xmlSchemaVFacetErr(xmlSchemaValidCtxtPtr ctxt,
1240 xmlParserErrors error,
1241 xmlNodePtr node,
1242 const xmlChar *value,
1243 unsigned long length,
1244 xmlSchemaTypePtr type,
1245 xmlSchemaFacetPtr facet,
1246 const char *message,
1247 const xmlChar *str1,
1248 const xmlChar *str2,
1249 const xmlChar *str3)
1250{
1251 xmlChar *str = NULL, *msg = NULL;
1252 xmlSchemaTypeType facetType;
1253
1254 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
1255 msg = xmlStrcat(msg, BAD_CAST " [");
1256 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1257 msg = xmlStrcat(msg, BAD_CAST ", facet '");
1258 if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
1259 facetType = XML_SCHEMA_FACET_ENUMERATION;
1260 /*
1261 * If enumerations are validated, one must not expect the
1262 * facet to be given.
1263 */
1264 } else
1265 facetType = facet->type;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001266 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facetType));
Daniel Veillardc0826a72004-08-10 14:17:33 +00001267 msg = xmlStrcat(msg, BAD_CAST "']: ");
1268 if (message == NULL) {
1269 /*
1270 * Use a default message.
1271 */
1272 if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
1273 (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
1274 (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
1275
1276 char len[25], actLen[25];
1277
1278 /* FIXME, TODO: What is the max expected string length of the
1279 * this value?
1280 */
1281 if (node->type == XML_ATTRIBUTE_NODE)
1282 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
1283 else
1284 msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
1285
1286 snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
1287 snprintf(actLen, 24, "%lu", length);
1288
1289 if (facetType == XML_SCHEMA_FACET_LENGTH)
1290 msg = xmlStrcat(msg,
1291 BAD_CAST "this differs from the allowed length of '%s'.\n");
1292 else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
1293 msg = xmlStrcat(msg,
1294 BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
1295 else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
1296 msg = xmlStrcat(msg,
1297 BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
1298
1299 if (node->type == XML_ATTRIBUTE_NODE)
1300 xmlSchemaVErrExt(ctxt, node, error,
1301 (const char *) msg,
1302 value, (const xmlChar *) actLen, (const xmlChar *) len,
1303 NULL, NULL);
1304 else
1305 xmlSchemaVErr(ctxt, node, error,
1306 (const char *) msg,
1307 (const xmlChar *) actLen, (const xmlChar *) len);
1308
1309 } else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
1310 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
1311 "of the set {%s}.\n");
1312 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
1313 xmlSchemaFormatFacetEnumSet(&str, type));
1314 } else if (facetType == XML_SCHEMA_FACET_PATTERN) {
1315 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
1316 "by the pattern '%s'.\n");
1317 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
1318 facet->value);
1319 } else if (node->type == XML_ATTRIBUTE_NODE) {
1320 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
1321 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value, NULL);
1322 } else {
1323 msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
1324 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
1325 }
1326 } else {
1327 msg = xmlStrcat(msg, (const xmlChar *) message);
1328 msg = xmlStrcat(msg, BAD_CAST ".\n");
1329 xmlSchemaVErr3(ctxt, node, error, (const char *) msg, str1, str2, str3);
1330 }
1331 FREE_AND_NULL(str)
1332 xmlFree(msg);
1333}
1334
1335/**
1336 * xmlSchemaVSimpleTypeErr:
1337 * @ctxt: the schema validation context
1338 * @error: the error code
1339 * @type: the type used for validation
1340 * @node: the node containing the validated value
1341 * @value: the validated value
1342 *
1343 * Reports a simple type validation error.
1344 * TODO: Should this report the value of an element as well?
1345 */
1346static void
1347xmlSchemaVSimpleTypeErr(xmlSchemaValidCtxtPtr ctxt,
1348 xmlParserErrors error,
1349 xmlNodePtr node,
1350 const xmlChar *value,
1351 xmlSchemaTypePtr type)
1352{
1353 xmlChar *str = NULL, *msg = NULL;
1354
1355 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
1356 msg = xmlStrcat(msg, BAD_CAST " [");
1357 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1358 if (node->type == XML_ATTRIBUTE_NODE) {
1359 msg = xmlStrcat(msg, BAD_CAST "]: The value '%s' is not valid.\n");
1360 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value, NULL);
1361 } else {
1362 msg = xmlStrcat(msg, BAD_CAST "]: The character content is not valid.\n");
1363 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
1364 }
1365 FREE_AND_NULL(str)
1366 xmlFree(msg);
1367}
1368
1369/**
William M. Brack2f2a6632004-08-20 23:09:47 +00001370 * xmlSchemaVComplexTypeErr:
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
1380xmlSchemaVComplexTypeErr(xmlSchemaValidCtxtPtr ctxt,
1381 xmlParserErrors error,
1382 xmlNodePtr node,
1383 xmlSchemaTypePtr type,
1384 const char *message)
1385{
1386 xmlChar *str = NULL, *msg = NULL;
1387
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00001388 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00001389 /* Specify the complex type only if it is global. */
1390 if ((type != NULL) && (type->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00001391 msg = xmlStrcat(msg, BAD_CAST " [");
1392 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1393 msg = xmlStrcat(msg, BAD_CAST "]");
1394 }
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001395 msg = xmlStrcat(msg, BAD_CAST ": %s.\n");
1396 xmlSchemaVErr(ctxt, node, error, (const char *) msg,
William M. Brack2f2a6632004-08-20 23:09:47 +00001397 (const xmlChar *) message, NULL);
1398 FREE_AND_NULL(str)
1399 xmlFree(msg);
1400}
1401
1402/**
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001403 * xmlSchemaVComplexTypeElemErr:
1404 * @ctxt: the schema validation context
1405 * @error: the error code
1406 * @node: the node containing the validated value
1407 * @type: the complex type used for validation
1408 * @message: the error message
1409 *
1410 * Reports a complex type validation error.
1411 */
1412static void
1413xmlSchemaVComplexTypeElemErr(xmlSchemaValidCtxtPtr ctxt,
1414 xmlParserErrors error,
1415 xmlNodePtr node,
1416 xmlSchemaTypePtr type,
1417 const char *message,
1418 int nbval,
1419 int nbneg,
1420 xmlChar **values)
1421{
1422 xmlChar *str = NULL, *msg = NULL;
1423 xmlChar *localName, *nsName;
1424 const xmlChar *cur, *end;
1425 int i;
1426
1427 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
1428 /* Specify the complex type only if it is global. */
1429 if ((type != NULL) && (type->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
1430 msg = xmlStrcat(msg, BAD_CAST " [");
1431 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1432 msg = xmlStrcat(msg, BAD_CAST "]");
1433 FREE_AND_NULL(str)
1434 }
1435 msg = xmlStrcat(msg, BAD_CAST ": ");
1436 msg = xmlStrcat(msg, (const xmlChar *) message);
1437 /*
1438 * Note that is does not make sense to report that we have a
1439 * wildcard here, since the wildcard might be unfolded into
1440 * multiple transitions.
1441 */
1442 if (nbval + nbneg > 0) {
1443 if (nbval + nbneg > 1) {
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00001444 str = xmlStrdup(BAD_CAST ". Expected is one of ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001445 } else
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00001446 str = xmlStrdup(BAD_CAST ". Expected is ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001447 nsName = NULL;
1448
1449 for (i = 0; i < nbval + nbneg; i++) {
1450 cur = values[i];
1451 /*
1452 * Get the local name.
1453 */
1454 localName = NULL;
1455
1456 end = cur;
1457 if (*end == '*') {
1458 localName = xmlStrdup(BAD_CAST "*");
1459 *end++;
1460 } else {
1461 while ((*end != 0) && (*end != '|'))
1462 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001463 localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001464 }
1465 if (*end != 0) {
1466 *end++;
1467 /*
1468 * Skip "*|*" if they come with negated expressions, since
1469 * they represent the same negated wildcard.
1470 */
1471 if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
1472 /*
1473 * Get the namespace name.
1474 */
1475 cur = end;
1476 if (*end == '*') {
1477 nsName = xmlStrdup(BAD_CAST "{*}");
1478 } else {
1479 while (*end != 0)
1480 end++;
1481
1482 if (i >= nbval)
1483 nsName = xmlStrdup(BAD_CAST "{##other:");
1484 else
1485 nsName = xmlStrdup(BAD_CAST "{");
1486
1487 nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
1488 nsName = xmlStrcat(nsName, BAD_CAST "}");
1489 }
1490 str = xmlStrcat(str, BAD_CAST nsName);
1491 FREE_AND_NULL(nsName)
1492 } else {
1493 FREE_AND_NULL(localName);
1494 continue;
1495 }
1496 }
1497 str = xmlStrcat(str, BAD_CAST localName);
1498 FREE_AND_NULL(localName);
1499
1500 if (i < nbval + nbneg -1)
1501 str = xmlStrcat(str, BAD_CAST ", ");
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00001502 }
1503 str = xmlStrcat(str, BAD_CAST " )");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001504 msg = xmlStrcat(msg, BAD_CAST str);
1505 FREE_AND_NULL(str)
1506 }
1507 msg = xmlStrcat(msg, BAD_CAST ".\n");
1508 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
1509 xmlFree(msg);
1510}
1511
1512/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00001513 * xmlSchemaPMissingAttrErr:
1514 * @ctxt: the schema validation context
1515 * @ownerDes: the designation of the owner
1516 * @ownerName: the name of the owner
1517 * @ownerItem: the owner as a schema object
1518 * @ownerElem: the owner as an element node
1519 * @node: the parent element node of the missing attribute node
1520 * @type: the corresponding type of the attribute node
1521 *
1522 * Reports an illegal attribute.
1523 */
1524static void
1525xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
1526 xmlParserErrors error,
1527 xmlChar **ownerDes,
1528 xmlSchemaTypePtr ownerItem,
1529 xmlNodePtr ownerElem,
1530 const char *name,
1531 const char *message)
1532{
1533 xmlChar *des = NULL;
1534
1535 if (ownerDes == NULL)
1536 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
1537 else if (*ownerDes == NULL) {
1538 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
1539 des = *ownerDes;
1540 } else
1541 des = *ownerDes;
1542 if (message != NULL)
1543 xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
1544 else
1545 xmlSchemaPErr(ctxt, ownerElem, error,
1546 "%s: The attribute '%s' is required but missing.\n",
1547 BAD_CAST des, BAD_CAST name);
1548 if (ownerDes == NULL)
1549 FREE_AND_NULL(des);
1550}
1551
William M. Brack2f2a6632004-08-20 23:09:47 +00001552/**
1553 * xmlSchemaCompTypeToString:
1554 * @type: the type of the schema item
1555 *
1556 * Returns the component name of a schema item.
1557 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001558static const char *
1559xmlSchemaCompTypeToString(xmlSchemaTypeType type)
1560{
1561 switch (type) {
1562 case XML_SCHEMA_TYPE_SIMPLE:
1563 return("simple type definition");
1564 case XML_SCHEMA_TYPE_COMPLEX:
1565 return("complex type definition");
1566 case XML_SCHEMA_TYPE_ELEMENT:
1567 return("element declaration");
1568 case XML_SCHEMA_TYPE_ATTRIBUTE:
1569 return("attribute declaration");
1570 case XML_SCHEMA_TYPE_GROUP:
1571 return("model group definition");
1572 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1573 return("attribute group definition");
1574 case XML_SCHEMA_TYPE_NOTATION:
1575 return("notation declaration");
1576 default:
1577 return("Not a schema component");
1578 }
1579}
1580/**
1581 * xmlSchemaPResCompAttrErr:
1582 * @ctxt: the schema validation context
1583 * @error: the error code
1584 * @ownerDes: the designation of the owner
1585 * @ownerItem: the owner as a schema object
1586 * @ownerElem: the owner as an element node
1587 * @name: the name of the attribute holding the QName
1588 * @refName: the referenced local name
1589 * @refURI: the referenced namespace URI
1590 * @message: optional message
1591 *
1592 * Used to report QName attribute values that failed to resolve
1593 * to schema components.
1594 */
1595static void
1596xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
1597 xmlParserErrors error,
1598 xmlChar **ownerDes,
1599 xmlSchemaTypePtr ownerItem,
1600 xmlNodePtr ownerElem,
1601 const char *name,
1602 const xmlChar *refName,
1603 const xmlChar *refURI,
1604 xmlSchemaTypeType refType,
1605 const char *refTypeStr)
1606{
1607 xmlChar *des = NULL, *strA = NULL;
1608
1609 if (ownerDes == NULL)
1610 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
1611 else if (*ownerDes == NULL) {
1612 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
1613 des = *ownerDes;
1614 } else
1615 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001616 if (refTypeStr == NULL)
1617 refTypeStr = xmlSchemaCompTypeToString(refType);
1618 xmlSchemaPErrExt(ctxt, ownerElem, error,
1619 NULL, NULL, NULL,
1620 "%s, attribute '%s': The QName value %s does not resolve to a(n) "
1621 "%s.\n", BAD_CAST des, BAD_CAST name,
1622 xmlSchemaFormatNsUriLocal(&strA, refURI, refName),
1623 BAD_CAST refTypeStr, NULL);
1624 if (ownerDes == NULL)
1625 FREE_AND_NULL(des)
1626 FREE_AND_NULL(strA)
1627}
1628
William M. Brack2f2a6632004-08-20 23:09:47 +00001629/**
1630 * xmlSchemaPCustomAttrErr:
1631 * @ctxt: the schema parser context
1632 * @error: the error code
1633 * @ownerDes: the designation of the owner
1634 * @ownerItem: the owner as a schema object
1635 * @attr: the illegal attribute node
1636 *
1637 * Reports an illegal attribute during the parse.
1638 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001639static void
1640xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00001641 xmlParserErrors error,
1642 xmlChar **ownerDes,
1643 xmlSchemaTypePtr ownerItem,
1644 xmlAttrPtr attr,
1645 const char *msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001646{
1647 xmlChar *des = 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 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
1657 "%s, attribute '%s': %s.\n",
1658 BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
1659 if (ownerDes == NULL)
1660 FREE_AND_NULL(des);
1661}
1662
1663/**
1664 * xmlSchemaPIllegalAttrErr:
William M. Brack2f2a6632004-08-20 23:09:47 +00001665 * @ctxt: the schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00001666 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00001667 * @ownerDes: the designation of the attribute's owner
1668 * @ownerItem: the attribute's owner item
Daniel Veillardc0826a72004-08-10 14:17:33 +00001669 * @attr: the illegal attribute node
1670 *
William M. Brack2f2a6632004-08-20 23:09:47 +00001671 * Reports an illegal attribute during the parse.
Daniel Veillardc0826a72004-08-10 14:17:33 +00001672 */
1673static void
1674xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
1675 xmlParserErrors error,
1676 xmlChar **ownerDes,
1677 xmlSchemaTypePtr ownerItem,
1678 xmlAttrPtr attr)
1679{
1680 xmlChar *des = NULL, *strA = NULL;
1681
1682 if (ownerDes == NULL)
1683 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
1684 else if (*ownerDes == NULL) {
1685 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
1686 des = *ownerDes;
1687 } else
1688 des = *ownerDes;
1689 xmlSchemaPErr(ctxt, (xmlNodePtr) attr, error,
1690 "%s: The attribute '%s' is not allowed.\n", BAD_CAST des,
1691 xmlSchemaFormatNsPrefixLocal(&strA, attr->ns, attr->name));
1692 if (ownerDes == NULL)
1693 FREE_AND_NULL(des);
1694 FREE_AND_NULL(strA);
1695}
1696
William M. Brack2f2a6632004-08-20 23:09:47 +00001697/**
1698 * xmlSchemaPAquireDes:
1699 * @des: the first designation
1700 * @itemDes: the second designation
1701 * @item: the schema item
1702 * @itemElem: the node of the schema item
1703 *
1704 * Creates a designation for an item.
1705 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001706static void
1707xmlSchemaPAquireDes(xmlChar **des,
1708 xmlChar **itemDes,
1709 xmlSchemaTypePtr item,
1710 xmlNodePtr itemElem)
1711{
1712 if (itemDes == NULL)
1713 xmlSchemaFormatItemForReport(des, NULL, item, itemElem, 1);
1714 else if (*itemDes == NULL) {
1715 xmlSchemaFormatItemForReport(itemDes, NULL, item, itemElem, 1);
1716 *des = *itemDes;
1717 } else
1718 *des = *itemDes;
1719}
1720
William M. Brack2f2a6632004-08-20 23:09:47 +00001721/**
1722 * xmlSchemaPCustomErr:
1723 * @ctxt: the schema parser context
1724 * @error: the error code
1725 * @itemDes: the designation of the schema item
1726 * @item: the schema item
1727 * @itemElem: the node of the schema item
1728 * @message: the error message
1729 * @str1: an optional param for the error message
1730 * @str2: an optional param for the error message
1731 * @str3: an optional param for the error message
1732 *
1733 * Reports an error during parsing.
1734 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001735static void
1736xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
1737 xmlParserErrors error,
1738 xmlChar **itemDes,
1739 xmlSchemaTypePtr item,
1740 xmlNodePtr itemElem,
1741 const char *message,
1742 const xmlChar *str1,
1743 const xmlChar *str2,
1744 const xmlChar *str3)
1745{
1746 xmlChar *des = NULL, *msg = NULL;
1747
1748 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
1749 msg = xmlStrdup(BAD_CAST "%s: ");
1750 msg = xmlStrcat(msg, (const xmlChar *) message);
1751 msg = xmlStrcat(msg, BAD_CAST ".\n");
1752 if ((itemElem == NULL) && (item != NULL))
1753 itemElem = item->node;
1754 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
1755 (const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
1756 if (itemDes == NULL)
1757 FREE_AND_NULL(des);
1758 FREE_AND_NULL(msg);
1759}
1760
William M. Brack2f2a6632004-08-20 23:09:47 +00001761/**
1762 * xmlSchemaPCustomErr:
1763 * @ctxt: the schema parser context
1764 * @error: the error code
1765 * @itemDes: the designation of the schema item
1766 * @item: the schema item
1767 * @itemElem: the node of the schema item
1768 * @message: the error message
1769 * @str1: the optional param for the error message
1770 *
1771 * Reports an error during parsing.
1772 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001773static void
1774xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
1775 xmlParserErrors error,
1776 xmlChar **itemDes,
1777 xmlSchemaTypePtr item,
1778 xmlNodePtr itemElem,
1779 const char *message,
1780 const xmlChar *str1)
1781{
1782 xmlSchemaPCustomErrExt(ctxt, error, itemDes, item, itemElem, message,
1783 str1, NULL, NULL);
1784}
1785
William M. Brack2f2a6632004-08-20 23:09:47 +00001786/**
1787 * xmlSchemaPAttrUseErr:
1788 * @ctxt: the schema parser context
1789 * @error: the error code
1790 * @itemDes: the designation of the schema type
1791 * @item: the schema type
1792 * @itemElem: the node of the schema type
1793 * @attr: the invalid schema attribute
1794 * @message: the error message
1795 * @str1: the optional param for the error message
1796 *
1797 * Reports an attribute use error during parsing.
1798 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001799static void
1800xmlSchemaPAttrUseErr(xmlSchemaParserCtxtPtr ctxt,
1801 xmlParserErrors error,
1802 xmlChar **itemDes,
1803 xmlSchemaTypePtr item,
1804 xmlNodePtr itemElem,
1805 const xmlSchemaAttributePtr attr,
1806 const char *message,
1807 const xmlChar *str1)
1808{
1809 xmlChar *des = NULL, *strA = NULL, *msg = NULL;
1810
1811 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
1812 xmlSchemaFormatNsUriLocal(&strA, xmlSchemaGetAttrTargetNsURI(attr),
1813 xmlSchemaGetAttrName(attr));
1814 msg = xmlStrdup(BAD_CAST "%s, attr. use %s: ");
1815 msg = xmlStrcat(msg, (const xmlChar *) message);
1816 msg = xmlStrcat(msg, BAD_CAST ".\n");
1817 if ((itemElem == NULL) && (item != NULL))
1818 itemElem = item->node;
1819 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
1820 (const char *) msg, BAD_CAST des, BAD_CAST strA, str1, NULL, NULL);
1821 if (itemDes == NULL)
1822 FREE_AND_NULL(des);
1823 FREE_AND_NULL(strA);
1824 xmlFree(msg);
1825}
1826
William M. Brack2f2a6632004-08-20 23:09:47 +00001827/**
1828 * xmlSchemaPIllegalFacetAtomicErr:
1829 * @ctxt: the schema parser context
1830 * @error: the error code
1831 * @itemDes: the designation of the type
1832 * @item: the schema type
1833 * @baseItem: the base type of type
1834 * @facet: the illegal facet
1835 *
1836 * Reports an illegal facet for atomic simple types.
1837 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001838static void
1839xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
1840 xmlParserErrors error,
1841 xmlChar **itemDes,
1842 xmlSchemaTypePtr item,
1843 xmlSchemaTypePtr baseItem,
1844 xmlSchemaFacetPtr facet)
1845{
1846 xmlChar *des = NULL, *strT = NULL;
1847
1848 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
1849 xmlSchemaPErrExt(ctxt, item->node, error, NULL, NULL, NULL,
1850 "%s: The facet '%s' is not allowed on types derived from the "
1851 "type %s.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001852 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type),
Daniel Veillardc0826a72004-08-10 14:17:33 +00001853 xmlSchemaFormatItemForReport(&strT, NULL, baseItem, NULL, 1),
1854 NULL, NULL);
1855 if (itemDes == NULL)
1856 FREE_AND_NULL(des);
1857 FREE_AND_NULL(strT);
1858}
1859
William M. Brack2f2a6632004-08-20 23:09:47 +00001860/**
1861 * xmlSchemaPIllegalFacetListUnionErr:
1862 * @ctxt: the schema parser context
1863 * @error: the error code
1864 * @itemDes: the designation of the schema item involved
1865 * @item: the schema item involved
1866 * @facet: the illegal facet
1867 *
1868 * Reports an illegal facet for <list> and <union>.
1869 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001870static void
1871xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
1872 xmlParserErrors error,
1873 xmlChar **itemDes,
1874 xmlSchemaTypePtr item,
1875 xmlSchemaFacetPtr facet)
1876{
1877 xmlChar *des = NULL, *strT = NULL;
1878
1879 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
1880 xmlSchemaPErr(ctxt, item->node, error,
1881 "%s: The facet '%s' is not allowed.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001882 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +00001883 if (itemDes == NULL)
1884 FREE_AND_NULL(des);
1885 FREE_AND_NULL(strT);
1886}
1887
1888/**
1889 * xmlSchemaPMutualExclAttrErr:
1890 * @ctxt: the schema validation context
1891 * @error: the error code
1892 * @elemDes: the designation of the parent element node
1893 * @attr: the bad attribute node
1894 * @type: the corresponding type of the attribute node
1895 *
1896 * Reports an illegal attribute.
1897 */
1898static void
1899xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
1900 xmlParserErrors error,
1901 xmlChar **ownerDes,
1902 xmlSchemaTypePtr ownerItem,
1903 xmlAttrPtr attr,
1904 const char *name1,
1905 const char *name2)
1906{
1907 xmlChar *des = NULL;
1908
1909 if (ownerDes == NULL)
1910 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
1911 else if (*ownerDes == NULL) {
1912 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
1913 des = *ownerDes;
1914 } else
1915 des = *ownerDes;
1916 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
1917 "%s: The attributes '%s' and '%s' are mutually exclusive.\n",
1918 BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
1919 if (ownerDes == NULL)
1920 FREE_AND_NULL(des)
1921}
1922
1923/**
1924 * xmlSchemaPSimpleTypeErr:
1925 * @ctxt: the schema validation context
1926 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00001927 * @type: the type specifier
Daniel Veillardc0826a72004-08-10 14:17:33 +00001928 * @ownerDes: the designation of the owner
1929 * @ownerItem: the schema object if existent
1930 * @node: the validated node
1931 * @value: the validated value
1932 *
1933 * Reports a simple type validation error.
1934 * TODO: Should this report the value of an element as well?
1935 */
1936static void
1937xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
1938 xmlParserErrors error,
1939 xmlChar **ownerDes,
1940 xmlSchemaTypePtr ownerItem,
1941 xmlNodePtr node,
William M. Brack2f2a6632004-08-20 23:09:47 +00001942 xmlSchemaTypePtr type,
Daniel Veillardc0826a72004-08-10 14:17:33 +00001943 const char *typeDes,
1944 const xmlChar *value,
1945 const char *message,
1946 const xmlChar *str1,
1947 const xmlChar *str2)
1948{
William M. Brack2f2a6632004-08-20 23:09:47 +00001949 xmlChar *des = NULL, *strA = NULL, *strT = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001950
1951 if (ownerDes == NULL)
1952 xmlSchemaPRequestItemDes(&des, ownerItem, node);
1953 else if (*ownerDes == NULL) {
1954 xmlSchemaPRequestItemDes(ownerDes, ownerItem, node);
1955 des = *ownerDes;
1956 } else
1957 des = *ownerDes;
William M. Brack2f2a6632004-08-20 23:09:47 +00001958 if (type != NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001959 typeDes = (const char *) xmlSchemaFormatItemForReport(&strT, NULL, type, NULL, 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001960 if (message == NULL) {
1961 /*
1962 * Use default messages.
1963 */
1964 if (node->type == XML_ATTRIBUTE_NODE) {
1965 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
1966 "%s, attribute '%s' [%s]: The value '%s' is not "
1967 "valid.\n",
1968 BAD_CAST des, xmlSchemaFormatNsPrefixLocal(&strA, node->ns,
1969 node->name), BAD_CAST typeDes, value, NULL);
1970 } else {
1971 xmlSchemaPErr(ctxt, node, error,
1972 "%s [%s]: The character content is not valid.\n",
1973 BAD_CAST des, BAD_CAST typeDes);
1974 }
1975 } else {
1976 xmlChar *msg;
1977
1978 msg = xmlStrdup(BAD_CAST "%s");
1979 if (node->type == XML_ATTRIBUTE_NODE)
1980 msg = xmlStrcat(msg, BAD_CAST ", attribute '%s'");
1981 msg = xmlStrcat(msg, BAD_CAST " [%s]: ");
1982 msg = xmlStrcat(msg, (const xmlChar *) message);
1983 msg = xmlStrcat(msg, BAD_CAST ".\n");
1984 if (node->type == XML_ATTRIBUTE_NODE) {
1985 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
1986 (const char *) msg,
1987 BAD_CAST des, xmlSchemaFormatNsPrefixLocal(&strA,
1988 node->ns, node->name), BAD_CAST typeDes, str1, str2);
1989 } else {
1990 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
1991 (const char *) msg,
1992 BAD_CAST des, BAD_CAST typeDes, str1, str2, NULL);
1993 }
1994 xmlFree(msg);
1995 }
1996 /* Cleanup. */
1997 FREE_AND_NULL(strA)
1998 FREE_AND_NULL(strT)
1999 if (ownerDes == NULL)
2000 FREE_AND_NULL(des)
2001}
2002
William M. Brack2f2a6632004-08-20 23:09:47 +00002003/**
2004 * xmlSchemaPContentErr:
2005 * @ctxt: the schema parser context
2006 * @error: the error code
2007 * @onwerDes: the designation of the holder of the content
2008 * @ownerItem: the owner item of the holder of the content
2009 * @ownerElem: the node of the holder of the content
2010 * @child: the invalid child node
2011 * @message: the optional error message
2012 * @content: the optional string describing the correct content
2013 *
2014 * Reports an error concerning the content of a schema element.
2015 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002016static void
2017xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
2018 xmlParserErrors error,
2019 xmlChar **ownerDes,
2020 xmlSchemaTypePtr ownerItem,
2021 xmlNodePtr ownerElem,
2022 xmlNodePtr child,
2023 const char *message,
2024 const char *content)
2025{
2026 xmlChar *des = NULL;
2027
2028 if (ownerDes == NULL)
2029 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
2030 else if (*ownerDes == NULL) {
2031 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
2032 des = *ownerDes;
2033 } else
2034 des = *ownerDes;
2035 if (message != NULL)
2036 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2037 "%s: %s.\n",
2038 BAD_CAST des, BAD_CAST message);
2039 else {
2040 if (content != NULL) {
2041 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2042 "%s: The content is not valid. Expected is %s.\n",
2043 BAD_CAST des, BAD_CAST content);
2044 } else {
2045 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2046 "%s: The content is not valid.\n",
2047 BAD_CAST des, NULL);
2048 }
2049 }
2050 if (ownerDes == NULL)
2051 FREE_AND_NULL(des)
2052}
2053
2054/**
2055 * xmlSchemaVIllegalAttrErr:
2056 * @ctxt: the schema validation context
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002057 * @error: the error code
Daniel Veillardc0826a72004-08-10 14:17:33 +00002058 * @attr: the illegal attribute node
2059 *
2060 * Reports an illegal attribute.
2061 */
2062static void
2063xmlSchemaVIllegalAttrErr(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002064 xmlParserErrors error,
William M. Brack2f2a6632004-08-20 23:09:47 +00002065 xmlAttrPtr attr)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002066{
2067 xmlChar *strE = NULL, *strA = NULL;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002068
2069 xmlSchemaVErr(ctxt, (xmlNodePtr) attr,
2070 error,
2071 /* XML_SCHEMAS_ERR_ATTRUNKNOWN, */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002072 "%s: The attribute '%s' is not allowed.\n",
2073 xmlSchemaFormatItemForReport(&strE, NULL, NULL, attr->parent, 0),
2074 xmlSchemaFormatNsPrefixLocal(&strA, attr->ns, attr->name));
2075 FREE_AND_NULL(strE)
2076 FREE_AND_NULL(strA)
2077}
2078
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002079
2080static int
2081xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
2082{
2083 switch (item->type) {
2084 case XML_SCHEMA_TYPE_COMPLEX:
2085 case XML_SCHEMA_TYPE_SIMPLE:
2086 case XML_SCHEMA_TYPE_GROUP:
2087 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
2088 return(1);
2089 break;
2090 case XML_SCHEMA_TYPE_ELEMENT:
2091 if ( ((xmlSchemaElementPtr) item)->flags &
2092 XML_SCHEMAS_ELEM_GLOBAL)
2093 return(1);
2094 break;
2095 case XML_SCHEMA_TYPE_ATTRIBUTE:
2096 if ( ((xmlSchemaAttributePtr) item)->flags &
2097 XML_SCHEMAS_ATTR_GLOBAL)
2098 return(1);
2099 break;
2100 /* Note that attribute groups are always global. */
2101 default:
2102 return(1);
2103 }
2104 return (0);
2105}
2106
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002107
2108static void
2109xmlSchemaStreamVCustomErr(xmlSchemaValidCtxtPtr vctxt,
2110 xmlParserErrors error,
2111 xmlSchemaNodeInfoPtr nodeInfo,
2112 xmlSchemaTypePtr type,
2113 const char *message,
2114 const xmlChar *str1,
2115 const xmlChar *str2)
2116{
2117 xmlChar *msg = NULL, *str = NULL;
2118
2119 msg = xmlStrdup(BAD_CAST "Element '");
2120
2121 if (vctxt->elemInfos[vctxt->depth] != nodeInfo) {
2122 xmlSchemaNodeInfoPtr elemInfo;
2123 /*
2124 * The node info is an attribute info.
2125 */
2126 elemInfo = vctxt->elemInfos[vctxt->depth];
2127 msg = xmlStrcat(msg, xmlSchemaFormatQName(&str,
2128 elemInfo->namespaceName, elemInfo->localName));
2129 msg = xmlStrcat(msg, BAD_CAST "', ");
2130 msg = xmlStrcat(msg, BAD_CAST "attribute '");
2131 }
2132 msg = xmlStrcat(msg, xmlSchemaFormatQName(&str,
2133 nodeInfo->namespaceName, nodeInfo->localName));
2134 msg = xmlStrcat(msg, BAD_CAST "'");
2135
2136 if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
2137 msg = xmlStrcat(msg, BAD_CAST " [");
2138 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str,
2139 NULL, type, NULL, 0));
2140 msg = xmlStrcat(msg, BAD_CAST "]");
2141 }
2142 msg = xmlStrcat(msg, BAD_CAST ": ");
2143
2144 msg = xmlStrcat(msg, (const xmlChar *) message);
2145 msg = xmlStrcat(msg, BAD_CAST ".\n");
2146 xmlSchemaVErr(vctxt, nodeInfo->node, error, (const char *) msg,
2147 str1, str2);
2148 FREE_AND_NULL(msg)
2149 FREE_AND_NULL(str)
2150}
2151
William M. Brack2f2a6632004-08-20 23:09:47 +00002152/**
2153 * xmlSchemaVCustomErr:
2154 * @ctxt: the schema validation context
2155 * @error: the error code
2156 * @node: the validated node
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002157 * @type: the schema type of the validated node
William M. Brack2f2a6632004-08-20 23:09:47 +00002158 * @message: the error message
2159 * @str1: the optional param for the message
2160 *
2161 * Reports a validation error.
2162 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002163static void
2164xmlSchemaVCustomErr(xmlSchemaValidCtxtPtr ctxt,
2165 xmlParserErrors error,
2166 xmlNodePtr node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002167 xmlSchemaTypePtr type,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002168 const char *message,
2169 const xmlChar *str1)
2170{
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002171 xmlChar *msg = NULL, *str = NULL;
2172
2173 if (node == NULL) {
2174 xmlSchemaVErr(ctxt, NULL,
2175 XML_SCHEMAV_INTERNAL,
2176 "Internal error: xmlSchemaVCustomErr, no node "
2177 "given.\n", NULL, NULL);
2178 return;
2179 }
2180 /* TODO: Are the HTML and DOCB doc nodes expected here? */
2181 if (node->type != XML_DOCUMENT_NODE) {
2182 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002183 if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002184 msg = xmlStrcat(msg, BAD_CAST " [");
2185 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
2186 msg = xmlStrcat(msg, BAD_CAST "]");
2187 }
2188 msg = xmlStrcat(msg, BAD_CAST ": ");
2189 } else
2190 msg = xmlStrdup((const xmlChar *) "");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002191 msg = xmlStrcat(msg, (const xmlChar *) message);
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002192 msg = xmlStrcat(msg, BAD_CAST ".\n");
2193 xmlSchemaVErr(ctxt, node, error, (const char *) msg, str1, NULL);
2194 FREE_AND_NULL(msg)
2195 FREE_AND_NULL(str)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002196}
2197
William M. Brack2f2a6632004-08-20 23:09:47 +00002198/**
William M. Brack2f2a6632004-08-20 23:09:47 +00002199 * xmlSchemaVWildcardErr:
2200 * @ctxt: the schema validation context
2201 * @error: the error code
2202 * @node: the validated node
2203 * @wild: the wildcard used
2204 * @message: the error message
2205 *
2206 * Reports an validation-by-wildcard error.
2207 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002208static void
2209xmlSchemaVWildcardErr(xmlSchemaValidCtxtPtr ctxt,
2210 xmlParserErrors error,
2211 xmlNodePtr node,
2212 xmlSchemaWildcardPtr wild,
2213 const char *message)
2214{
2215 xmlChar *des = NULL, *msg = NULL;
2216
2217 xmlSchemaFormatItemForReport(&des, NULL, NULL, node, 0);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00002218 msg = xmlStrdup(BAD_CAST "%s [");
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00002219 msg = xmlStrcat(msg, xmlSchemaWildcardPCToString(wild->processContents));
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002220 msg = xmlStrcat(msg, BAD_CAST " wildcard]: ");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002221 msg = xmlStrcat(msg, (const xmlChar *) message);
2222 msg = xmlStrcat(msg, BAD_CAST ".\n");
2223 xmlSchemaVErr(ctxt, node, error, (const char *) msg, BAD_CAST des, NULL);
2224 FREE_AND_NULL(des);
2225 FREE_AND_NULL(msg);
2226}
2227
2228/**
2229 * xmlSchemaVMissingAttrErr:
2230 * @ctxt: the schema validation context
2231 * @node: the parent element node of the missing attribute node
2232 * @type: the corresponding type of the attribute node
2233 *
2234 * Reports an illegal attribute.
2235 */
2236static void
2237xmlSchemaVMissingAttrErr(xmlSchemaValidCtxtPtr ctxt,
2238 xmlNodePtr elem,
2239 xmlSchemaAttributePtr type)
2240{
2241 const xmlChar *name, *uri;
2242 xmlChar *strE = NULL, *strA = NULL;
2243
2244 if (type->ref != NULL) {
2245 name = type->ref;
2246 uri = type->refNs;
2247 } else {
2248 name = type->name;
2249 uri = type->targetNamespace;
2250 }
2251 xmlSchemaVErr(ctxt, elem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002252 XML_SCHEMAV_CVC_COMPLEX_TYPE_4,
2253 /* XML_SCHEMAS_ERR_MISSING, */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002254 "%s: The attribute %s is required but missing.\n",
2255 xmlSchemaFormatItemForReport(&strE, NULL, NULL, elem, 0),
2256 xmlSchemaFormatNsUriLocal(&strA, uri, name));
2257 FREE_AND_NULL(strE)
2258 FREE_AND_NULL(strA)
2259}
2260
Daniel Veillard4255d502002-04-16 15:50:10 +00002261/************************************************************************
2262 * *
2263 * Allocation functions *
2264 * *
2265 ************************************************************************/
2266
2267/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002268 * xmlSchemaNewSchemaForParserCtxt:
William M. Brack08171912003-12-29 02:52:11 +00002269 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00002270 *
2271 * Allocate a new Schema structure.
2272 *
2273 * Returns the newly allocated structure or NULL in case or error
2274 */
2275static xmlSchemaPtr
2276xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
2277{
2278 xmlSchemaPtr ret;
2279
2280 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
2281 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002282 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002283 return (NULL);
2284 }
2285 memset(ret, 0, sizeof(xmlSchema));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002286 ret->dict = ctxt->dict;
Daniel Veillard500a1de2004-03-22 15:22:58 +00002287 xmlDictReference(ret->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00002288
2289 return (ret);
2290}
2291
2292/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002293 * xmlSchemaNewSchema:
2294 * @ctxt: a schema validation context
2295 *
2296 * Allocate a new Schema structure.
2297 *
2298 * Returns the newly allocated structure or NULL in case or error
2299 */
2300static xmlSchemaAssemblePtr
2301xmlSchemaNewAssemble(void)
2302{
2303 xmlSchemaAssemblePtr ret;
2304
2305 ret = (xmlSchemaAssemblePtr) xmlMalloc(sizeof(xmlSchemaAssemble));
2306 if (ret == NULL) {
2307 /* xmlSchemaPErrMemory(ctxt, "allocating assemble info", NULL); */
2308 return (NULL);
2309 }
2310 memset(ret, 0, sizeof(xmlSchemaAssemble));
2311 ret->items = NULL;
2312 return (ret);
2313}
2314
2315/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002316 * xmlSchemaNewFacet:
Daniel Veillard4255d502002-04-16 15:50:10 +00002317 *
2318 * Allocate a new Facet structure.
2319 *
2320 * Returns the newly allocated structure or NULL in case or error
2321 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00002322xmlSchemaFacetPtr
2323xmlSchemaNewFacet(void)
Daniel Veillard4255d502002-04-16 15:50:10 +00002324{
2325 xmlSchemaFacetPtr ret;
2326
2327 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
2328 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002329 return (NULL);
2330 }
2331 memset(ret, 0, sizeof(xmlSchemaFacet));
2332
2333 return (ret);
2334}
2335
2336/**
2337 * xmlSchemaNewAnnot:
William M. Brack08171912003-12-29 02:52:11 +00002338 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00002339 * @node: a node
2340 *
2341 * Allocate a new annotation structure.
2342 *
2343 * Returns the newly allocated structure or NULL in case or error
2344 */
2345static xmlSchemaAnnotPtr
2346xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
2347{
2348 xmlSchemaAnnotPtr ret;
2349
2350 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
2351 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002352 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
Daniel Veillard4255d502002-04-16 15:50:10 +00002353 return (NULL);
2354 }
2355 memset(ret, 0, sizeof(xmlSchemaAnnot));
2356 ret->content = node;
2357 return (ret);
2358}
2359
2360/**
Daniel Veillardfdc91562002-07-01 21:52:03 +00002361 * xmlSchemaFreeAnnot:
2362 * @annot: a schema type structure
2363 *
2364 * Deallocate a annotation structure
2365 */
2366static void
2367xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
2368{
2369 if (annot == NULL)
2370 return;
2371 xmlFree(annot);
2372}
2373
2374/**
Daniel Veillard1d913862003-11-21 00:28:39 +00002375 * xmlSchemaFreeImport:
2376 * @import: a schema import structure
2377 *
2378 * Deallocate an import structure
2379 */
2380static void
2381xmlSchemaFreeImport(xmlSchemaImportPtr import)
2382{
2383 if (import == NULL)
2384 return;
2385
2386 xmlSchemaFree(import->schema);
William M. Brack2f2a6632004-08-20 23:09:47 +00002387 xmlFreeDoc(import->doc);
Daniel Veillard1d913862003-11-21 00:28:39 +00002388 xmlFree(import);
2389}
2390
2391/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002392 * xmlSchemaFreeInclude:
2393 * @include: a schema include structure
2394 *
2395 * Deallocate an include structure
2396 */
2397static void
2398xmlSchemaFreeInclude(xmlSchemaIncludePtr include)
2399{
2400 if (include == NULL)
2401 return;
2402
2403 xmlFreeDoc(include->doc);
2404 xmlFree(include);
2405}
2406
2407/**
2408 * xmlSchemaFreeIncludeList:
2409 * @includes: a schema include list
2410 *
2411 * Deallocate an include structure
2412 */
2413static void
2414xmlSchemaFreeIncludeList(xmlSchemaIncludePtr includes)
2415{
2416 xmlSchemaIncludePtr next;
2417
2418 while (includes != NULL) {
2419 next = includes->next;
2420 xmlSchemaFreeInclude(includes);
2421 includes = next;
2422 }
2423}
2424
2425/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002426 * xmlSchemaFreeNotation:
2427 * @schema: a schema notation structure
2428 *
2429 * Deallocate a Schema Notation structure.
2430 */
2431static void
2432xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
2433{
2434 if (nota == NULL)
2435 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002436 xmlFree(nota);
2437}
2438
2439/**
2440 * xmlSchemaFreeAttribute:
2441 * @schema: a schema attribute structure
2442 *
2443 * Deallocate a Schema Attribute structure.
2444 */
2445static void
2446xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
2447{
2448 if (attr == NULL)
2449 return;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002450 if (attr->annot != NULL)
2451 xmlSchemaFreeAnnot(attr->annot);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002452 if (attr->defVal != NULL)
2453 xmlSchemaFreeValue(attr->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00002454 xmlFree(attr);
2455}
2456
2457/**
Daniel Veillard3646d642004-06-02 19:19:14 +00002458 * xmlSchemaFreeWildcardNsSet:
2459 * set: a schema wildcard namespace
2460 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00002461 * Deallocates a list of wildcard constraint structures.
Daniel Veillard3646d642004-06-02 19:19:14 +00002462 */
2463static void
2464xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
2465{
2466 xmlSchemaWildcardNsPtr next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002467
Daniel Veillard3646d642004-06-02 19:19:14 +00002468 while (set != NULL) {
2469 next = set->next;
2470 xmlFree(set);
2471 set = next;
2472 }
2473}
2474
2475/**
2476 * xmlSchemaFreeWildcard:
Daniel Veillard01fa6152004-06-29 17:04:39 +00002477 * @wildcard: a wildcard structure
Daniel Veillard3646d642004-06-02 19:19:14 +00002478 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00002479 * Deallocates a wildcard structure.
Daniel Veillard3646d642004-06-02 19:19:14 +00002480 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00002481void
Daniel Veillard3646d642004-06-02 19:19:14 +00002482xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
2483{
2484 if (wildcard == NULL)
2485 return;
2486 if (wildcard->annot != NULL)
2487 xmlSchemaFreeAnnot(wildcard->annot);
2488 if (wildcard->nsSet != NULL)
2489 xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
2490 if (wildcard->negNsSet != NULL)
2491 xmlFree(wildcard->negNsSet);
2492 xmlFree(wildcard);
2493}
2494
2495/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002496 * xmlSchemaFreeAttributeGroup:
2497 * @schema: a schema attribute group structure
2498 *
2499 * Deallocate a Schema Attribute Group structure.
2500 */
2501static void
2502xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attr)
2503{
2504 if (attr == NULL)
2505 return;
Daniel Veillard3646d642004-06-02 19:19:14 +00002506 if (attr->annot != NULL)
2507 xmlSchemaFreeAnnot(attr->annot);
2508 if ((attr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) &&
2509 (attr->attributeWildcard != NULL))
2510 xmlSchemaFreeWildcard(attr->attributeWildcard);
2511
Daniel Veillard4255d502002-04-16 15:50:10 +00002512 xmlFree(attr);
2513}
2514
2515/**
Daniel Veillard3646d642004-06-02 19:19:14 +00002516 * xmlSchemaFreeAttributeUseList:
Daniel Veillard01fa6152004-06-29 17:04:39 +00002517 * @attrUse: an attribute link
Daniel Veillard3646d642004-06-02 19:19:14 +00002518 *
2519 * Deallocate a list of schema attribute uses.
2520 */
2521static void
2522xmlSchemaFreeAttributeUseList(xmlSchemaAttributeLinkPtr attrUse)
2523{
2524 xmlSchemaAttributeLinkPtr next;
2525
2526 while (attrUse != NULL) {
2527 next = attrUse->next;
2528 xmlFree(attrUse);
2529 attrUse = next;
2530 }
2531}
2532
2533/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00002534 * xmlSchemaFreeTypeLinkList:
2535 * @alink: a type link
2536 *
2537 * Deallocate a list of types.
2538 */
2539static void
2540xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
2541{
2542 xmlSchemaTypeLinkPtr next;
2543
2544 while (link != NULL) {
2545 next = link->next;
2546 xmlFree(link);
2547 link = next;
2548 }
2549}
2550
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00002551#ifdef IDC_ENABLED
2552static void
2553xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
2554{
2555 xmlSchemaIDCStateObjPtr next;
2556 while (sto != NULL) {
2557 next = sto->next;
2558 if (sto->history != NULL)
2559 xmlFree(sto->history);
2560 if (sto->xpathCtxt != NULL)
2561 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
2562 xmlFree(sto);
2563 sto = next;
2564 }
2565}
2566
2567/**
2568 * xmlSchemaFreeIDC:
2569 * @idc: a identity-constraint definition
2570 *
2571 * Deallocates an identity-constraint definition.
2572 */
2573static void
2574xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)
2575{
2576 xmlSchemaIDCSelectPtr cur, prev;
2577
2578 if (idcDef == NULL)
2579 return;
2580 if (idcDef->annot != NULL)
2581 xmlSchemaFreeAnnot(idcDef->annot);
2582 if (idcDef->ref != NULL)
2583 xmlFree(idcDef->ref);
2584 /* Selector */
2585 if (idcDef->selector != NULL) {
2586 if (idcDef->selector->xpathComp != NULL)
2587 xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp);
2588 xmlFree(idcDef->selector);
2589 }
2590 /* Fields */
2591 if (idcDef->fields != NULL) {
2592 cur = idcDef->fields;
2593 do {
2594 prev = cur;
2595 cur = cur->next;
2596 if (prev->xpathComp != NULL)
2597 xmlFreePattern((xmlPatternPtr) prev->xpathComp);
2598 xmlFree(prev);
2599 } while (cur != NULL);
2600 }
2601 xmlFree(idcDef);
2602}
2603#endif /* IDC_ENABLED */
2604
Daniel Veillard01fa6152004-06-29 17:04:39 +00002605/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002606 * xmlSchemaFreeElement:
2607 * @schema: a schema element structure
2608 *
2609 * Deallocate a Schema Element structure.
2610 */
2611static void
2612xmlSchemaFreeElement(xmlSchemaElementPtr elem)
2613{
2614 if (elem == NULL)
2615 return;
Daniel Veillard32370232002-10-16 14:08:14 +00002616 if (elem->annot != NULL)
2617 xmlSchemaFreeAnnot(elem->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00002618 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002619 xmlRegFreeRegexp(elem->contModel);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002620 if (elem->defVal != NULL)
2621 xmlSchemaFreeValue(elem->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00002622 xmlFree(elem);
2623}
2624
2625/**
2626 * xmlSchemaFreeFacet:
2627 * @facet: a schema facet structure
2628 *
2629 * Deallocate a Schema Facet structure.
2630 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00002631void
Daniel Veillard4255d502002-04-16 15:50:10 +00002632xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
2633{
2634 if (facet == NULL)
2635 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002636 if (facet->val != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002637 xmlSchemaFreeValue(facet->val);
Daniel Veillard4255d502002-04-16 15:50:10 +00002638 if (facet->regexp != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002639 xmlRegFreeRegexp(facet->regexp);
Daniel Veillardfdc91562002-07-01 21:52:03 +00002640 if (facet->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002641 xmlSchemaFreeAnnot(facet->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00002642 xmlFree(facet);
2643}
2644
2645/**
2646 * xmlSchemaFreeType:
2647 * @type: a schema type structure
2648 *
2649 * Deallocate a Schema Type structure.
2650 */
2651void
2652xmlSchemaFreeType(xmlSchemaTypePtr type)
2653{
2654 if (type == NULL)
2655 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002656 if (type->annot != NULL)
Daniel Veillard32370232002-10-16 14:08:14 +00002657 xmlSchemaFreeAnnot(type->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00002658 if (type->facets != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002659 xmlSchemaFacetPtr facet, next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002660
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002661 facet = type->facets;
2662 while (facet != NULL) {
2663 next = facet->next;
2664 xmlSchemaFreeFacet(facet);
2665 facet = next;
2666 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002667 }
Daniel Veillard3646d642004-06-02 19:19:14 +00002668 if (type->type != XML_SCHEMA_TYPE_BASIC) {
2669 if (type->attributeUses != NULL)
2670 xmlSchemaFreeAttributeUseList(type->attributeUses);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002671 if ((type->attributeWildcard != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +00002672 ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002673 (type->flags & XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD))) {
2674 /*
2675 * NOTE: The only case where an attribute wildcard
2676 * is not owned, is if a complex type inherits it
2677 * from a base type.
2678 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002679 xmlSchemaFreeWildcard(type->attributeWildcard);
2680 }
2681 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00002682 if (type->memberTypes != NULL)
2683 xmlSchemaFreeTypeLinkList(type->memberTypes);
2684 if (type->facetSet != NULL) {
2685 xmlSchemaFacetLinkPtr next, link;
2686
2687 link = type->facetSet;
2688 do {
2689 next = link->next;
2690 xmlFree(link);
2691 link = next;
2692 } while (link != NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002693 }
2694 if (type->contModel != NULL)
2695 xmlRegFreeRegexp(type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00002696 xmlFree(type);
2697}
2698
2699/**
Daniel Veillardb0f397e2003-12-23 23:30:53 +00002700 * xmlSchemaFreeTypeList:
2701 * @type: a schema type structure
2702 *
2703 * Deallocate a Schema Type structure.
2704 */
2705static void
2706xmlSchemaFreeTypeList(xmlSchemaTypePtr type)
2707{
2708 xmlSchemaTypePtr next;
2709
2710 while (type != NULL) {
2711 next = type->redef;
2712 xmlSchemaFreeType(type);
2713 type = next;
2714 }
2715}
2716
2717/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002718 * xmlSchemaFree:
2719 * @schema: a schema structure
2720 *
2721 * Deallocate a Schema structure.
2722 */
2723void
2724xmlSchemaFree(xmlSchemaPtr schema)
2725{
2726 if (schema == NULL)
2727 return;
2728
Daniel Veillard4255d502002-04-16 15:50:10 +00002729 if (schema->notaDecl != NULL)
2730 xmlHashFree(schema->notaDecl,
2731 (xmlHashDeallocator) xmlSchemaFreeNotation);
2732 if (schema->attrDecl != NULL)
2733 xmlHashFree(schema->attrDecl,
2734 (xmlHashDeallocator) xmlSchemaFreeAttribute);
2735 if (schema->attrgrpDecl != NULL)
2736 xmlHashFree(schema->attrgrpDecl,
2737 (xmlHashDeallocator) xmlSchemaFreeAttributeGroup);
2738 if (schema->elemDecl != NULL)
2739 xmlHashFree(schema->elemDecl,
2740 (xmlHashDeallocator) xmlSchemaFreeElement);
2741 if (schema->typeDecl != NULL)
2742 xmlHashFree(schema->typeDecl,
Daniel Veillardb0f397e2003-12-23 23:30:53 +00002743 (xmlHashDeallocator) xmlSchemaFreeTypeList);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00002744 if (schema->groupDecl != NULL)
2745 xmlHashFree(schema->groupDecl,
2746 (xmlHashDeallocator) xmlSchemaFreeType);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00002747#ifdef IDC_ENABLED
2748 if (schema->idcDef != NULL)
2749 xmlHashFree(schema->idcDef,
2750 (xmlHashDeallocator) xmlSchemaFreeIDC);
2751#endif
Daniel Veillard1d913862003-11-21 00:28:39 +00002752 if (schema->schemasImports != NULL)
2753 xmlHashFree(schema->schemasImports,
2754 (xmlHashDeallocator) xmlSchemaFreeImport);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002755 if (schema->includes != NULL) {
2756 xmlSchemaFreeIncludeList((xmlSchemaIncludePtr) schema->includes);
2757 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002758 if (schema->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002759 xmlSchemaFreeAnnot(schema->annot);
Daniel Veillarddda22c12004-01-24 08:31:30 +00002760 if (schema->doc != NULL && !schema->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002761 xmlFreeDoc(schema->doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002762 xmlDictFree(schema->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00002763 xmlFree(schema);
2764}
2765
2766/************************************************************************
2767 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00002768 * Debug functions *
2769 * *
2770 ************************************************************************/
2771
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002772#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002773
Daniel Veillard4255d502002-04-16 15:50:10 +00002774/**
2775 * xmlSchemaElementDump:
2776 * @elem: an element
2777 * @output: the file output
2778 *
2779 * Dump the element
2780 */
2781static void
2782xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002783 const xmlChar * name ATTRIBUTE_UNUSED,
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002784 const xmlChar * namespace ATTRIBUTE_UNUSED,
2785 const xmlChar * context ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00002786{
2787 if (elem == NULL)
2788 return;
2789
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002790 if (elem->flags & XML_SCHEMAS_ELEM_REF) {
2791 fprintf(output, "Particle: %s", name);
2792 fprintf(output, ", term element: %s", elem->ref);
2793 if (elem->refNs != NULL)
2794 fprintf(output, " ns %s", elem->refNs);
2795 } else {
2796 fprintf(output, "Element");
2797 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
2798 fprintf(output, " (global)");
2799 fprintf(output, ": %s ", elem->name);
2800 if (namespace != NULL)
2801 fprintf(output, "ns %s", namespace);
2802 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002803 fprintf(output, "\n");
2804 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002805 fprintf(output, " min %d ", elem->minOccurs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002806 if (elem->maxOccurs >= UNBOUNDED)
2807 fprintf(output, "max: unbounded\n");
2808 else if (elem->maxOccurs != 1)
2809 fprintf(output, "max: %d\n", elem->maxOccurs);
2810 else
2811 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002812 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002813 /*
2814 * Misc other properties.
2815 */
2816 if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
2817 (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
2818 (elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
2819 (elem->flags & XML_SCHEMAS_ELEM_DEFAULT) ||
2820 (elem->id != NULL)) {
2821 fprintf(output, " props: ");
2822 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
2823 fprintf(output, "[fixed] ");
2824 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
2825 fprintf(output, "[default] ");
2826 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
2827 fprintf(output, "[abstract] ");
2828 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
2829 fprintf(output, "[nillable] ");
2830 if (elem->id != NULL)
2831 fprintf(output, "[id: '%s'] ", elem->id);
2832 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002833 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002834 /*
2835 * Default/fixed value.
2836 */
Daniel Veillard4255d502002-04-16 15:50:10 +00002837 if (elem->value != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002838 fprintf(output, " value: '%s'\n", elem->value);
2839 /*
2840 * Type.
2841 */
2842 if (elem->namedType != NULL) {
2843 fprintf(output, " type: %s ", elem->namedType);
2844 if (elem->namedTypeNs != NULL)
2845 fprintf(output, "ns %s\n", elem->namedTypeNs);
2846 else
2847 fprintf(output, "\n");
2848 }
2849 /*
2850 * Substitution group.
2851 */
2852 if (elem->substGroup != NULL) {
2853 fprintf(output, " substitutionGroup: %s ", elem->substGroup);
2854 if (elem->substGroupNs != NULL)
2855 fprintf(output, "ns %s\n", elem->substGroupNs);
2856 else
2857 fprintf(output, "\n");
2858 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002859}
2860
2861/**
2862 * xmlSchemaAnnotDump:
2863 * @output: the file output
2864 * @annot: a annotation
2865 *
2866 * Dump the annotation
2867 */
2868static void
2869xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
2870{
2871 xmlChar *content;
2872
2873 if (annot == NULL)
2874 return;
2875
2876 content = xmlNodeGetContent(annot->content);
2877 if (content != NULL) {
2878 fprintf(output, " Annot: %s\n", content);
2879 xmlFree(content);
2880 } else
2881 fprintf(output, " Annot: empty\n");
2882}
2883
2884/**
2885 * xmlSchemaTypeDump:
2886 * @output: the file output
2887 * @type: a type structure
2888 *
2889 * Dump a SchemaType structure
2890 */
2891static void
2892xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
2893{
2894 if (type == NULL) {
2895 fprintf(output, "Type: NULL\n");
2896 return;
2897 }
2898 fprintf(output, "Type: ");
2899 if (type->name != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002900 fprintf(output, "%s ", type->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00002901 else
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002902 fprintf(output, "no name ");
2903 if (type->targetNamespace != NULL)
2904 fprintf(output, "ns %s ", type->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00002905 switch (type->type) {
2906 case XML_SCHEMA_TYPE_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002907 fprintf(output, "[basic] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002908 break;
2909 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002910 fprintf(output, "[simple] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002911 break;
2912 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002913 fprintf(output, "[complex] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002914 break;
2915 case XML_SCHEMA_TYPE_SEQUENCE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002916 fprintf(output, "[sequence] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002917 break;
2918 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002919 fprintf(output, "[choice] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002920 break;
2921 case XML_SCHEMA_TYPE_ALL:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002922 fprintf(output, "[all] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002923 break;
2924 case XML_SCHEMA_TYPE_UR:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002925 fprintf(output, "[ur] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002926 break;
2927 case XML_SCHEMA_TYPE_RESTRICTION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002928 fprintf(output, "[restriction] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002929 break;
2930 case XML_SCHEMA_TYPE_EXTENSION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002931 fprintf(output, "[extension] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002932 break;
2933 default:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002934 fprintf(output, "[unknown type %d] ", type->type);
Daniel Veillard4255d502002-04-16 15:50:10 +00002935 break;
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002936 }
2937 fprintf(output, "content: ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002938 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002939 case XML_SCHEMA_CONTENT_UNKNOWN:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002940 fprintf(output, "[unknown] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002941 break;
2942 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002943 fprintf(output, "[empty] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002944 break;
2945 case XML_SCHEMA_CONTENT_ELEMENTS:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002946 fprintf(output, "[element] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002947 break;
2948 case XML_SCHEMA_CONTENT_MIXED:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002949 fprintf(output, "[mixed] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002950 break;
2951 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00002952 /* not used. */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002953 break;
2954 case XML_SCHEMA_CONTENT_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002955 fprintf(output, "[basic] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002956 break;
2957 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002958 fprintf(output, "[simple] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002959 break;
2960 case XML_SCHEMA_CONTENT_ANY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002961 fprintf(output, "[any] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002962 break;
Daniel Veillard4255d502002-04-16 15:50:10 +00002963 }
2964 fprintf(output, "\n");
2965 if ((type->minOccurs != 1) || (type->maxOccurs != 1)) {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002966 fprintf(output, " min: %d ", type->minOccurs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002967 if (type->maxOccurs >= UNBOUNDED)
2968 fprintf(output, "max: unbounded\n");
2969 else if (type->maxOccurs != 1)
2970 fprintf(output, "max: %d\n", type->maxOccurs);
2971 else
2972 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002973 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002974 if (type->base != NULL) {
2975 fprintf(output, " base type: %s", type->base);
2976 if (type->baseNs != NULL)
2977 fprintf(output, " ns %s\n", type->baseNs);
2978 else
2979 fprintf(output, "\n");
2980 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002981 if (type->annot != NULL)
2982 xmlSchemaAnnotDump(output, type->annot);
2983 if (type->subtypes != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002984 xmlSchemaTypePtr sub = type->subtypes;
Daniel Veillard4255d502002-04-16 15:50:10 +00002985
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002986 fprintf(output, " subtypes: ");
2987 while (sub != NULL) {
2988 fprintf(output, "%s ", sub->name);
2989 sub = sub->next;
2990 }
2991 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002992 }
2993
2994}
2995
2996/**
2997 * xmlSchemaDump:
2998 * @output: the file output
2999 * @schema: a schema structure
3000 *
3001 * Dump a Schema structure.
3002 */
3003void
3004xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
3005{
Daniel Veillardce682bc2004-11-05 17:22:25 +00003006 if (output == NULL)
3007 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003008 if (schema == NULL) {
3009 fprintf(output, "Schemas: NULL\n");
3010 return;
3011 }
3012 fprintf(output, "Schemas: ");
3013 if (schema->name != NULL)
3014 fprintf(output, "%s, ", schema->name);
3015 else
3016 fprintf(output, "no name, ");
3017 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00003018 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003019 else
3020 fprintf(output, "no target namespace");
3021 fprintf(output, "\n");
3022 if (schema->annot != NULL)
3023 xmlSchemaAnnotDump(output, schema->annot);
3024
3025 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
3026 output);
3027 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003028 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00003029}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003030
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003031#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00003032#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003033/**
3034 * xmlSchemaDebugDumpIDCTable:
3035 * @vctxt: the WXS validation context
3036 *
3037 * Displays the current IDC table for debug purposes.
3038 */
3039static void
3040xmlSchemaDebugDumpIDCTable(FILE * output,
3041 const xmlChar *namespaceName,
3042 const xmlChar *localName,
3043 xmlSchemaPSVIIDCBindingPtr bind)
3044{
3045 xmlChar *str = NULL, *value;
3046 xmlSchemaPSVIIDCNodePtr tab;
3047 xmlSchemaPSVIIDCKeyPtr key;
3048 int i, j, res;
3049
3050 fprintf(output, "IDC: TABLES on %s\n",
3051 xmlSchemaFormatNsUriLocal(&str, namespaceName, localName));
3052 FREE_AND_NULL(str)
3053
3054 if (bind == NULL)
3055 return;
3056 do {
3057 fprintf(output, "IDC: BINDING %s\n",
3058 xmlSchemaFormatNsUriLocal(&str, bind->definition->targetNamespace,
3059 bind->definition->name));
3060 FREE_AND_NULL(str)
3061 for (i = 0; i < bind->nbNodes; i++) {
3062 tab = bind->nodeTable[i];
3063 fprintf(output, " ( ");
3064 for (j = 0; j < bind->definition->nbFields; j++) {
3065 key = tab->keys[j];
3066 if ((key != NULL) && (key->compValue != NULL)) {
3067#ifdef IDC_VALUE_SUPPORT
3068 res = xmlSchemaGetCanonValue(key->compValue, &value);
3069#else
3070 value = xmlStrdup(BAD_CAST "dummy-value");
3071 res = 0;
3072#endif
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003073 if (res >= 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003074 fprintf(output, "\"%s\" ", value);
3075 else
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003076 fprintf(output, "CANON-VALUE-FAILED ");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003077 if (res == 0)
3078 FREE_AND_NULL(value)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003079 } else if (key != NULL)
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003080 fprintf(output, "(no val), ");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003081 else
3082 fprintf(output, "(key missing), ");
3083 }
3084 fprintf(output, ")\n");
3085 }
3086 bind = bind->next;
3087 } while (bind != NULL);
3088}
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00003089#endif /* DEBUG_IDC */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003090#endif /* IDC_ENABLED */
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00003091#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +00003092
3093/************************************************************************
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003094 * *
3095 * Utilities *
3096 * *
3097 ************************************************************************/
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003098
Daniel Veillardc0826a72004-08-10 14:17:33 +00003099/**
3100 * xmlSchemaGetPropNode:
3101 * @node: the element node
3102 * @name: the name of the attribute
3103 *
3104 * Seeks an attribute with a name of @name in
3105 * no namespace.
3106 *
3107 * Returns the attribute or NULL if not present.
3108 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003109static xmlAttrPtr
Daniel Veillardc0826a72004-08-10 14:17:33 +00003110xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
Daniel Veillard01fa6152004-06-29 17:04:39 +00003111{
3112 xmlAttrPtr prop;
3113
Daniel Veillardc0826a72004-08-10 14:17:33 +00003114 if ((node == NULL) || (name == NULL))
3115 return(NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003116 prop = node->properties;
3117 while (prop != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00003118 if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
3119 return(prop);
3120 prop = prop->next;
3121 }
3122 return (NULL);
3123}
3124
3125/**
3126 * xmlSchemaGetPropNodeNs:
3127 * @node: the element node
3128 * @uri: the uri
3129 * @name: the name of the attribute
3130 *
3131 * Seeks an attribute with a local name of @name and
3132 * a namespace URI of @uri.
3133 *
3134 * Returns the attribute or NULL if not present.
3135 */
3136static xmlAttrPtr
3137xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
3138{
3139 xmlAttrPtr prop;
3140
3141 if ((node == NULL) || (name == NULL))
3142 return(NULL);
3143 prop = node->properties;
3144 while (prop != NULL) {
3145 if ((prop->ns != NULL) &&
3146 xmlStrEqual(prop->name, BAD_CAST name) &&
3147 xmlStrEqual(prop->ns->href, BAD_CAST uri))
Daniel Veillard01fa6152004-06-29 17:04:39 +00003148 return(prop);
3149 prop = prop->next;
3150 }
3151 return (NULL);
3152}
3153
3154static const xmlChar *
3155xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3156{
3157 xmlChar *val;
3158 const xmlChar *ret;
3159
3160 val = xmlNodeGetContent(node);
3161 if (val == NULL)
3162 return(NULL);
3163 ret = xmlDictLookup(ctxt->dict, val, -1);
3164 xmlFree(val);
3165 return(ret);
3166}
3167
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003168/**
3169 * xmlSchemaGetProp:
3170 * @ctxt: the parser context
3171 * @node: the node
3172 * @name: the property name
3173 *
3174 * Read a attribute value and internalize the string
3175 *
3176 * Returns the string or NULL if not present.
3177 */
3178static const xmlChar *
3179xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
3180 const char *name)
3181{
3182 xmlChar *val;
3183 const xmlChar *ret;
3184
3185 val = xmlGetProp(node, BAD_CAST name);
3186 if (val == NULL)
3187 return(NULL);
3188 ret = xmlDictLookup(ctxt->dict, val, -1);
3189 xmlFree(val);
3190 return(ret);
3191}
3192
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003193/************************************************************************
Daniel Veillard4255d502002-04-16 15:50:10 +00003194 * *
3195 * Parsing functions *
3196 * *
3197 ************************************************************************/
3198
3199/**
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003200 * xmlSchemaGetElem:
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003201 * @schema: the schema context
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003202 * @name: the element name
3203 * @ns: the element namespace
3204 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003205 * Lookup a global element declaration in the schema.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003206 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003207 * Returns the element declaration or NULL if not found.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003208 */
3209static xmlSchemaElementPtr
3210xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003211 const xmlChar * namespace)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003212{
3213 xmlSchemaElementPtr ret;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003214
3215 if ((name == NULL) || (schema == NULL))
3216 return (NULL);
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003217
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003218 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003219 if ((ret != NULL) &&
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003220 (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003221 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00003222 } else
3223 ret = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00003224 /*
3225 * This one was removed, since top level element declarations have
3226 * the target namespace specified in targetNamespace of the <schema>
3227 * information element, even if elementFormDefault is "unqualified".
3228 */
3229
3230 /* else if ((schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003231 if (xmlStrEqual(namespace, schema->targetNamespace))
3232 ret = xmlHashLookup2(schema->elemDecl, name, NULL);
3233 else
3234 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003235 if ((ret != NULL) &&
3236 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003237 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003238 }
William M. Bracke7091952004-05-11 15:09:58 +00003239 */
Daniel Veillard3646d642004-06-02 19:19:14 +00003240
William M. Brack2f2a6632004-08-20 23:09:47 +00003241 /*
3242 * Removed since imported components will be hold by the main schema only.
3243 *
Daniel Veillard3646d642004-06-02 19:19:14 +00003244 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003245 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003246 else
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003247 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003248 if (import != NULL) {
Daniel Veillardf2a12832003-11-24 13:04:35 +00003249 ret = xmlSchemaGetElem(import->schema, name, namespace, level + 1);
Daniel Veillard3646d642004-06-02 19:19:14 +00003250 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
3251 return (ret);
3252 } else
3253 ret = NULL;
3254 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003255 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003256#ifdef DEBUG
3257 if (ret == NULL) {
3258 if (namespace == NULL)
3259 fprintf(stderr, "Unable to lookup type %s", name);
3260 else
3261 fprintf(stderr, "Unable to lookup type %s:%s", name,
3262 namespace);
3263 }
3264#endif
3265 return (ret);
3266}
3267
3268/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003269 * xmlSchemaGetType:
3270 * @schema: the schemas context
3271 * @name: the type name
3272 * @ns: the type namespace
3273 *
3274 * Lookup a type in the schemas or the predefined types
3275 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003276 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +00003277 */
3278static xmlSchemaTypePtr
3279xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003280 const xmlChar * namespace)
3281{
Daniel Veillard4255d502002-04-16 15:50:10 +00003282 xmlSchemaTypePtr ret;
3283
3284 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003285 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003286 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003287 ret = xmlHashLookup2(schema->typeDecl, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003288 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003289 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003290 }
3291 ret = xmlSchemaGetPredefinedType(name, namespace);
Daniel Veillard1d913862003-11-21 00:28:39 +00003292 if (ret != NULL)
3293 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00003294 /*
3295 * Removed, since the imported components will be grafted on the
3296 * main schema only.
Daniel Veillard3646d642004-06-02 19:19:14 +00003297 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003298 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003299 else
Daniel Veillard1d913862003-11-21 00:28:39 +00003300 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003301 if (import != NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00003302 ret = xmlSchemaGetType(import->schema, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003303 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
3304 return (ret);
3305 } else
3306 ret = NULL;
3307 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003308 */
Daniel Veillard4255d502002-04-16 15:50:10 +00003309#ifdef DEBUG
3310 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003311 if (namespace == NULL)
3312 fprintf(stderr, "Unable to lookup type %s", name);
3313 else
3314 fprintf(stderr, "Unable to lookup type %s:%s", name,
3315 namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003316 }
3317#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003318 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003319}
3320
Daniel Veillard3646d642004-06-02 19:19:14 +00003321/**
3322 * xmlSchemaGetAttribute:
3323 * @schema: the context of the schema
3324 * @name: the name of the attribute
3325 * @ns: the target namespace of the attribute
3326 *
3327 * Lookup a an attribute in the schema or imported schemas
3328 *
3329 * Returns the attribute declaration or NULL if not found.
3330 */
3331static xmlSchemaAttributePtr
3332xmlSchemaGetAttribute(xmlSchemaPtr schema, const xmlChar * name,
3333 const xmlChar * namespace)
3334{
3335 xmlSchemaAttributePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00003336
3337 if ((name == NULL) || (schema == NULL))
3338 return (NULL);
3339
3340
3341 ret = xmlHashLookup2(schema->attrDecl, name, namespace);
3342 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL))
3343 return (ret);
3344 else
3345 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00003346 /*
3347 * Removed, since imported components will be hold by the main schema only.
3348 *
Daniel Veillard3646d642004-06-02 19:19:14 +00003349 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003350 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003351 else
3352 import = xmlHashLookup(schema->schemasImports, namespace);
3353 if (import != NULL) {
3354 ret = xmlSchemaGetAttribute(import->schema, name, namespace);
3355 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL)) {
3356 return (ret);
3357 } else
3358 ret = NULL;
3359 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003360 */
Daniel Veillard3646d642004-06-02 19:19:14 +00003361#ifdef DEBUG
3362 if (ret == NULL) {
3363 if (namespace == NULL)
3364 fprintf(stderr, "Unable to lookup attribute %s", name);
3365 else
3366 fprintf(stderr, "Unable to lookup attribute %s:%s", name,
3367 namespace);
3368 }
3369#endif
3370 return (ret);
3371}
3372
3373/**
3374 * xmlSchemaGetAttributeGroup:
3375 * @schema: the context of the schema
3376 * @name: the name of the attribute group
3377 * @ns: the target namespace of the attribute group
3378 *
3379 * Lookup a an attribute group in the schema or imported schemas
3380 *
3381 * Returns the attribute group definition or NULL if not found.
3382 */
3383static xmlSchemaAttributeGroupPtr
3384xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
3385 const xmlChar * namespace)
3386{
3387 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00003388
3389 if ((name == NULL) || (schema == NULL))
3390 return (NULL);
3391
3392
3393 ret = xmlHashLookup2(schema->attrgrpDecl, name, namespace);
3394 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
3395 return (ret);
3396 else
3397 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00003398 /*
3399 * Removed since imported components will be hold by the main schema only.
3400 *
Daniel Veillard3646d642004-06-02 19:19:14 +00003401 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003402 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003403 else
3404 import = xmlHashLookup(schema->schemasImports, namespace);
3405 if (import != NULL) {
3406 ret = xmlSchemaGetAttributeGroup(import->schema, name, namespace);
3407 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
3408 return (ret);
3409 else
3410 ret = NULL;
3411 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003412 */
Daniel Veillard3646d642004-06-02 19:19:14 +00003413#ifdef DEBUG
3414 if (ret == NULL) {
3415 if (namespace == NULL)
3416 fprintf(stderr, "Unable to lookup attribute group %s", name);
3417 else
3418 fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
3419 namespace);
3420 }
3421#endif
3422 return (ret);
3423}
3424
3425/**
3426 * xmlSchemaGetGroup:
3427 * @schema: the context of the schema
3428 * @name: the name of the group
3429 * @ns: the target namespace of the group
3430 *
3431 * Lookup a group in the schema or imported schemas
3432 *
3433 * Returns the group definition or NULL if not found.
3434 */
3435static xmlSchemaTypePtr
3436xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
3437 const xmlChar * namespace)
3438{
3439 xmlSchemaTypePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00003440
3441 if ((name == NULL) || (schema == NULL))
3442 return (NULL);
3443
3444
3445 ret = xmlHashLookup2(schema->groupDecl, name, namespace);
3446 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
3447 return (ret);
3448 else
3449 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00003450 /*
3451 * Removed since imported components will be hold by the main schema only.
3452 *
Daniel Veillard3646d642004-06-02 19:19:14 +00003453 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003454 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003455 else
3456 import = xmlHashLookup(schema->schemasImports, namespace);
3457 if (import != NULL) {
3458 ret = xmlSchemaGetGroup(import->schema, name, namespace);
3459 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
3460 return (ret);
3461 else
3462 ret = NULL;
3463 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003464 */
Daniel Veillard3646d642004-06-02 19:19:14 +00003465#ifdef DEBUG
3466 if (ret == NULL) {
3467 if (namespace == NULL)
3468 fprintf(stderr, "Unable to lookup group %s", name);
3469 else
3470 fprintf(stderr, "Unable to lookup group %s:%s", name,
3471 namespace);
3472 }
3473#endif
3474 return (ret);
3475}
3476
Daniel Veillard4255d502002-04-16 15:50:10 +00003477/************************************************************************
3478 * *
3479 * Parsing functions *
3480 * *
3481 ************************************************************************/
3482
3483#define IS_BLANK_NODE(n) \
3484 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content)))
3485
3486/**
3487 * xmlSchemaIsBlank:
3488 * @str: a string
3489 *
3490 * Check if a string is ignorable
3491 *
3492 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
3493 */
3494static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003495xmlSchemaIsBlank(xmlChar * str)
3496{
Daniel Veillard4255d502002-04-16 15:50:10 +00003497 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003498 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003499 while (*str != 0) {
William M. Brack76e95df2003-10-18 16:20:14 +00003500 if (!(IS_BLANK_CH(*str)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003501 return (0);
3502 str++;
Daniel Veillard4255d502002-04-16 15:50:10 +00003503 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003504 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003505}
3506
3507/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003508 * xmlSchemaAddAssembledItem:
3509 * @ctxt: a schema parser context
3510 * @schema: the schema being built
3511 * @item: the item
3512 *
3513 * Add a item to the schema's list of current items.
3514 * This is used if the schema was already constructed and
3515 * new schemata need to be added to it.
3516 * *WARNING* this interface is highly subject to change.
3517 *
3518 * Returns 0 if suceeds and -1 if an internal error occurs.
3519 */
3520static int
3521xmlSchemaAddAssembledItem(xmlSchemaParserCtxtPtr ctxt,
3522 xmlSchemaTypePtr item)
3523{
3524 static int growSize = 100;
3525 xmlSchemaAssemblePtr ass;
3526
3527 ass = ctxt->assemble;
3528 if (ass->sizeItems < 0) {
3529 /* If disabled. */
3530 return (0);
3531 }
3532 if (ass->sizeItems <= 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003533 ass->items = (void **) xmlMalloc(growSize * sizeof(xmlSchemaTypePtr));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003534 if (ass->items == NULL) {
3535 xmlSchemaPErrMemory(ctxt,
3536 "allocating new item buffer", NULL);
3537 return (-1);
3538 }
3539 ass->sizeItems = growSize;
3540 } else if (ass->sizeItems <= ass->nbItems) {
3541 ass->sizeItems *= 2;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003542 ass->items = (void **) xmlRealloc(ass->items,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003543 ass->sizeItems * sizeof(xmlSchemaTypePtr));
3544 if (ass->items == NULL) {
3545 xmlSchemaPErrMemory(ctxt,
3546 "growing item buffer", NULL);
3547 ass->sizeItems = 0;
3548 return (-1);
3549 }
3550 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003551 /* ass->items[ass->nbItems++] = (void *) item; */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003552 ((xmlSchemaTypePtr *) ass->items)[ass->nbItems++] = (void *) item;
3553 return (0);
3554}
3555
3556/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003557 * xmlSchemaAddNotation:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003558 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003559 * @schema: the schema being built
3560 * @name: the item name
3561 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00003562 * Add an XML schema annotation declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00003563 * *WARNING* this interface is highly subject to change
3564 *
3565 * Returns the new struture or NULL in case of error
3566 */
3567static xmlSchemaNotationPtr
3568xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00003569 const xmlChar *name)
Daniel Veillard4255d502002-04-16 15:50:10 +00003570{
3571 xmlSchemaNotationPtr ret = NULL;
3572 int val;
3573
3574 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3575 return (NULL);
3576
3577 if (schema->notaDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003578 schema->notaDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003579 if (schema->notaDecl == NULL)
3580 return (NULL);
3581
3582 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
3583 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003584 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003585 return (NULL);
3586 }
3587 memset(ret, 0, sizeof(xmlSchemaNotation));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003588 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003589 val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
3590 ret);
3591 if (val != 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00003592 /*
3593 * TODO: This should never happen, since a unique name will be computed.
3594 * If it fails, then an other internal error must have occured.
3595 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003596 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
3597 XML_SCHEMAP_REDEFINED_NOTATION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003598 "Annotation declaration '%s' is already declared.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003599 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003600 xmlFree(ret);
3601 return (NULL);
3602 }
3603 return (ret);
3604}
3605
3606
3607/**
3608 * xmlSchemaAddAttribute:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003609 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003610 * @schema: the schema being built
3611 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003612 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00003613 *
3614 * Add an XML schema Attrribute declaration
3615 * *WARNING* this interface is highly subject to change
3616 *
3617 * Returns the new struture or NULL in case of error
3618 */
3619static xmlSchemaAttributePtr
3620xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003621 const xmlChar * name, const xmlChar * namespace,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003622 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00003623{
3624 xmlSchemaAttributePtr ret = NULL;
3625 int val;
3626
3627 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3628 return (NULL);
3629
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003630#ifdef DEBUG
3631 fprintf(stderr, "Adding attribute %s\n", name);
3632 if (namespace != NULL)
3633 fprintf(stderr, " target namespace %s\n", namespace);
3634#endif
3635
Daniel Veillard4255d502002-04-16 15:50:10 +00003636 if (schema->attrDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003637 schema->attrDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003638 if (schema->attrDecl == NULL)
3639 return (NULL);
3640
3641 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
3642 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003643 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003644 return (NULL);
3645 }
3646 memset(ret, 0, sizeof(xmlSchemaAttribute));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003647 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00003648 ret->targetNamespace = namespace;
Daniel Veillard4255d502002-04-16 15:50:10 +00003649 val = xmlHashAddEntry3(schema->attrDecl, name,
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00003650 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003651 if (val != 0) {
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003652 if (topLevel) {
3653 xmlSchemaPCustomErr(ctxt,
3654 XML_SCHEMAP_REDEFINED_ATTR,
3655 NULL, NULL, node,
3656 "A global attribute declaration with the name '%s' does "
3657 "already exist", name);
3658 xmlFree(ret);
3659 return (NULL);
3660 } else {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003661 char buf[30];
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003662 /*
3663 * Using the ctxt->container for xmlHashAddEntry3 is ambigious
3664 * in the scenario:
3665 * 1. multiple top-level complex types have different target
3666 * namespaces but have the SAME NAME; this can happen if
3667 * schemata are imported
3668 * 2. those complex types contain attributes with an equal name
3669 * 3. those attributes are in no namespace
3670 * We will compute a new context string.
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003671 */
3672 snprintf(buf, 29, "#aCont%d", ctxt->counter++ + 1);
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003673 val = xmlHashAddEntry3(schema->attrDecl, name,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00003674 namespace, xmlDictLookup(ctxt->dict, BAD_CAST buf, -1), ret);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003675
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003676 if (val != 0) {
3677 xmlSchemaPCustomErr(ctxt,
3678 XML_SCHEMAP_INTERNAL,
3679 NULL, NULL, node,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003680 "Internal error: xmlSchemaAddAttribute, "
3681 "a dublicate attribute declaration with the name '%s' "
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003682 "could not be added to the hash.", name);
3683 xmlFree(ret);
3684 return (NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003685 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003686 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003687 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003688 if (ctxt->assemble != NULL)
3689 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003690 return (ret);
3691}
3692
3693/**
3694 * xmlSchemaAddAttributeGroup:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003695 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003696 * @schema: the schema being built
3697 * @name: the item name
3698 *
3699 * Add an XML schema Attrribute Group declaration
3700 *
3701 * Returns the new struture or NULL in case of error
3702 */
3703static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003704xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00003705 xmlSchemaPtr schema, const xmlChar * name,
3706 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003707{
3708 xmlSchemaAttributeGroupPtr ret = NULL;
3709 int val;
3710
3711 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3712 return (NULL);
3713
3714 if (schema->attrgrpDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003715 schema->attrgrpDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003716 if (schema->attrgrpDecl == NULL)
3717 return (NULL);
3718
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003719 ret =
3720 (xmlSchemaAttributeGroupPtr)
3721 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00003722 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003723 xmlSchemaPErrMemory(ctxt, "allocating attribute group", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003724 return (NULL);
3725 }
3726 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003727 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003728 val = xmlHashAddEntry3(schema->attrgrpDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003729 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003730 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003731 xmlSchemaPCustomErr(ctxt,
3732 XML_SCHEMAP_REDEFINED_ATTRGROUP,
3733 NULL, NULL, node,
3734 "A global attribute group definition with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003735 xmlFree(ret);
3736 return (NULL);
3737 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003738 if (ctxt->assemble != NULL)
3739 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003740 return (ret);
3741}
3742
3743/**
3744 * xmlSchemaAddElement:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003745 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003746 * @schema: the schema being built
3747 * @name: the type name
3748 * @namespace: the type namespace
3749 *
3750 * Add an XML schema Element declaration
3751 * *WARNING* this interface is highly subject to change
3752 *
3753 * Returns the new struture or NULL in case of error
3754 */
3755static xmlSchemaElementPtr
3756xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003757 const xmlChar * name, const xmlChar * namespace,
3758 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00003759{
3760 xmlSchemaElementPtr ret = NULL;
3761 int val;
3762
3763 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3764 return (NULL);
3765
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003766#ifdef DEBUG
3767 fprintf(stderr, "Adding element %s\n", name);
3768 if (namespace != NULL)
3769 fprintf(stderr, " target namespace %s\n", namespace);
3770#endif
3771
Daniel Veillard4255d502002-04-16 15:50:10 +00003772 if (schema->elemDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003773 schema->elemDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003774 if (schema->elemDecl == NULL)
3775 return (NULL);
3776
3777 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
3778 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003779 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003780 return (NULL);
3781 }
3782 memset(ret, 0, sizeof(xmlSchemaElement));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003783 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003784 val = xmlHashAddEntry3(schema->elemDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003785 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003786 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003787 if (topLevel) {
3788 xmlSchemaPCustomErr(ctxt,
3789 XML_SCHEMAP_REDEFINED_ELEMENT,
3790 NULL, NULL, node,
3791 "A global element declaration with the name '%s' does "
3792 "already exist", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003793 xmlFree(ret);
3794 return (NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00003795 } else {
3796 char buf[30];
3797
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003798 snprintf(buf, 29, "#eCont%d", ctxt->counter++ + 1);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003799 val = xmlHashAddEntry3(schema->elemDecl, name,
3800 namespace, (xmlChar *) buf, ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00003801 if (val != 0) {
3802 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003803 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00003804 NULL, NULL, node,
3805 "Internal error: xmlSchemaAddElement, "
3806 "a dublicate element declaration with the name '%s' "
3807 "could not be added to the hash.", name);
3808 xmlFree(ret);
3809 return (NULL);
3810 }
3811 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00003812
Daniel Veillard4255d502002-04-16 15:50:10 +00003813 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003814 if (ctxt->assemble != NULL)
3815 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003816 return (ret);
3817}
3818
3819/**
3820 * xmlSchemaAddType:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003821 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003822 * @schema: the schema being built
3823 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003824 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00003825 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00003826 * Add an XML schema item
Daniel Veillard4255d502002-04-16 15:50:10 +00003827 * *WARNING* this interface is highly subject to change
3828 *
3829 * Returns the new struture or NULL in case of error
3830 */
3831static xmlSchemaTypePtr
3832xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003833 const xmlChar * name, const xmlChar * namespace,
3834 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003835{
3836 xmlSchemaTypePtr ret = NULL;
3837 int val;
3838
3839 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3840 return (NULL);
3841
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003842#ifdef DEBUG
3843 fprintf(stderr, "Adding type %s\n", name);
3844 if (namespace != NULL)
3845 fprintf(stderr, " target namespace %s\n", namespace);
3846#endif
3847
Daniel Veillard4255d502002-04-16 15:50:10 +00003848 if (schema->typeDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003849 schema->typeDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003850 if (schema->typeDecl == NULL)
3851 return (NULL);
3852
3853 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
3854 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003855 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003856 return (NULL);
3857 }
3858 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003859 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003860 ret->redef = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003861 val = xmlHashAddEntry2(schema->typeDecl, name, namespace, ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00003862 if (val != 0) {
3863 if (ctxt->includes == 0) {
3864 xmlSchemaPCustomErr(ctxt,
3865 XML_SCHEMAP_REDEFINED_TYPE,
3866 NULL, NULL, node,
3867 "A global type definition with the name '%s' does already exist", name);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003868 xmlFree(ret);
3869 return (NULL);
3870 } else {
3871 xmlSchemaTypePtr prev;
3872
3873 prev = xmlHashLookup2(schema->typeDecl, name, namespace);
3874 if (prev == NULL) {
3875 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003876 XML_ERR_INTERNAL_ERROR,
3877 "Internal error: xmlSchemaAddType, on type "
3878 "'%s'.\n",
3879 name, NULL);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003880 xmlFree(ret);
3881 return (NULL);
3882 }
3883 ret->redef = prev->redef;
3884 prev->redef = ret;
3885 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003886 }
3887 ret->minOccurs = 1;
3888 ret->maxOccurs = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +00003889 ret->attributeUses = NULL;
3890 ret->attributeWildcard = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003891 if (ctxt->assemble != NULL)
3892 xmlSchemaAddAssembledItem(ctxt,ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003893 return (ret);
3894}
3895
3896/**
3897 * xmlSchemaAddGroup:
3898 * @ctxt: a schema validation context
3899 * @schema: the schema being built
3900 * @name: the group name
3901 *
3902 * Add an XML schema Group definition
3903 *
3904 * Returns the new struture or NULL in case of error
3905 */
3906static xmlSchemaTypePtr
3907xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00003908 const xmlChar *name, const xmlChar *namespaceName,
3909 xmlNodePtr node)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003910{
3911 xmlSchemaTypePtr ret = NULL;
3912 int val;
3913
3914 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3915 return (NULL);
3916
3917 if (schema->groupDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003918 schema->groupDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003919 if (schema->groupDecl == NULL)
3920 return (NULL);
3921
3922 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
3923 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003924 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003925 return (NULL);
3926 }
3927 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003928 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003929 val =
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00003930 xmlHashAddEntry2(schema->groupDecl, name, namespaceName,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003931 ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003932 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003933 xmlSchemaPCustomErr(ctxt,
3934 XML_SCHEMAP_REDEFINED_GROUP,
3935 NULL, NULL, node,
3936 "A global model group definition with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003937 xmlFree(ret);
3938 return (NULL);
3939 }
3940 ret->minOccurs = 1;
3941 ret->maxOccurs = 1;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003942 if (ctxt->assemble != NULL)
3943 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003944 return (ret);
3945}
3946
Daniel Veillard3646d642004-06-02 19:19:14 +00003947/**
3948 * xmlSchemaNewWildcardNs:
3949 * @ctxt: a schema validation context
3950 *
3951 * Creates a new wildcard namespace constraint.
3952 *
3953 * Returns the new struture or NULL in case of error
3954 */
3955static xmlSchemaWildcardNsPtr
3956xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
3957{
3958 xmlSchemaWildcardNsPtr ret;
3959
3960 ret = (xmlSchemaWildcardNsPtr)
3961 xmlMalloc(sizeof(xmlSchemaWildcardNs));
3962 if (ret == NULL) {
3963 xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
3964 return (NULL);
3965 }
3966 ret->value = NULL;
3967 ret->next = NULL;
3968 return (ret);
3969}
3970
3971/**
3972 * xmlSchemaAddWildcard:
3973 * @ctxt: a schema validation context
Daniel Veillardc0826a72004-08-10 14:17:33 +00003974 * Adds a wildcard. It corresponds to a
3975 * xsd:anyAttribute and is used as storage for namespace
3976 * constraints on a xsd:any.
Daniel Veillard3646d642004-06-02 19:19:14 +00003977 *
3978 * Returns the new struture or NULL in case of error
3979 */
3980static xmlSchemaWildcardPtr
3981xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt)
3982{
3983 xmlSchemaWildcardPtr ret = NULL;
3984
3985 if (ctxt == NULL)
3986 return (NULL);
3987
3988 ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
3989 if (ret == NULL) {
3990 xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
3991 return (NULL);
3992 }
3993 memset(ret, 0, sizeof(xmlSchemaWildcard));
3994 ret->minOccurs = 1;
3995 ret->maxOccurs = 1;
3996
3997 return (ret);
3998}
3999
Daniel Veillard4255d502002-04-16 15:50:10 +00004000/************************************************************************
4001 * *
4002 * Utilities for parsing *
4003 * *
4004 ************************************************************************/
4005
4006/**
4007 * xmlGetQNameProp:
4008 * @ctxt: a schema validation context
4009 * @node: a subtree containing XML Schema informations
4010 * @name: the attribute name
4011 * @namespace: the result namespace if any
4012 *
4013 * Extract a QName Attribute value
4014 *
4015 * Returns the NCName or NULL if not found, and also update @namespace
4016 * with the namespace URI
4017 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004018static const xmlChar *
Daniel Veillard4255d502002-04-16 15:50:10 +00004019xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004020 const char *name, const xmlChar ** namespace)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004021{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004022 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00004023 xmlNsPtr ns;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004024 const xmlChar *ret, *prefix;
4025 int len;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004026 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00004027
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004028 *namespace = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004029 attr = xmlSchemaGetPropNode(node, name);
4030 if (attr == NULL)
4031 return (NULL);
4032 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004033
Daniel Veillard4255d502002-04-16 15:50:10 +00004034 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004035 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004036
Daniel Veillardba0153a2004-04-01 10:42:31 +00004037 if (!strchr((char *) val, ':')) {
Daniel Veillardebcdebd2004-03-05 00:15:50 +00004038 ns = xmlSearchNs(node->doc, node, 0);
4039 if (ns) {
4040 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
4041 return (val);
4042 }
4043 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004044 ret = xmlSplitQName3(val, &len);
4045 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004046 return (val);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004047 }
4048 ret = xmlDictLookup(ctxt->dict, ret, -1);
4049 prefix = xmlDictLookup(ctxt->dict, val, len);
Daniel Veillard4255d502002-04-16 15:50:10 +00004050
4051 ns = xmlSearchNs(node->doc, node, prefix);
4052 if (ns == NULL) {
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004053 xmlSchemaPSimpleTypeErr(ctxt, XML_SCHEMAP_PREFIX_UNDEFINED,
4054 NULL, NULL, (xmlNodePtr) attr,
4055 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, val,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004056 "The QName value '%s' has no corresponding namespace "
4057 "declaration in scope", val, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004058 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004059 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004060 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004061 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004062}
4063
4064/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00004065 * xmlSchemaPValAttrNodeQNameValue:
4066 * @ctxt: a schema parser context
4067 * @schema: the schema context
4068 * @ownerDes: the designation of the parent element
4069 * @ownerItem: the parent as a schema object
4070 * @value: the QName value
4071 * @local: the resulting local part if found, the attribute value otherwise
4072 * @uri: the resulting namespace URI if found
4073 *
4074 * Extracts the local name and the URI of a QName value and validates it.
4075 * This one is intended to be used on attribute values that
4076 * should resolve to schema components.
4077 *
4078 * Returns 0, in case the QName is valid, a positive error code
4079 * if not valid and -1 if an internal error occurs.
4080 */
4081static int
4082xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
4083 xmlSchemaPtr schema,
4084 xmlChar **ownerDes,
4085 xmlSchemaTypePtr ownerItem,
4086 xmlAttrPtr attr,
4087 const xmlChar *value,
4088 const xmlChar **uri,
4089 const xmlChar **prefix,
4090 const xmlChar **local)
4091{
4092 const xmlChar *pref;
4093 xmlNsPtr ns;
4094 int len, ret;
4095
4096 *uri = NULL;
4097 *local = NULL;
4098 if (prefix != 0)
4099 *prefix = NULL;
4100 ret = xmlValidateQName(value, 1);
4101 if (ret > 0) {
4102 xmlSchemaPSimpleTypeErr(ctxt,
4103 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4104 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004105 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
4106 "QName", value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004107 NULL, NULL, NULL);
4108 *local = value;
4109 return (ctxt->err);
4110 } else if (ret < 0)
4111 return (-1);
4112
4113 if (!strchr((char *) value, ':')) {
4114 ns = xmlSearchNs(attr->doc, attr->parent, 0);
4115 if (ns)
4116 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
4117 else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
4118 /*
4119 * This one takes care of included schemas with no
4120 * target namespace.
4121 */
4122 *uri = schema->targetNamespace;
4123 }
4124 *local = value;
4125 return (0);
4126 }
4127 /*
4128 * At this point xmlSplitQName3 has to return a local name.
4129 */
4130 *local = xmlSplitQName3(value, &len);
4131 *local = xmlDictLookup(ctxt->dict, *local, -1);
4132 pref = xmlDictLookup(ctxt->dict, value, len);
4133 if (prefix != 0)
4134 *prefix = pref;
4135 ns = xmlSearchNs(attr->doc, attr->parent, pref);
4136 if (ns == NULL) {
4137 xmlSchemaPSimpleTypeErr(ctxt,
4138 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4139 ownerDes, ownerItem, (xmlNodePtr) attr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004140 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), "QName", value,
4141 "The QName value '%s' has no corresponding namespace "
4142 "declaration in scope", value, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004143 return (ctxt->err);
4144 } else {
4145 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
4146 }
4147 return (0);
4148}
4149
4150/**
4151 * xmlSchemaPValAttrNodeQName:
4152 * @ctxt: a schema parser context
4153 * @schema: the schema context
4154 * @ownerDes: the designation of the owner element
4155 * @ownerItem: the owner as a schema object
4156 * @attr: the attribute node
4157 * @local: the resulting local part if found, the attribute value otherwise
4158 * @uri: the resulting namespace URI if found
4159 *
4160 * Extracts and validates the QName of an attribute value.
4161 * This one is intended to be used on attribute values that
4162 * should resolve to schema components.
4163 *
4164 * Returns 0, in case the QName is valid, a positive error code
4165 * if not valid and -1 if an internal error occurs.
4166 */
4167static int
4168xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
4169 xmlSchemaPtr schema,
4170 xmlChar **ownerDes,
4171 xmlSchemaTypePtr ownerItem,
4172 xmlAttrPtr attr,
4173 const xmlChar **uri,
4174 const xmlChar **prefix,
4175 const xmlChar **local)
4176{
4177 const xmlChar *value;
4178
4179 value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4180 return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
4181 ownerDes, ownerItem, attr, value, uri, prefix, local));
4182}
4183
4184/**
4185 * xmlSchemaPValAttrQName:
4186 * @ctxt: a schema parser context
4187 * @schema: the schema context
4188 * @ownerDes: the designation of the parent element
4189 * @ownerItem: the owner as a schema object
4190 * @ownerElem: the parent node of the attribute
4191 * @name: the name of the attribute
4192 * @local: the resulting local part if found, the attribute value otherwise
4193 * @uri: the resulting namespace URI if found
4194 *
4195 * Extracts and validates the QName of an attribute value.
4196 *
4197 * Returns 0, in case the QName is valid, a positive error code
4198 * if not valid and -1 if an internal error occurs.
4199 */
4200static int
4201xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
4202 xmlSchemaPtr schema,
4203 xmlChar **ownerDes,
4204 xmlSchemaTypePtr ownerItem,
4205 xmlNodePtr ownerElem,
4206 const char *name,
4207 const xmlChar **uri,
4208 const xmlChar **prefix,
4209 const xmlChar **local)
4210{
4211 xmlAttrPtr attr;
4212
4213 attr = xmlSchemaGetPropNode(ownerElem, name);
4214 if (attr == NULL) {
4215 *local = NULL;
4216 *uri = NULL;
4217 return (0);
4218 }
4219 return (xmlSchemaPValAttrNodeQName(ctxt, schema,
4220 ownerDes, ownerItem, attr, uri, prefix, local));
4221}
4222
4223/**
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00004224 * xmlSchemaPValAttrID:
4225 * @ctxt: a schema parser context
4226 * @schema: the schema context
4227 * @ownerDes: the designation of the parent element
4228 * @ownerItem: the owner as a schema object
4229 * @ownerElem: the parent node of the attribute
4230 * @name: the name of the attribute
4231 *
4232 * Extracts and validates the ID of an attribute value.
4233 *
4234 * Returns 0, in case the ID is valid, a positive error code
4235 * if not valid and -1 if an internal error occurs.
4236 */
4237static int
4238xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,
4239 xmlChar **ownerDes,
4240 xmlSchemaTypePtr ownerItem,
4241 xmlNodePtr ownerElem,
4242 const xmlChar *name)
4243{
4244 int ret;
4245 xmlChar *value;
4246 xmlAttrPtr attr;
4247
4248 value = xmlGetNoNsProp(ownerElem, name);
4249 if (value == NULL)
4250 return (0);
4251
4252 attr = xmlSchemaGetPropNode(ownerElem, (const char *) name);
4253 if (attr == NULL)
4254 return (-1);
4255
4256 ret = xmlValidateNCName(BAD_CAST value, 1);
4257 if (ret == 0) {
4258 /*
4259 * NOTE: the IDness might have already be declared in the DTD
4260 */
4261 if (attr->atype != XML_ATTRIBUTE_ID) {
4262 xmlIDPtr res;
4263 xmlChar *strip;
4264
4265 /*
4266 * TODO: Use xmlSchemaStrip here; it's not exported at this
4267 * moment.
4268 */
4269 strip = xmlSchemaCollapseString(BAD_CAST value);
4270 if (strip != NULL)
4271 value = strip;
4272 res = xmlAddID(NULL, ownerElem->doc, BAD_CAST value, attr);
4273 if (res == NULL) {
4274 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
4275 xmlSchemaPSimpleTypeErr(ctxt,
4276 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4277 ownerDes, ownerItem, (xmlNodePtr) attr,
4278 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00004279 NULL, NULL, "The ID '%s' is already defined",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00004280 BAD_CAST value, NULL);
4281 } else
4282 attr->atype = XML_ATTRIBUTE_ID;
4283 if (strip != NULL)
4284 xmlFree(strip);
4285 }
4286 } else if (ret > 0) {
4287 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
4288 xmlSchemaPSimpleTypeErr(ctxt,
4289 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4290 ownerDes, ownerItem, (xmlNodePtr) attr,
4291 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
4292 NULL, BAD_CAST value, NULL, NULL, NULL);
4293 }
4294 xmlFree(value);
4295
4296 return (ret);
4297}
4298
4299/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004300 * xmlGetMaxOccurs:
4301 * @ctxt: a schema validation context
4302 * @node: a subtree containing XML Schema informations
4303 *
4304 * Get the maxOccurs property
4305 *
4306 * Returns the default if not found, or the value
4307 */
4308static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004309xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
4310 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004311{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004312 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00004313 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004314 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00004315
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004316 attr = xmlSchemaGetPropNode(node, "maxOccurs");
4317 if (attr == NULL)
4318 return (def);
4319 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00004320
4321 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004322 if (max != UNBOUNDED) {
4323 xmlSchemaPSimpleTypeErr(ctxt,
4324 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4325 /* XML_SCHEMAP_INVALID_MINOCCURS, */
4326 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
4327 val, NULL, NULL, NULL);
4328 return (def);
4329 } else
4330 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00004331 }
4332
4333 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00004334 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004335 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004336 if (*cur == 0) {
4337 xmlSchemaPSimpleTypeErr(ctxt,
4338 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4339 /* XML_SCHEMAP_INVALID_MINOCCURS, */
4340 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
4341 val, NULL, NULL, NULL);
4342 return (def);
4343 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004344 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004345 ret = ret * 10 + (*cur - '0');
4346 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00004347 }
William M. Brack76e95df2003-10-18 16:20:14 +00004348 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004349 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004350 /*
4351 * TODO: Restrict the maximal value to Integer.
4352 */
4353 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
4354 xmlSchemaPSimpleTypeErr(ctxt,
4355 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4356 /* XML_SCHEMAP_INVALID_MINOCCURS, */
4357 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
4358 val, NULL, NULL, NULL);
4359 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00004360 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004361 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004362}
4363
4364/**
4365 * xmlGetMinOccurs:
4366 * @ctxt: a schema validation context
4367 * @node: a subtree containing XML Schema informations
4368 *
4369 * Get the minOccurs property
4370 *
4371 * Returns the default if not found, or the value
4372 */
4373static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004374xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
4375 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004376{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004377 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00004378 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004379 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00004380
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004381 attr = xmlSchemaGetPropNode(node, "minOccurs");
4382 if (attr == NULL)
4383 return (def);
4384 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00004385 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00004386 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004387 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004388 if (*cur == 0) {
4389 xmlSchemaPSimpleTypeErr(ctxt,
4390 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4391 /* XML_SCHEMAP_INVALID_MINOCCURS, */
4392 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
4393 val, NULL, NULL, NULL);
4394 return (def);
4395 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004396 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004397 ret = ret * 10 + (*cur - '0');
4398 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00004399 }
William M. Brack76e95df2003-10-18 16:20:14 +00004400 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004401 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004402 /*
4403 * TODO: Restrict the maximal value to Integer.
4404 */
4405 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
4406 xmlSchemaPSimpleTypeErr(ctxt,
4407 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4408 /* XML_SCHEMAP_INVALID_MINOCCURS, */
4409 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
4410 val, NULL, NULL, NULL);
4411 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00004412 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004413 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004414}
4415
4416/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004417 * xmlSchemaPGetBoolNodeValue:
4418 * @ctxt: a schema validation context
4419 * @ownerDes: owner designation
4420 * @ownerItem: the owner as a schema item
4421 * @node: the node holding the value
4422 *
4423 * Converts a boolean string value into 1 or 0.
4424 *
4425 * Returns 0 or 1.
4426 */
4427static int
4428xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
4429 xmlChar **ownerDes,
4430 xmlSchemaTypePtr ownerItem,
4431 xmlNodePtr node)
4432{
4433 xmlChar *value = NULL;
4434 int res = 0;
4435
4436 value = xmlNodeGetContent(node);
4437 /*
4438 * 3.2.2.1 Lexical representation
4439 * An instance of a datatype that is defined as ·boolean·
4440 * can have the following legal literals {true, false, 1, 0}.
4441 */
4442 if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
4443 res = 1;
4444 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
4445 res = 0;
4446 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
4447 res = 1;
4448 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
4449 res = 0;
4450 else {
4451 xmlSchemaPSimpleTypeErr(ctxt,
4452 XML_SCHEMAP_INVALID_BOOLEAN,
4453 ownerDes, ownerItem, node,
4454 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
4455 "(1 | 0 | true | false)", BAD_CAST value,
4456 NULL, NULL, NULL);
4457 }
4458 if (value != NULL)
4459 xmlFree(value);
4460 return (res);
4461}
4462
4463/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004464 * xmlGetBooleanProp:
4465 * @ctxt: a schema validation context
4466 * @node: a subtree containing XML Schema informations
4467 * @name: the attribute name
4468 * @def: the default value
4469 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00004470 * Evaluate if a boolean property is set
Daniel Veillard4255d502002-04-16 15:50:10 +00004471 *
4472 * Returns the default if not found, 0 if found to be false,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004473 * 1 if found to be true
Daniel Veillard4255d502002-04-16 15:50:10 +00004474 */
4475static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00004476xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
4477 xmlChar **ownerDes,
4478 xmlSchemaTypePtr ownerItem,
4479 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004480 const char *name, int def)
4481{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004482 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00004483
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004484 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004485 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004486 return (def);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004487 /*
4488 * 3.2.2.1 Lexical representation
4489 * An instance of a datatype that is defined as ·boolean·
4490 * can have the following legal literals {true, false, 1, 0}.
4491 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004492 if (xmlStrEqual(val, BAD_CAST "true"))
4493 def = 1;
4494 else if (xmlStrEqual(val, BAD_CAST "false"))
4495 def = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004496 else if (xmlStrEqual(val, BAD_CAST "1"))
4497 def = 1;
4498 else if (xmlStrEqual(val, BAD_CAST "0"))
4499 def = 0;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00004500 else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004501 xmlSchemaPSimpleTypeErr(ctxt,
4502 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00004503 ownerDes, ownerItem,
4504 (xmlNodePtr) xmlSchemaGetPropNode(node, name),
William M. Brack2f2a6632004-08-20 23:09:47 +00004505 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
4506 "(1 | 0 | true | false)", val, NULL, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004507 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004508 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00004509}
4510
4511/************************************************************************
4512 * *
4513 * Shema extraction from an Infoset *
4514 * *
4515 ************************************************************************/
4516static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
4517 ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00004518 xmlNodePtr node,
4519 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004520static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
4521 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00004522 xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00004523 xmlNodePtr node,
4524 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004525static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
4526 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00004527 xmlSchemaPtr schema,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00004528 xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00004529static xmlSchemaTypePtr xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt,
4530 xmlSchemaPtr schema,
4531 xmlNodePtr node);
4532static xmlSchemaTypePtr xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt,
4533 xmlSchemaPtr schema,
4534 xmlNodePtr node);
4535static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
4536 ctxt,
4537 xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00004538 xmlNodePtr node,
4539 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00004540static xmlSchemaAttributeGroupPtr
4541xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00004542 xmlSchemaPtr schema, xmlNodePtr node,
4543 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00004544static xmlSchemaTypePtr xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt,
4545 xmlSchemaPtr schema,
4546 xmlNodePtr node);
4547static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
4548 xmlSchemaPtr schema,
4549 xmlNodePtr node);
Daniel Veillard3646d642004-06-02 19:19:14 +00004550static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004551xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
4552 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00004553
4554/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004555 * xmlSchemaPValAttrNodeValue:
Daniel Veillard01fa6152004-06-29 17:04:39 +00004556 *
4557 * @ctxt: a schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00004558 * @ownerDes: the designation of the parent element
4559 * @ownerItem: the schema object owner if existent
4560 * @attr: the schema attribute node being validated
4561 * @value: the value
4562 * @type: the built-in type to be validated against
Daniel Veillard01fa6152004-06-29 17:04:39 +00004563 *
4564 * Validates a value against the given built-in type.
4565 * This one is intended to be used internally for validation
4566 * of schema attribute values during parsing of the schema.
4567 *
4568 * Returns 0 if the value is valid, a positive error code
4569 * number otherwise and -1 in case of an internal or API error.
4570 */
4571static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00004572xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr ctxt,
4573 xmlChar **ownerDes,
4574 xmlSchemaTypePtr ownerItem,
4575 xmlAttrPtr attr,
4576 const xmlChar *value,
4577 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +00004578{
Daniel Veillard01fa6152004-06-29 17:04:39 +00004579
Daniel Veillardc0826a72004-08-10 14:17:33 +00004580 int ret = 0;
4581
4582 /*
4583 * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
4584 * one is really meant to be used internally, so better not.
4585 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00004586 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00004587 return (-1);
4588 if (type->type != XML_SCHEMA_TYPE_BASIC) {
4589 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004590 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004591 "Internal error: xmlSchemaPValAttrNodeValue, the given "
Daniel Veillardc0826a72004-08-10 14:17:33 +00004592 "type '%s' is not a built-in type.\n",
4593 type->name, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00004594 return (-1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004595 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00004596 switch (type->builtInType) {
4597 case XML_SCHEMAS_NCNAME:
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004598 case XML_SCHEMAS_QNAME:
4599 case XML_SCHEMAS_ANYURI:
4600 case XML_SCHEMAS_TOKEN:
4601 case XML_SCHEMAS_LANGUAGE:
4602 ret = xmlSchemaValPredefTypeNode(type, value, NULL, (xmlNodePtr) attr);
4603 break;
4604
4605 /*
4606 case XML_SCHEMAS_NCNAME:
Daniel Veillard01fa6152004-06-29 17:04:39 +00004607 ret = xmlValidateNCName(value, 1);
4608 break;
4609 case XML_SCHEMAS_QNAME:
Daniel Veillardc0826a72004-08-10 14:17:33 +00004610 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004611 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004612 "Internal error: xmlSchemaPvalueAttrNode, use "
4613 "the function xmlSchemaExtractSchemaQNamePropvalueidated "
4614 "for extracting QName valueues instead.\n",
4615 NULL, NULL);
4616 return (-1);
4617 case XML_SCHEMAS_ANYURI:
4618 if (value != NULL) {
4619 xmlURIPtr uri = xmlParseURI((const char *) value);
4620 if (uri == NULL)
4621 ret = 1;
4622 else
4623 xmlFreeURI(uri);
Daniel Veillard01fa6152004-06-29 17:04:39 +00004624 }
4625 break;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004626 case XML_SCHEMAS_TOKEN: {
4627 const xmlChar *cur = value;
4628
4629 if (IS_BLANK_CH(*cur)) {
4630 ret = 1;
4631 } else while (*cur != 0) {
4632 if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) {
4633 ret = 1;
4634 break;
4635 } else if (*cur == ' ') {
4636 cur++;
4637 if ((*cur == 0) || (*cur == ' ')) {
4638 ret = 1;
4639 break;
4640 }
4641 } else {
4642 cur++;
4643 }
4644 }
4645 }
4646 break;
4647 case XML_SCHEMAS_LANGUAGE:
4648 if (xmlCheckLanguageID(value) != 1)
4649 ret = 1;
4650 break;
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004651 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00004652 default: {
4653 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004654 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004655 "Internal error: xmlSchemaPValAttrNodeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +00004656 "valueidation using the type '%s' is not implemented "
4657 "yet.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +00004658 type->name, NULL);
4659 return (-1);
4660 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004661 }
4662 /*
4663 * TODO: Should we use the S4S error codes instead?
4664 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004665 if (ret < 0) {
4666 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
4667 XML_SCHEMAP_INTERNAL,
4668 "Internal error: xmlSchemaPValAttrNodeValue, "
4669 "failed to validate a schema attribute value.\n",
4670 NULL, NULL);
4671 return (-1);
4672 } else if (ret > 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004673 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
4674 xmlSchemaPSimpleTypeErr(ctxt,
4675 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2,
4676 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004677 type, NULL, value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004678 NULL, NULL, NULL);
4679 return(XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2);
4680 } else {
4681 xmlSchemaPSimpleTypeErr(ctxt,
4682 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
4683 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004684 type, NULL, value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004685 NULL, NULL, NULL);
4686 return(XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
4687 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00004688 }
4689 return (ret);
4690}
4691
4692/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00004693 * xmlSchemaPValAttrNode:
4694 *
4695 * @ctxt: a schema parser context
4696 * @ownerDes: the designation of the parent element
4697 * @ownerItem: the schema object owner if existent
4698 * @attr: the schema attribute node being validated
4699 * @type: the built-in type to be validated against
4700 * @value: the resulting value if any
4701 *
4702 * Extracts and validates a value against the given built-in type.
4703 * This one is intended to be used internally for validation
4704 * of schema attribute values during parsing of the schema.
4705 *
4706 * Returns 0 if the value is valid, a positive error code
4707 * number otherwise and -1 in case of an internal or API error.
4708 */
4709static int
4710xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
4711 xmlChar **ownerDes,
4712 xmlSchemaTypePtr ownerItem,
4713 xmlAttrPtr attr,
4714 xmlSchemaTypePtr type,
4715 const xmlChar **value)
4716{
4717 const xmlChar *val;
4718
4719 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
4720 return (-1);
4721
4722 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4723 if (value != NULL)
4724 *value = val;
4725
4726 return (xmlSchemaPValAttrNodeValue(ctxt, ownerDes, ownerItem, attr,
4727 val, type));
4728}
4729
4730/**
4731 * xmlSchemaPValAttr:
4732 *
4733 * @ctxt: a schema parser context
4734 * @node: the element node of the attribute
4735 * @ownerDes: the designation of the parent element
4736 * @ownerItem: the schema object owner if existent
4737 * @ownerElem: the owner element node
4738 * @name: the name of the schema attribute node
4739 * @type: the built-in type to be validated against
4740 * @value: the resulting value if any
4741 *
4742 * Extracts and validates a value against the given built-in type.
4743 * This one is intended to be used internally for validation
4744 * of schema attribute values during parsing of the schema.
4745 *
4746 * Returns 0 if the value is valid, a positive error code
4747 * number otherwise and -1 in case of an internal or API error.
4748 */
4749static int
4750xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
4751 xmlChar **ownerDes,
4752 xmlSchemaTypePtr ownerItem,
4753 xmlNodePtr ownerElem,
4754 const char *name,
4755 xmlSchemaTypePtr type,
4756 const xmlChar **value)
4757{
4758 xmlAttrPtr attr;
4759
4760 if ((ctxt == NULL) || (type == NULL)) {
4761 if (value != NULL)
4762 *value = NULL;
4763 return (-1);
4764 }
4765 if (type->type != XML_SCHEMA_TYPE_BASIC) {
4766 if (value != NULL)
4767 *value = NULL;
4768 xmlSchemaPErr(ctxt, ownerElem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004769 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004770 "Internal error: xmlSchemaPValAttr, the given "
4771 "type '%s' is not a built-in type.\n",
4772 type->name, NULL);
4773 return (-1);
4774 }
4775 attr = xmlSchemaGetPropNode(ownerElem, name);
4776 if (attr == NULL) {
4777 if (value != NULL)
4778 *value = NULL;
4779 return (0);
4780 }
4781 return (xmlSchemaPValAttrNode(ctxt, ownerDes, ownerItem, attr,
4782 type, value));
4783}
4784/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004785 * xmlSchemaParseAttrDecls:
4786 * @ctxt: a schema validation context
4787 * @schema: the schema being built
4788 * @node: a subtree containing XML Schema informations
4789 * @type: the hosting type
4790 *
4791 * parse a XML schema attrDecls declaration corresponding to
4792 * <!ENTITY % attrDecls
4793 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
4794 */
4795static xmlNodePtr
4796xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4797 xmlNodePtr child, xmlSchemaTypePtr type)
4798{
4799 xmlSchemaAttributePtr lastattr, attr;
4800
4801 lastattr = NULL;
4802 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004803 (IS_SCHEMA(child, "attributeGroup"))) {
4804 attr = NULL;
4805 if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00004806 attr = xmlSchemaParseAttribute(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004807 } else if (IS_SCHEMA(child, "attributeGroup")) {
4808 attr = (xmlSchemaAttributePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00004809 xmlSchemaParseAttributeGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004810 }
4811 if (attr != NULL) {
4812 if (lastattr == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00004813 if (type->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
4814 ((xmlSchemaAttributeGroupPtr) type)->attributes = attr;
4815 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004816 type->attributes = attr;
4817 lastattr = attr;
4818 } else {
4819 lastattr->next = attr;
4820 lastattr = attr;
4821 }
4822 }
4823 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004824 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004825 return (child);
Daniel Veillard4255d502002-04-16 15:50:10 +00004826}
4827
4828/**
4829 * xmlSchemaParseAnnotation:
4830 * @ctxt: a schema validation context
4831 * @schema: the schema being built
4832 * @node: a subtree containing XML Schema informations
4833 *
4834 * parse a XML schema Attrribute declaration
4835 * *WARNING* this interface is highly subject to change
4836 *
William M. Bracke7091952004-05-11 15:09:58 +00004837 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00004838 * 1 in case of success.
4839 */
4840static xmlSchemaAnnotPtr
4841xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4842 xmlNodePtr node)
4843{
4844 xmlSchemaAnnotPtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004845 xmlNodePtr child = NULL;
4846 xmlAttrPtr attr;
4847 int barked = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00004848
Daniel Veillardc0826a72004-08-10 14:17:33 +00004849 /*
4850 * INFO: S4S completed.
4851 */
4852 /*
4853 * id = ID
4854 * {any attributes with non-schema namespace . . .}>
4855 * Content: (appinfo | documentation)*
4856 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004857 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4858 return (NULL);
4859 ret = xmlSchemaNewAnnot(ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004860 attr = node->properties;
4861 while (attr != NULL) {
4862 if (((attr->ns == NULL) &&
4863 (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
4864 ((attr->ns != NULL) &&
4865 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
4866
4867 xmlSchemaPIllegalAttrErr(ctxt,
4868 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4869 NULL, NULL, attr);
4870 }
4871 attr = attr->next;
4872 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00004873 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00004874 /*
4875 * And now for the children...
4876 */
4877 child = node->children;
4878 while (child != NULL) {
4879 if (IS_SCHEMA(child, "appinfo")) {
4880 /* TODO: make available the content of "appinfo". */
4881 /*
4882 * source = anyURI
4883 * {any attributes with non-schema namespace . . .}>
4884 * Content: ({any})*
4885 */
4886 attr = child->properties;
4887 while (attr != NULL) {
4888 if (((attr->ns == NULL) &&
4889 (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
4890 ((attr->ns != NULL) &&
4891 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004892
Daniel Veillardc0826a72004-08-10 14:17:33 +00004893 xmlSchemaPIllegalAttrErr(ctxt,
4894 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4895 NULL, NULL, attr);
4896 }
4897 attr = attr->next;
4898 }
4899 xmlSchemaPValAttr(ctxt, NULL, NULL, child, "source",
4900 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
4901 child = child->next;
4902 } else if (IS_SCHEMA(child, "documentation")) {
4903 /* TODO: make available the content of "documentation". */
4904 /*
4905 * source = anyURI
4906 * {any attributes with non-schema namespace . . .}>
4907 * Content: ({any})*
4908 */
4909 attr = child->properties;
4910 while (attr != NULL) {
4911 if (attr->ns == NULL) {
4912 if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
4913 xmlSchemaPIllegalAttrErr(ctxt,
4914 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4915 NULL, NULL, attr);
4916 }
4917 } else {
4918 if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
4919 (xmlStrEqual(attr->name, BAD_CAST "lang") &&
4920 (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
4921
4922 xmlSchemaPIllegalAttrErr(ctxt,
4923 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4924 NULL, NULL, attr);
4925 }
4926 }
4927 attr = attr->next;
4928 }
4929 /*
4930 * Attribute "xml:lang".
4931 */
4932 attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
4933 if (attr != NULL)
4934 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
4935 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
4936 child = child->next;
4937 } else {
4938 if (!barked)
4939 xmlSchemaPContentErr(ctxt,
4940 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
4941 NULL, NULL, node, child, NULL, "(appinfo | documentation)*");
4942 barked = 1;
4943 child = child->next;
4944 }
4945 }
4946
Daniel Veillard4255d502002-04-16 15:50:10 +00004947 return (ret);
4948}
4949
4950/**
4951 * xmlSchemaParseFacet:
4952 * @ctxt: a schema validation context
4953 * @schema: the schema being built
4954 * @node: a subtree containing XML Schema informations
4955 *
4956 * parse a XML schema Facet declaration
4957 * *WARNING* this interface is highly subject to change
4958 *
4959 * Returns the new type structure or NULL in case of error
4960 */
4961static xmlSchemaFacetPtr
4962xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004963 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004964{
4965 xmlSchemaFacetPtr facet;
4966 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004967 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00004968
4969 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4970 return (NULL);
4971
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004972 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004973 if (facet == NULL) {
4974 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
4975 return (NULL);
4976 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004977 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004978 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00004979 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004980 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
4981 "Facet %s has no value\n", node->name, NULL);
4982 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00004983 return (NULL);
4984 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004985 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004986 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004987 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004988 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004989 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004990 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004991 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004992 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004993 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004994 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004995 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004996 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004997 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004998 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004999 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005000 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005001 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005002 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005003 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005004 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005005 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005006 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
5007 } else if (IS_SCHEMA(node, "minLength")) {
5008 facet->type = XML_SCHEMA_FACET_MINLENGTH;
5009 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005010 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
5011 "Unknown facet type %s\n", node->name, NULL);
5012 xmlSchemaFreeFacet(facet);
5013 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005014 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005015 xmlSchemaPValAttrID(ctxt, NULL,
5016 (xmlSchemaTypePtr) facet, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00005017 facet->value = value;
Daniel Veillard01fa6152004-06-29 17:04:39 +00005018 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
5019 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
5020 const xmlChar *fixed;
5021
5022 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
5023 if (fixed != NULL) {
5024 if (xmlStrEqual(fixed, BAD_CAST "true"))
5025 facet->fixed = 1;
5026 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005027 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005028 child = node->children;
5029
5030 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005031 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5032 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005033 }
5034 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005035 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
5036 "Facet %s has unexpected child content\n",
5037 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005038 }
5039 return (facet);
5040}
5041
5042/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005043 * xmlSchemaParseWildcardNs:
5044 * @ctxt: a schema parser context
5045 * @wildc: the wildcard, already created
5046 * @node: a subtree containing XML Schema informations
5047 *
5048 * Parses the attribute "processContents" and "namespace"
5049 * of a xsd:anyAttribute and xsd:any.
5050 * *WARNING* this interface is highly subject to change
5051 *
5052 * Returns 0 if everything goes fine, a positive error code
5053 * if something is not valid and -1 if an internal error occurs.
5054 */
5055static int
5056xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
5057 xmlSchemaPtr schema,
5058 xmlSchemaWildcardPtr wildc,
5059 xmlNodePtr node)
5060{
5061 const xmlChar *pc, *ns, *dictnsItem;
5062 int ret = 0;
5063 xmlChar *nsItem;
5064 xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
5065 xmlAttrPtr attr;
5066
5067 pc = xmlSchemaGetProp(ctxt, node, "processContents");
5068 if ((pc == NULL)
5069 || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
5070 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
5071 } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
5072 wildc->processContents = XML_SCHEMAS_ANY_SKIP;
5073 } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
5074 wildc->processContents = XML_SCHEMAS_ANY_LAX;
5075 } else {
5076 xmlSchemaPSimpleTypeErr(ctxt,
5077 XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD,
5078 NULL, NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00005079 NULL, "(strict | skip | lax)", pc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005080 NULL, NULL, NULL);
5081 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
5082 ret = XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD;
5083 }
5084 /*
5085 * Build the namespace constraints.
5086 */
5087 attr = xmlSchemaGetPropNode(node, "namespace");
5088 ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5089 if ((ns == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
5090 wildc->any = 1;
5091 else if (xmlStrEqual(ns, BAD_CAST "##other")) {
5092 wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
5093 if (wildc->negNsSet == NULL) {
5094 return (-1);
5095 }
5096 wildc->negNsSet->value = schema->targetNamespace;
5097 } else {
5098 const xmlChar *end, *cur;
5099
5100 cur = ns;
5101 do {
5102 while (IS_BLANK_CH(*cur))
5103 cur++;
5104 end = cur;
5105 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
5106 end++;
5107 if (end == cur)
5108 break;
5109 nsItem = xmlStrndup(cur, end - cur);
5110 if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
5111 (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
5112 xmlSchemaPSimpleTypeErr(ctxt,
5113 XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
5114 NULL, NULL, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005115 NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005116 "((##any | ##other) | List of (anyURI | "
5117 "(##targetNamespace | ##local)))",
5118 nsItem, NULL, NULL, NULL);
5119 ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
5120 } else {
5121 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
5122 dictnsItem = schema->targetNamespace;
5123 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
5124 dictnsItem = NULL;
5125 } else {
5126 /*
5127 * Validate the item (anyURI).
5128 */
5129 xmlSchemaPValAttrNodeValue(ctxt, NULL, NULL, attr,
5130 nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
5131 dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
5132 }
5133 /*
5134 * Avoid dublicate namespaces.
5135 */
5136 tmp = wildc->nsSet;
5137 while (tmp != NULL) {
5138 if (dictnsItem == tmp->value)
5139 break;
5140 tmp = tmp->next;
5141 }
5142 if (tmp == NULL) {
5143 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
5144 if (tmp == NULL) {
5145 xmlFree(nsItem);
5146 return (-1);
5147 }
5148 tmp->value = dictnsItem;
5149 tmp->next = NULL;
5150 if (wildc->nsSet == NULL)
5151 wildc->nsSet = tmp;
5152 else
5153 lastNs->next = tmp;
5154 lastNs = tmp;
5155 }
5156
5157 }
5158 xmlFree(nsItem);
5159 cur = end;
5160 } while (*cur != 0);
5161 }
5162 return (ret);
5163}
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005164
5165static int
5166xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
5167 xmlSchemaTypePtr item,
5168 xmlNodePtr node,
5169 int minOccurs,
5170 int maxOccurs) {
5171
5172 if (maxOccurs != UNBOUNDED) {
5173 /*
5174 * TODO: Maby we should better not create the particle,
5175 * if min/max is invalid, since it could confuse the build of the
5176 * content model.
5177 */
5178 /*
5179 * 3.9.6 Schema Component Constraint: Particle Correct
5180 *
5181 */
5182 if (maxOccurs < 1) {
5183 /*
5184 * 2.2 {max occurs} must be greater than or equal to 1.
5185 */
5186 xmlSchemaPCustomAttrErr(ctxt,
5187 XML_SCHEMAP_P_PROPS_CORRECT_2_2,
5188 NULL, item, xmlSchemaGetPropNode(node, "maxOccurs"),
5189 "The value must be greater than or equal to 1");
5190 return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
5191 } else if (minOccurs > maxOccurs) {
5192 /*
5193 * 2.1 {min occurs} must not be greater than {max occurs}.
5194 */
5195 xmlSchemaPCustomAttrErr(ctxt,
5196 XML_SCHEMAP_P_PROPS_CORRECT_2_1,
5197 NULL, item, xmlSchemaGetPropNode(node, "minOccurs"),
5198 "The value must not be greater than the value of 'maxOccurs'");
5199 return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
5200 }
5201 }
5202 return (0);
5203}
5204
Daniel Veillardc0826a72004-08-10 14:17:33 +00005205/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005206 * xmlSchemaParseAny:
5207 * @ctxt: a schema validation context
5208 * @schema: the schema being built
5209 * @node: a subtree containing XML Schema informations
5210 *
5211 * parse a XML schema Any declaration
5212 * *WARNING* this interface is highly subject to change
5213 *
5214 * Returns the new type structure or NULL in case of error
5215 */
5216static xmlSchemaTypePtr
5217xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5218 xmlNodePtr node)
5219{
5220 xmlSchemaTypePtr type;
5221 xmlNodePtr child = NULL;
5222 xmlChar name[30];
Daniel Veillardc0826a72004-08-10 14:17:33 +00005223 xmlSchemaWildcardPtr wildc;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005224 int minOccurs, maxOccurs;
Daniel Veillard4255d502002-04-16 15:50:10 +00005225
5226 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5227 return (NULL);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005228 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
5229 "(nonNegativeInteger | unbounded)");
5230 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
5231 "nonNegativeInteger");
5232 if ((minOccurs == 0) && (maxOccurs == 0))
5233 return (NULL);
5234
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005235 snprintf((char *) name, 30, "#any%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00005236 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005237 if (type == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005238 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005239 type->node = node;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005240 type->type = XML_SCHEMA_TYPE_ANY;
5241
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005242 /*
5243 * TODO: Use a particle component here.
5244 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00005245 wildc = xmlSchemaAddWildcard(ctxt);
5246 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005247 * Check min/max sanity.
5248 */
5249 type->maxOccurs = maxOccurs;
5250 type->minOccurs = minOccurs;
5251 xmlSchemaPCheckParticleCorrect_2(ctxt, type,
5252 node, type->minOccurs, type->maxOccurs);
5253 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005254 * This is not nice, since it is won't be used as a attribute wildcard,
5255 * but better than adding a field to the structure.
5256 */
5257 type->attributeWildcard = wildc;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005258 xmlSchemaParseWildcardNs(ctxt, schema, wildc, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005259 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00005260 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005261 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5262 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005263 }
5264 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005265 xmlSchemaPErr2(ctxt, node, child,
5266 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
5267 "Sequence %s has unexpected content\n", type->name,
5268 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005269 }
5270
5271 return (type);
5272}
5273
5274/**
5275 * xmlSchemaParseNotation:
5276 * @ctxt: a schema validation context
5277 * @schema: the schema being built
5278 * @node: a subtree containing XML Schema informations
5279 *
5280 * parse a XML schema Notation declaration
5281 *
5282 * Returns the new structure or NULL in case of error
5283 */
5284static xmlSchemaNotationPtr
5285xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005286 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005287{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005288 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00005289 xmlSchemaNotationPtr ret;
5290 xmlNodePtr child = NULL;
5291
5292 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5293 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005294 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00005295 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005296 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
5297 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005298 return (NULL);
5299 }
5300 ret = xmlSchemaAddNotation(ctxt, schema, name);
5301 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005302 return (NULL);
5303 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005304 ret->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00005305
5306 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
5307 node, BAD_CAST "id");
5308
5309 if (IS_SCHEMA(child, "annotation")) {
5310 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5311 child = child->next;
5312 }
5313
Daniel Veillard4255d502002-04-16 15:50:10 +00005314 child = node->children;
5315 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005316 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5317 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005318 }
5319 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005320 xmlSchemaPErr2(ctxt, node, child,
5321 XML_SCHEMAP_UNKNOWN_NOTATION_CHILD,
5322 "notation %s has unexpected content\n", name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005323 }
5324
5325 return (ret);
5326}
5327
5328/**
5329 * xmlSchemaParseAnyAttribute:
5330 * @ctxt: a schema validation context
5331 * @schema: the schema being built
5332 * @node: a subtree containing XML Schema informations
5333 *
5334 * parse a XML schema AnyAttrribute declaration
5335 * *WARNING* this interface is highly subject to change
5336 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005337 * Returns a wildcard or NULL.
Daniel Veillard4255d502002-04-16 15:50:10 +00005338 */
Daniel Veillard3646d642004-06-02 19:19:14 +00005339static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005340xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
5341 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005342{
Daniel Veillard3646d642004-06-02 19:19:14 +00005343 xmlSchemaWildcardPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00005344 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005345 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005346
5347 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5348 return (NULL);
5349
Daniel Veillard3646d642004-06-02 19:19:14 +00005350 ret = xmlSchemaAddWildcard(ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00005351 if (ret == NULL) {
5352 return (NULL);
5353 }
William M. Bracke7091952004-05-11 15:09:58 +00005354 ret->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005355 /*
5356 * Check for illegal attributes.
5357 */
5358 attr = node->properties;
5359 while (attr != NULL) {
5360 if (attr->ns == NULL) {
5361 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5362 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
5363 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
5364 xmlSchemaPIllegalAttrErr(ctxt,
5365 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5366 NULL, NULL, attr);
5367 }
5368 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5369 xmlSchemaPIllegalAttrErr(ctxt,
5370 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5371 NULL, NULL, attr);
5372 }
5373 attr = attr->next;
5374 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005375 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
5376 node, BAD_CAST "id");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005377 /*
5378 * Parse the namespace list.
5379 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00005380 if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0) {
5381 xmlSchemaFreeWildcard(ret);
5382 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005383 }
5384 /*
5385 * And now for the children...
5386 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005387 child = node->children;
5388 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005389 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5390 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005391 }
5392 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005393 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005394 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5395 NULL, NULL, node, child,
5396 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005397 }
5398
5399 return (ret);
5400}
5401
5402
5403/**
5404 * xmlSchemaParseAttribute:
5405 * @ctxt: a schema validation context
5406 * @schema: the schema being built
5407 * @node: a subtree containing XML Schema informations
5408 *
5409 * parse a XML schema Attrribute declaration
5410 * *WARNING* this interface is highly subject to change
5411 *
William M. Bracke7091952004-05-11 15:09:58 +00005412 * Returns the attribute declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00005413 */
5414static xmlSchemaAttributePtr
5415xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00005416 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005417{
Daniel Veillardc0826a72004-08-10 14:17:33 +00005418 const xmlChar *name, *attrValue;
5419 xmlChar *repName = NULL; /* The reported designation. */
Daniel Veillard4255d502002-04-16 15:50:10 +00005420 xmlSchemaAttributePtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005421 xmlNodePtr child = NULL;
5422 xmlAttrPtr attr, nameAttr;
5423 int isRef = 0;
William M. Bracke7091952004-05-11 15:09:58 +00005424
5425 /*
5426 * Note that the w3c spec assumes the schema to be validated with schema
5427 * for schemas beforehand.
5428 *
5429 * 3.2.3 Constraints on XML Representations of Attribute Declarations
William M. Bracke7091952004-05-11 15:09:58 +00005430 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005431
5432 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5433 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005434 attr = xmlSchemaGetPropNode(node, "ref");
5435 nameAttr = xmlSchemaGetPropNode(node, "name");
5436
5437 if ((attr == NULL) && (nameAttr == NULL)) {
5438 /*
5439 * 3.2.3 : 3.1
5440 * One of ref or name must be present, but not both
5441 */
5442 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
5443 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, node, NULL,
5444 "One of the attributes 'ref' or 'name' must be present");
5445 return (NULL);
5446 }
5447 if ((topLevel) || (attr == NULL)) {
5448 if (nameAttr == NULL) {
5449 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
5450 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, node,
5451 "name", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005452 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005453 }
5454 } else
5455 isRef = 1;
5456
5457 if (isRef) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005458 char buf[50];
Daniel Veillardc0826a72004-08-10 14:17:33 +00005459 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix = NULL;
5460
5461 /*
5462 * Parse as attribute reference.
5463 */
5464 if (xmlSchemaPValAttrNodeQName(ctxt, schema,
5465 (xmlChar **) &xmlSchemaElemDesAttrRef, NULL, attr, &refNs,
5466 &refPrefix, &ref) != 0) {
5467 return (NULL);
5468 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005469 snprintf(buf, 49, "#aRef%d", ctxt->counter++ + 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005470 name = (const xmlChar *) buf;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005471 ret = xmlSchemaAddAttribute(ctxt, schema, name, NULL, node, 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005472 if (ret == NULL) {
5473 if (repName != NULL)
5474 xmlFree(repName);
5475 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005476 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005477 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
5478 ret->node = node;
5479 ret->refNs = refNs;
5480 ret->refPrefix = refPrefix;
5481 ret->ref = ref;
5482 /*
5483 xmlSchemaFormatTypeRep(&repName, (xmlSchemaTypePtr) ret, NULL, NULL);
5484 */
5485 if (nameAttr != NULL)
5486 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
5487 &repName, (xmlSchemaTypePtr) ret, nameAttr,
5488 "ref", "name");
5489 /*
5490 * Check for illegal attributes.
5491 */
5492 attr = node->properties;
5493 while (attr != NULL) {
5494 if (attr->ns == NULL) {
5495 if (xmlStrEqual(attr->name, BAD_CAST "type") ||
5496 xmlStrEqual(attr->name, BAD_CAST "form")) {
5497 /*
5498 * 3.2.3 : 3.2
5499 * If ref is present, then all of <simpleType>,
5500 * form and type must be absent.
5501 */
5502 xmlSchemaPIllegalAttrErr(ctxt,
5503 XML_SCHEMAP_SRC_ATTRIBUTE_3_2, &repName,
5504 (xmlSchemaTypePtr) ret, attr);
5505 } else if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
5506 (!xmlStrEqual(attr->name, BAD_CAST "use")) &&
5507 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5508 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
5509 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
5510 (!xmlStrEqual(attr->name, BAD_CAST "default"))) {
5511 xmlSchemaPIllegalAttrErr(ctxt,
5512 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5513 &repName, (xmlSchemaTypePtr) ret, attr);
5514 }
5515 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5516 xmlSchemaPIllegalAttrErr(ctxt,
5517 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5518 &repName, (xmlSchemaTypePtr) ret, attr);
5519 }
5520 attr = attr->next;
5521 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005522 } else {
William M. Bracke7091952004-05-11 15:09:58 +00005523 const xmlChar *ns = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005524
5525 /*
5526 * Parse as attribute declaration.
5527 */
5528 if (xmlSchemaPValAttrNode(ctxt,
5529 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, nameAttr,
5530 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
5531 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005532 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005533 /*
5534 xmlSchemaFormatTypeRep(&repName, NULL, xmlSchemaElemDesAttrDecl, name);
5535 */
5536 /*
5537 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
5538 */
5539 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
5540 xmlSchemaPSimpleTypeErr(ctxt,
5541 XML_SCHEMAP_NO_XMLNS,
5542 &repName, NULL, (xmlNodePtr) nameAttr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005543 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), "NCName", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005544 "The value must not match 'xmlns'",
5545 NULL, NULL);
5546 if (repName != NULL)
5547 xmlFree(repName);
5548 return (NULL);
5549 }
5550 /*
5551 * Evaluate the target namespace
5552 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005553 if (topLevel) {
5554 ns = schema->targetNamespace;
5555 } else {
5556 attr = xmlSchemaGetPropNode(node, "form");
5557 if (attr != NULL) {
5558 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5559 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
5560 ns = schema->targetNamespace;
5561 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
5562 xmlSchemaPSimpleTypeErr(ctxt,
5563 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5564 &repName, NULL, (xmlNodePtr) attr,
5565 NULL, "(qualified | unqualified)",
5566 attrValue, NULL, NULL, NULL);
5567 }
5568 } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
5569 ns = schema->targetNamespace;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005570 }
5571 ret = xmlSchemaAddAttribute(ctxt, schema, name, ns, node, topLevel);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005572 if (ret == NULL) {
5573 if (repName != NULL)
5574 xmlFree(repName);
Daniel Veillard3646d642004-06-02 19:19:14 +00005575 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005576 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005577 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005578 ret->node = node;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005579 if (topLevel)
5580 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
5581 /*
5582 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
5583 */
5584 if (xmlStrEqual(ret->targetNamespace, xmlSchemaInstanceNs)) {
5585 xmlSchemaPCustomErr(ctxt,
5586 XML_SCHEMAP_NO_XSI,
5587 &repName, (xmlSchemaTypePtr) ret, node,
5588 "The target namespace must not match '%s'",
5589 xmlSchemaInstanceNs);
5590 }
5591 /*
5592 * Check for illegal attributes.
5593 */
5594 attr = node->properties;
5595 while (attr != NULL) {
5596 if (attr->ns == NULL) {
5597 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5598 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
5599 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
5600 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
5601 (!xmlStrEqual(attr->name, BAD_CAST "type"))) {
5602 if ((topLevel) ||
5603 ((!xmlStrEqual(attr->name, BAD_CAST "form")) &&
5604 (!xmlStrEqual(attr->name, BAD_CAST "use")))) {
5605 xmlSchemaPIllegalAttrErr(ctxt,
5606 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5607 &repName, (xmlSchemaTypePtr) ret, attr);
5608 }
5609 }
5610 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5611 xmlSchemaPIllegalAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5612 &repName, (xmlSchemaTypePtr) ret, attr);
5613 }
5614 attr = attr->next;
5615 }
5616 xmlSchemaPValAttrQName(ctxt, schema, &repName, (xmlSchemaTypePtr) ret,
5617 node, "type", &ret->typeNs, NULL, &ret->typeName);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005618 }
5619 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
5620 node, BAD_CAST "id");
William M. Bracke7091952004-05-11 15:09:58 +00005621 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005622 * Attribute "fixed".
William M. Bracke7091952004-05-11 15:09:58 +00005623 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00005624 ret->defValue = xmlSchemaGetProp(ctxt, node, "fixed");
5625 if (ret->defValue != NULL)
5626 ret->flags |= XML_SCHEMAS_ATTR_FIXED;
5627 /*
5628 * Attribute "default".
5629 */
5630 attr = xmlSchemaGetPropNode(node, "default");
5631 if (attr != NULL) {
5632 /*
5633 * 3.2.3 : 1
5634 * default and fixed must not both be present.
5635 */
5636 if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
5637 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
5638 &repName, (xmlSchemaTypePtr) ret, attr, "default", "fixed");
5639 } else
5640 ret->defValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5641 }
5642 if (topLevel == 0) {
5643 /*
5644 * Attribute "use".
5645 */
5646 attr = xmlSchemaGetPropNode(node, "use");
5647 if (attr != NULL) {
5648 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5649 if (xmlStrEqual(attrValue, BAD_CAST "optional"))
5650 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
5651 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
5652 ret->occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
5653 else if (xmlStrEqual(attrValue, BAD_CAST "required"))
5654 ret->occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
5655 else
5656 xmlSchemaPSimpleTypeErr(ctxt,
5657 XML_SCHEMAP_INVALID_ATTR_USE,
5658 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005659 NULL, "(optional | prohibited | required)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00005660 attrValue, NULL, NULL, NULL);
5661 } else
5662 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
5663 /*
5664 * 3.2.3 : 2
5665 * If default and use are both present, use must have
5666 * the actual value optional.
5667 */
5668 if ((ret->occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
5669 (ret->defValue != NULL) &&
5670 ((ret->flags & XML_SCHEMAS_ATTR_FIXED) == 0)) {
5671 xmlSchemaPSimpleTypeErr(ctxt,
5672 XML_SCHEMAP_SRC_ATTRIBUTE_2,
5673 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005674 NULL, "(optional | prohibited | required)", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005675 "The value must be 'optional' if the attribute "
5676 "'default' is present as well", NULL, NULL);
5677 }
5678 }
5679 /*
5680 * And now for the children...
5681 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005682 child = node->children;
5683 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005684 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5685 child = child->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005686 }
5687 if (isRef) {
5688 if (child != NULL) {
5689 if (IS_SCHEMA(child, "simpleType"))
5690 /*
5691 * 3.2.3 : 3.2
5692 * If ref is present, then all of <simpleType>,
5693 * form and type must be absent.
5694 */
5695 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
5696 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
5697 "(annotation?)");
5698 else
5699 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5700 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
5701 "(annotation?)");
5702 }
5703 } else {
5704 if (IS_SCHEMA(child, "simpleType")) {
5705 if (ret->typeName != NULL) {
5706 /*
5707 * 3.2.3 : 4
5708 * type and <simpleType> must not both be present.
5709 */
5710 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
5711 &repName, (xmlSchemaTypePtr) ret, node, child,
5712 "The attribute 'type' and the <simpleType> child "
5713 "are mutually exclusive", NULL);
5714 } else
5715 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
5716 child = child->next;
5717 }
5718 if (child != NULL)
5719 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5720 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
5721 "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005722 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005723 /*
5724 * Cleanup.
5725 */
5726 if (repName != NULL)
5727 xmlFree(repName);
Daniel Veillard4255d502002-04-16 15:50:10 +00005728 return (ret);
5729}
5730
5731/**
5732 * xmlSchemaParseAttributeGroup:
5733 * @ctxt: a schema validation context
5734 * @schema: the schema being built
5735 * @node: a subtree containing XML Schema informations
5736 *
5737 * parse a XML schema Attribute Group declaration
5738 * *WARNING* this interface is highly subject to change
5739 *
5740 * Returns the attribute group or NULL in case of error.
5741 */
5742static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005743xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00005744 xmlSchemaPtr schema, xmlNodePtr node,
5745 int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005746{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005747 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00005748 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00005749 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005750 const xmlChar *oldcontainer;
5751 xmlAttrPtr attr, nameAttr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005752
5753 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5754 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005755
5756 nameAttr = xmlSchemaGetPropNode(node, "name");
5757 attr = xmlSchemaGetPropNode(node, "ref");
5758 if ((topLevel) || (attr == NULL)) {
5759 /*
5760 * Parse as an attribute group definition.
5761 * Note that those are allowed at top level only.
5762 */
5763 if (nameAttr == NULL) {
5764 xmlSchemaPMissingAttrErr(ctxt,
5765 XML_SCHEMAP_S4S_ATTR_MISSING,
5766 NULL, NULL, node, "name", NULL);
5767 return (NULL);
5768 }
5769 name = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) nameAttr);
5770 /*
5771 * The name is crucial, exit if invalid.
5772 */
5773 if (xmlSchemaPValAttrNode(ctxt,
5774 NULL, NULL, nameAttr,
5775 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
5776 return (NULL);
5777 }
5778 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
5779 if (ret == NULL)
5780 return (NULL);
5781 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
5782 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
5783 ret->node = node;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005784 ret->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005785 } else {
5786 char buf[50];
5787 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix;
5788
5789 /*
5790 * Parse as an attribute group definition reference.
5791 */
5792 if (attr == NULL) {
5793 xmlSchemaPMissingAttrErr(ctxt,
5794 XML_SCHEMAP_S4S_ATTR_MISSING,
5795 NULL, NULL, node, "ref", NULL);
5796 }
5797 xmlSchemaPValAttrNodeQName(ctxt, schema,
5798 NULL, NULL, attr, &refNs, &refPrefix, &ref);
5799
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005800 snprintf(buf, 49, "#agRef%d", ctxt->counter++ + 1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005801 name = (const xmlChar *) buf;
5802 if (name == NULL) {
5803 xmlSchemaPErrMemory(ctxt, "creating internal name for an "
5804 "attribute group definition reference", node);
5805 return (NULL);
5806 }
5807 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
5808 if (ret == NULL)
5809 return (NULL);
5810 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
5811 ret->ref = ref;
5812 ret->refNs = refNs;
5813 /* TODO: Is @refPrefix currently used? */
5814 ret->refPrefix = refPrefix;
5815 ret->node = node;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005816 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005817 /*
5818 * Check for illegal attributes.
5819 */
5820 attr = node->properties;
5821 while (attr != NULL) {
5822 if (attr->ns == NULL) {
5823 if ((((topLevel == 0) && (!xmlStrEqual(attr->name, BAD_CAST "ref"))) ||
5824 (topLevel && (!xmlStrEqual(attr->name, BAD_CAST "name")))) &&
5825 (!xmlStrEqual(attr->name, BAD_CAST "id")))
5826 {
5827 xmlSchemaPIllegalAttrErr(ctxt,
5828 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5829 NULL, NULL, attr);
5830 }
5831 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5832 xmlSchemaPIllegalAttrErr(ctxt,
5833 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5834 NULL, NULL, attr);
5835 }
5836 attr = attr->next;
5837 }
5838 /* TODO: Validate "id" ? */
5839 /*
5840 * And now for the children...
5841 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005842 oldcontainer = ctxt->container;
Daniel Veillard4255d502002-04-16 15:50:10 +00005843 ctxt->container = name;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005844 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00005845 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005846 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5847 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005848 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005849 if (topLevel) {
5850 child = xmlSchemaParseAttrDecls(ctxt, schema, child, (xmlSchemaTypePtr) ret);
5851 if (IS_SCHEMA(child, "anyAttribute")) {
5852 ret->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
5853 child = child->next;
5854 }
5855 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005856 if (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005857 xmlSchemaPContentErr(ctxt,
5858 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5859 NULL, NULL, node, child, NULL,
5860 "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005861 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005862 ctxt->container = oldcontainer;
5863 return (ret);
5864}
5865
5866/**
William M. Brack2f2a6632004-08-20 23:09:47 +00005867 * xmlSchemaPValAttrFormDefault:
5868 * @value: the value
5869 * @flags: the flags to be modified
5870 * @flagQualified: the specific flag for "qualified"
5871 *
5872 * Returns 0 if the value is valid, 1 otherwise.
5873 */
5874static int
5875xmlSchemaPValAttrFormDefault(const xmlChar *value,
5876 int *flags,
5877 int flagQualified)
5878{
5879 if (xmlStrEqual(value, BAD_CAST "qualified")) {
5880 if ((*flags & flagQualified) == 0)
5881 *flags |= flagQualified;
5882 } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
5883 return (1);
5884
5885 return (0);
5886}
5887
5888/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005889 * xmlSchemaPValAttrBlockFinal:
5890 * @value: the value
5891 * @flags: the flags to be modified
5892 * @flagAll: the specific flag for "#all"
5893 * @flagExtension: the specific flag for "extension"
5894 * @flagRestriction: the specific flag for "restriction"
5895 * @flagSubstitution: the specific flag for "substitution"
5896 * @flagList: the specific flag for "list"
5897 * @flagUnion: the specific flag for "union"
5898 *
5899 * Validates the value of the attribute "final" and "block". The value
5900 * is converted into the specified flag values and returned in @flags.
5901 *
5902 * Returns 0 if the value is valid, 1 otherwise.
5903 */
5904
5905static int
5906xmlSchemaPValAttrBlockFinal(const xmlChar *value,
5907 int *flags,
5908 int flagAll,
5909 int flagExtension,
5910 int flagRestriction,
5911 int flagSubstitution,
5912 int flagList,
5913 int flagUnion)
5914{
5915 int ret = 0;
5916
5917 /*
5918 * TODO: This does not check for dublicate entries.
5919 */
William M. Brack2f2a6632004-08-20 23:09:47 +00005920 if (value == NULL)
5921 return (1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005922 if (xmlStrEqual(value, BAD_CAST "#all")) {
5923 if (flagAll != -1)
5924 *flags |= flagAll;
5925 else {
5926 if (flagExtension != -1)
5927 *flags |= flagExtension;
5928 if (flagRestriction != -1)
5929 *flags |= flagRestriction;
5930 if (flagSubstitution != -1)
5931 *flags |= flagSubstitution;
5932 if (flagList != -1)
5933 *flags |= flagList;
5934 if (flagUnion != -1)
5935 *flags |= flagUnion;
5936 }
5937 } else {
5938 const xmlChar *end, *cur = value;
5939 xmlChar *item;
5940
5941 do {
5942 while (IS_BLANK_CH(*cur))
5943 cur++;
5944 end = cur;
5945 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
5946 end++;
5947 if (end == cur)
5948 break;
5949 item = xmlStrndup(cur, end - cur);
5950 if (xmlStrEqual(item, BAD_CAST "extension")) {
5951 if (flagExtension != -1) {
5952 if ((*flags & flagExtension) == 0)
5953 *flags |= flagExtension;
5954 } else
5955 ret = 1;
5956 } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
5957 if (flagRestriction != -1) {
5958 if ((*flags & flagRestriction) == 0)
5959 *flags |= flagRestriction;
5960 } else
5961 ret = 1;
5962 } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
5963 if (flagSubstitution != -1) {
5964 if ((*flags & flagSubstitution) == 0)
5965 *flags |= flagSubstitution;
5966 } else
5967 ret = 1;
5968 } else if (xmlStrEqual(item, BAD_CAST "list")) {
5969 if (flagList != -1) {
5970 if ((*flags & flagList) == 0)
5971 *flags |= flagList;
5972 } else
5973 ret = 1;
5974 } else if (xmlStrEqual(item, BAD_CAST "union")) {
5975 if (flagUnion != -1) {
5976 if ((*flags & flagUnion) == 0)
5977 *flags |= flagUnion;
5978 } else
5979 ret = 1;
5980 } else
5981 ret = 1;
5982 if (item != NULL)
5983 xmlFree(item);
5984 cur = end;
5985 } while ((ret == 0) && (*cur != 0));
5986 }
5987
5988 return (ret);
5989}
5990
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005991#ifdef IDC_ENABLED
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00005992static int
5993xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00005994 xmlSchemaIDCPtr idc,
5995 xmlSchemaIDCSelectPtr selector,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00005996 xmlAttrPtr attr,
5997 int isField)
5998{
5999 xmlNodePtr node;
6000
6001 /*
6002 * c-selector-xpath:
6003 * Schema Component Constraint: Selector Value OK
6004 *
6005 * TODO: 1 The {selector} must be a valid XPath expression, as defined
6006 * in [XPath].
6007 */
6008 if (selector == NULL) {
6009 xmlSchemaPErr(ctxt, idc->node,
6010 XML_SCHEMAP_INTERNAL,
6011 "Internal error: xmlSchemaCheckCSelectorXPath, "
6012 "the selector is not specified.\n", NULL, NULL);
6013 return (-1);
6014 }
6015 if (attr == NULL)
6016 node = idc->node;
6017 else
6018 node = (xmlNodePtr) attr;
6019 if (selector->xpath == NULL) {
6020 xmlSchemaPCustomErr(ctxt,
6021 /* TODO: Adjust error code. */
6022 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6023 NULL, NULL, node,
6024 "The XPath expression of the selector is not valid", NULL);
6025 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
6026 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006027 const xmlChar **nsArray = NULL;
6028 xmlNsPtr *nsList = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006029 /*
6030 * Compile the XPath expression.
6031 */
6032 /*
6033 * TODO: We need the array of in-scope namespaces for compilation.
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006034 * TODO: Call xmlPatterncompile with different options for selector/
6035 * field.
6036 */
6037 nsList = xmlGetNsList(attr->doc, attr->parent);
6038 /*
6039 * Build an array of prefixes and namespaces.
6040 */
6041 if (nsList != NULL) {
6042 int i, count = 0;
6043 xmlNsPtr ns;
6044
6045 for (i = 0; nsList[i] != NULL; i++)
6046 count++;
6047
6048 nsArray = (const xmlChar **) xmlMalloc(
6049 (count * 2 + 1) * sizeof(const xmlChar *));
6050 if (nsArray == NULL) {
6051 xmlSchemaPErrMemory(ctxt, "allocating a namespace array",
6052 NULL);
6053 return (-1);
6054 }
6055 for (i = 0; i < count; i++) {
6056 ns = nsList[i];
6057 nsArray[2 * i] = nsList[i]->href;
6058 nsArray[2 * i + 1] = nsList[i]->prefix;
6059 }
6060 nsArray[count * 2] = NULL;
6061 xmlFree(nsList);
6062 }
6063 if (isField)
6064 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik285ebab2005-03-04 18:04:59 +00006065 NULL, 1, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006066 else
6067 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik285ebab2005-03-04 18:04:59 +00006068 NULL, 1, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006069 if (nsArray != NULL)
6070 xmlFree((xmlChar **) nsArray);
6071
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006072#ifdef IDC_XPATH_SUPPORT
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00006073 if (selector->xpathComp == NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006074 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00006075 /* TODO: Adjust error code? */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006076 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6077 NULL, NULL, node,
6078 "The XPath expression '%s' could not be "
6079 "compiled", selector->xpath);
6080 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
6081 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00006082#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006083 }
6084 return (0);
6085}
6086
6087/**
6088 * xmlSchemaAssignAnnotation:
6089 * @item: the schema component
6090 * @annot: the annotation
6091 *
6092 * Adds the annotation to the given schema component.
6093 *
6094 * Returns the given annotaion.
6095 */
6096static xmlSchemaAnnotPtr
6097xmlSchemaAssignAnnotation(xmlSchemaBasicItemPtr item,
6098 xmlSchemaAnnotPtr annot)
6099{
6100 xmlSchemaAnnotPtr cur = item->annot;
6101
6102 if (item->annot == NULL) {
6103 item->annot = annot;
6104 return (annot);
6105 }
6106 cur = item->annot;
6107 if (cur->next != NULL) {
6108 cur = cur->next;
6109 }
6110 cur->next = annot;
6111 return (annot);
6112}
6113
6114/**
6115 * xmlSchemaParseIDCSelectorAndField:
6116 * @ctxt: a schema validation context
6117 * @schema: the schema being built
6118 * @node: a subtree containing XML Schema informations
6119 *
6120 * Parses a XML Schema identity-contraint definition's
6121 * <selector> and <field> elements.
6122 *
6123 * Returns the parsed identity-constraint definition.
6124 */
6125static xmlSchemaIDCSelectPtr
6126xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
6127 xmlSchemaPtr schema,
6128 xmlSchemaIDCPtr idc,
6129 xmlNodePtr node,
6130 int isField)
6131{
6132 xmlSchemaIDCSelectPtr item;
6133 xmlNodePtr child = NULL;
6134 xmlAttrPtr attr;
6135
6136 /*
6137 * Check for illegal attributes.
6138 */
6139 attr = node->properties;
6140 while (attr != NULL) {
6141 if (attr->ns == NULL) {
6142 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6143 (!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
6144 xmlSchemaPIllegalAttrErr(ctxt,
6145 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6146 NULL, NULL, attr);
6147 }
6148 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6149 xmlSchemaPIllegalAttrErr(ctxt,
6150 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6151 NULL, NULL, attr);
6152 }
6153 attr = attr->next;
6154 }
6155 /*
6156 * Create the item.
6157 */
6158 item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
6159 if (item == NULL) {
6160 xmlSchemaPErrMemory(ctxt,
6161 "allocating a 'selector' of an identity-constraint definition",
6162 NULL);
6163 return (NULL);
6164 }
6165 memset(item, 0, sizeof(xmlSchemaIDCSelect));
6166 /*
6167 * Attribute "xpath" (mandatory).
6168 */
6169 attr = xmlSchemaGetPropNode(node, "xpath");
6170 if (attr == NULL) {
6171 xmlSchemaPMissingAttrErr(ctxt,
6172 XML_SCHEMAP_S4S_ATTR_MISSING,
6173 NULL, NULL, node,
6174 "name", NULL);
6175 } else {
6176 item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6177 /*
6178 * URGENT TODO: "field"s have an other syntax than "selector"s.
6179 */
6180
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006181 if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr,
6182 isField) == -1) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006183 xmlSchemaPErr(ctxt,
6184 (xmlNodePtr) attr,
6185 XML_SCHEMAP_INTERNAL,
6186 "Internal error: xmlSchemaParseIDCSelectorAndField, "
6187 "validating the XPath expression of a IDC selector.\n",
6188 NULL, NULL);
6189 }
6190
6191 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00006192 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006193 /*
6194 * And now for the children...
6195 */
6196 child = node->children;
6197 if (IS_SCHEMA(child, "annotation")) {
6198 /*
6199 * Add the annotation to the parent IDC.
6200 */
6201 xmlSchemaAssignAnnotation((xmlSchemaBasicItemPtr) idc,
6202 xmlSchemaParseAnnotation(ctxt, schema, child));
6203 child = child->next;
6204 }
6205 if (child != NULL) {
6206 xmlSchemaPContentErr(ctxt,
6207 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6208 NULL, NULL, node, child,
6209 NULL, "(annotation?)");
6210 }
6211
6212 return (item);
6213}
6214
6215/**
6216 * xmlSchemaParseIDC:
6217 * @ctxt: a schema validation context
6218 * @schema: the schema being built
6219 * @node: a subtree containing XML Schema informations
6220 *
6221 * Parses a XML Schema identity-contraint definition.
6222 *
6223 * Returns the parsed identity-constraint definition.
6224 */
6225static xmlSchemaIDCPtr
6226xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
6227 xmlSchemaPtr schema,
6228 xmlNodePtr node,
6229 xmlSchemaTypeType idcCategory,
6230 const xmlChar *targetNamespace)
6231{
6232 xmlSchemaIDCPtr item = NULL;
6233 xmlNodePtr child = NULL;
6234 xmlAttrPtr attr;
6235 const xmlChar *name = NULL;
6236 xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
6237 int resAdd;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00006238
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006239 /*
6240 * Check for illegal attributes.
6241 */
6242 attr = node->properties;
6243 while (attr != NULL) {
6244 if (attr->ns == NULL) {
6245 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6246 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
6247 ((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
6248 (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
6249 xmlSchemaPIllegalAttrErr(ctxt,
6250 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6251 NULL, NULL, attr);
6252 }
6253 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6254 xmlSchemaPIllegalAttrErr(ctxt,
6255 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6256 NULL, NULL, attr);
6257 }
6258 attr = attr->next;
6259 }
6260 /*
6261 * Attribute "name" (mandatory).
6262 */
6263 attr = xmlSchemaGetPropNode(node, "name");
6264 if (attr == NULL) {
6265 xmlSchemaPMissingAttrErr(ctxt,
6266 XML_SCHEMAP_S4S_ATTR_MISSING,
6267 NULL, NULL, node,
6268 "name", NULL);
6269 return (NULL);
6270 } else if (xmlSchemaPValAttrNode(ctxt,
6271 NULL, NULL, attr,
6272 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
6273 return (NULL);
6274 }
6275 /*
6276 * Create the component.
6277 */
6278 if (schema->idcDef == NULL)
6279 schema->idcDef = xmlHashCreateDict(10, ctxt->dict);
6280 if (schema->idcDef == NULL)
6281 return (NULL);
6282
6283 item = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
6284 if (item == NULL) {
6285 xmlSchemaPErrMemory(ctxt,
6286 "allocating an identity-constraint definition", NULL);
6287 return (NULL);
6288 }
6289 /*
6290 * Add the IDC to the list of IDCs on the schema component.
6291 */
6292 resAdd = xmlHashAddEntry2(schema->idcDef, name, targetNamespace, item);
6293 if (resAdd != 0) {
6294 xmlSchemaPCustomErrExt(ctxt,
6295 XML_SCHEMAP_REDEFINED_TYPE,
6296 NULL, NULL, node,
6297 "An identity-constraint definition with the name '%s' "
6298 "and targetNamespace '%s' does already exist",
6299 name, targetNamespace, NULL);
6300 xmlFree(item);
6301 return (NULL);
6302 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006303 memset(item, 0, sizeof(xmlSchemaIDC));
6304 item->name = name;
6305 item->type = idcCategory;
6306 item->node = node;
6307 /*
6308 * The target namespace of the parent element declaration.
6309 */
6310 item->targetNamespace = targetNamespace;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00006311 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) item,
6312 node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006313 if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
6314 /*
6315 * Attribute "refer" (mandatory).
6316 */
6317 attr = xmlSchemaGetPropNode(node, "refer");
6318 if (attr == NULL) {
6319 xmlSchemaPMissingAttrErr(ctxt,
6320 XML_SCHEMAP_S4S_ATTR_MISSING,
6321 NULL, NULL, node,
6322 "refer", NULL);
6323 } else {
6324 /*
6325 * Create a reference item.
6326 */
6327 item->ref = (xmlSchemaItemQNRefPtr) xmlMalloc(
6328 sizeof(xmlSchemaItemQNRef));
6329 if (item->ref == NULL) {
6330 xmlSchemaPErrMemory(ctxt,
6331 "allocating a QName reference item", NULL);
6332 return (NULL);
6333 }
6334 memset(item->ref, 0, sizeof(xmlSchemaItemQNRef));
6335 xmlSchemaPValAttrNodeQName(ctxt, schema,
6336 NULL, NULL, attr,
6337 &(item->ref->targetNamespace), 0,
6338 &(item->ref->name));
6339 }
6340 }
6341 /*
6342 * And now for the children...
6343 */
6344 child = node->children;
6345 if (IS_SCHEMA(child, "annotation")) {
6346 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6347 child = child->next;
6348 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00006349 if (child == NULL) {
6350 xmlSchemaPContentErr(ctxt,
6351 XML_SCHEMAP_S4S_ELEM_MISSING,
6352 NULL, NULL, node, child,
6353 "A child element is missing",
6354 "(annotation?, (selector, field+))");
6355 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006356 /*
6357 * Child element <selector>.
6358 */
6359 if (IS_SCHEMA(child, "selector")) {
6360 item->selector = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
6361 item, child, 0);
6362 child = child->next;
6363 /*
6364 * Child elements <field>.
6365 */
6366 if (IS_SCHEMA(child, "field")) {
6367 do {
6368 field = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
6369 item, child, 1);
6370 if (field != NULL) {
6371 field->index = item->nbFields;
6372 item->nbFields++;
6373 if (lastField != NULL)
6374 lastField->next = field;
6375 else
6376 item->fields = field;
6377 lastField = field;
6378 }
6379 child = child->next;
6380 } while (IS_SCHEMA(child, "field"));
6381 } else {
6382 xmlSchemaPContentErr(ctxt,
6383 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6384 NULL, NULL, node, child,
6385 NULL, "(annotation?, (selector, field+))");
6386 }
6387 }
6388 if (child != NULL) {
6389 xmlSchemaPContentErr(ctxt,
6390 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6391 NULL, NULL, node, child,
6392 NULL, "(annotation?, (selector, field+))");
6393 }
6394
6395 return (item);
6396}
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006397#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006398
Daniel Veillardc0826a72004-08-10 14:17:33 +00006399/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006400 * xmlSchemaParseElement:
6401 * @ctxt: a schema validation context
6402 * @schema: the schema being built
6403 * @node: a subtree containing XML Schema informations
6404 *
6405 * parse a XML schema Element declaration
6406 * *WARNING* this interface is highly subject to change
6407 *
William M. Bracke7091952004-05-11 15:09:58 +00006408 * Returns the parsed element declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00006409 */
6410static xmlSchemaElementPtr
6411xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00006412 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006413{
Daniel Veillardc0826a72004-08-10 14:17:33 +00006414 const xmlChar *name = NULL;
6415 const xmlChar *attrValue;
6416 xmlChar *repName = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00006417 xmlSchemaElementPtr ret;
6418 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006419 const xmlChar *oldcontainer;
6420 xmlAttrPtr attr, nameAttr;
6421 int minOccurs, maxOccurs;
6422 int isRef = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006423#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006424 xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006425#endif
William M. Bracke7091952004-05-11 15:09:58 +00006426
6427 /* 3.3.3 Constraints on XML Representations of Element Declarations */
6428 /* TODO: Complete implementation of 3.3.6 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006429
Daniel Veillard4255d502002-04-16 15:50:10 +00006430 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6431 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006432
Daniel Veillardc0826a72004-08-10 14:17:33 +00006433 oldcontainer = ctxt->container;
6434
6435 nameAttr = xmlSchemaGetPropNode(node, "name");
6436 attr = xmlSchemaGetPropNode(node, "ref");
6437 if ((topLevel) || (attr == NULL)) {
6438 if (nameAttr == NULL) {
6439 xmlSchemaPMissingAttrErr(ctxt,
6440 XML_SCHEMAP_S4S_ATTR_MISSING,
6441 (xmlChar **) &xmlSchemaElemDesElemDecl, NULL, node,
6442 "name", NULL);
6443 return (NULL);
6444 }
6445 name = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) nameAttr);
6446 } else {
6447 isRef = 1;
6448
6449 }
6450 /*
6451 * ... unless minOccurs=maxOccurs=0, in which case the item corresponds
6452 * to no component at all
6453 * TODO: It might be better to validate the element, even if it won't be
6454 * used.
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006455 */
6456 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
6457 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(nonNegativeInteger | unbounded)");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006458 if ((minOccurs == 0) && (maxOccurs == 0))
6459 return (NULL);
6460 /*
6461 * If we get a "ref" attribute on a local <element> we will assume it's
6462 * a reference - even if there's a "name" attribute; this seems to be more
6463 * robust.
6464 */
6465 if (isRef) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006466 char buf[50];
Daniel Veillardc0826a72004-08-10 14:17:33 +00006467 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix;
6468
6469 /*
6470 * Parse as a particle.
6471 */
6472 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006473 (xmlChar **) &xmlSchemaElemDesElemRef,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006474 NULL, attr, &refNs, &refPrefix, &ref);
6475
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006476 snprintf(buf, 49, "#eRef%d", ctxt->counter++ + 1);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006477 ret = xmlSchemaAddElement(ctxt, schema, (const xmlChar *) buf, NULL, node, 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006478 if (ret == NULL) {
6479 if (repName != NULL)
6480 xmlFree(repName);
6481 return (NULL);
6482 }
6483 ret->type = XML_SCHEMA_TYPE_ELEMENT;
6484 ret->node = node;
6485 ret->ref = ref;
6486 ret->refNs = refNs;
6487 ret->refPrefix = refPrefix;
6488 ret->flags |= XML_SCHEMAS_ELEM_REF;
6489 /*
6490 * Check for illegal attributes.
6491 */
6492 /*
6493 * 3.3.3 : 2.1
6494 * One of ref or name must be present, but not both
6495 */
6496 if (nameAttr != NULL) {
6497 xmlSchemaPMutualExclAttrErr(ctxt,
6498 XML_SCHEMAP_SRC_ELEMENT_2_1,
6499 &repName, (xmlSchemaTypePtr) ret, nameAttr,
6500 "ref", "name");
6501 }
6502 /* 3.3.3 : 2.2 */
6503 attr = node->properties;
6504 while (attr != NULL) {
6505 if (attr->ns == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006506 if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
6507 xmlStrEqual(attr->name, BAD_CAST "name") ||
6508 xmlStrEqual(attr->name, BAD_CAST "id") ||
6509 xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
6510 xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
6511 {
6512 attr = attr->next;
6513 continue;
6514 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006515 xmlSchemaPCustomAttrErr(ctxt,
6516 XML_SCHEMAP_SRC_ELEMENT_2_2,
6517 &repName, (xmlSchemaTypePtr) ret, attr,
6518 "Only the attributes 'minOccurs', 'maxOccurs' and "
6519 "'id' are allowed in addition to 'ref'");
6520 break;
6521 }
6522 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6523 xmlSchemaPIllegalAttrErr(ctxt,
6524 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6525 &repName, (xmlSchemaTypePtr) ret, attr);
6526 }
6527 attr = attr->next;
6528 }
6529 } else {
6530 const xmlChar *ns = NULL, *fixed;
6531
6532 /*
6533 * Parse as an element declaration.
6534 */
6535 if (xmlSchemaPValAttrNode(ctxt,
6536 (xmlChar **) &xmlSchemaElemDesElemDecl, NULL, nameAttr,
6537 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
6538 return (NULL);
6539 /*
6540 * Evaluate the target namespace.
6541 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006542 if (topLevel) {
6543 ns = schema->targetNamespace;
6544 } else {
6545 attr = xmlSchemaGetPropNode(node, "form");
6546 if (attr != NULL) {
6547 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6548 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
William M. Bracke7091952004-05-11 15:09:58 +00006549 ns = schema->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006550 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
6551 xmlSchemaPSimpleTypeErr(ctxt,
6552 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6553 &repName, NULL, (xmlNodePtr) attr,
6554 NULL, "(qualified | unqualified)",
6555 attrValue, NULL, NULL, NULL);
6556 }
6557 } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
6558 ns = schema->targetNamespace;
William M. Brack2f2a6632004-08-20 23:09:47 +00006559 }
6560 ret = xmlSchemaAddElement(ctxt, schema, name, ns, node, topLevel);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006561 if (ret == NULL) {
6562 if (repName != NULL)
6563 xmlFree(repName);
6564 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006565 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006566 ret->type = XML_SCHEMA_TYPE_ELEMENT;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006567 ret->node = node;
6568 ret->targetNamespace = ns;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006569 /*
6570 * Check for illegal attributes.
6571 */
William M. Bracke7091952004-05-11 15:09:58 +00006572 attr = node->properties;
6573 while (attr != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006574 if (attr->ns == NULL) {
6575 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
6576 (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
6577 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6578 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
6579 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
6580 (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006581 (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
6582 {
6583 if (topLevel == 0) {
6584 if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006585 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006586 (!xmlStrEqual(attr->name, BAD_CAST "form")))
6587 {
6588 if (xmlStrEqual(attr->name, BAD_CAST "substitutionGroup")) {
6589 /*
6590 * 3.3.6 : 3 If there is a non-·absent· {substitution
6591 * group affiliation}, then {scope} must be global.
6592 * TODO: This one is redundant, since the S4S does
6593 * prohibit this attribute on local declarations already;
6594 * so why an explicit error code? Weird spec.
6595 * TODO: Move this to the proper constraint layer.
6596 * TODO: Or better wait for spec 1.1 to come.
6597 */
6598 xmlSchemaPIllegalAttrErr(ctxt,
6599 XML_SCHEMAP_E_PROPS_CORRECT_3,
6600 &repName, (xmlSchemaTypePtr) ret, attr);
6601 } else {
6602 xmlSchemaPIllegalAttrErr(ctxt,
6603 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6604 &repName, (xmlSchemaTypePtr) ret, attr);
6605 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006606 }
6607 } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
6608 (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
6609 (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
6610
6611 xmlSchemaPIllegalAttrErr(ctxt,
6612 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6613 &repName, (xmlSchemaTypePtr) ret, attr);
6614 }
6615 }
6616 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6617
6618 xmlSchemaPIllegalAttrErr(ctxt,
6619 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6620 &repName, (xmlSchemaTypePtr) ret, attr);
William M. Bracke7091952004-05-11 15:09:58 +00006621 }
6622 attr = attr->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006623 }
William M. Bracke7091952004-05-11 15:09:58 +00006624 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006625 * Extract/validate attributes.
6626 */
6627 if (topLevel) {
6628 /*
6629 * Process top attributes of global element declarations here.
6630 */
6631 ret->flags |= XML_SCHEMAS_ELEM_GLOBAL;
6632 ret->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
6633 xmlSchemaPValAttrQName(ctxt, schema, &repName,
6634 (xmlSchemaTypePtr) ret, node, "substitutionGroup",
6635 &(ret->substGroupNs), NULL, &(ret->substGroup));
6636 if (xmlGetBooleanProp(ctxt, &repName, (xmlSchemaTypePtr) ret,
6637 node, "abstract", 0))
6638 ret->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
6639 /*
6640 * Attribute "final".
6641 */
6642 attr = xmlSchemaGetPropNode(node, "final");
6643 if (attr == NULL) {
6644 ret->flags |= XML_SCHEMAS_ELEM_FINAL_ABSENT;
6645 } else {
6646 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6647 if (xmlSchemaPValAttrBlockFinal(attrValue, &(ret->flags),
6648 -1,
6649 XML_SCHEMAS_ELEM_FINAL_EXTENSION,
6650 XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
6651 xmlSchemaPSimpleTypeErr(ctxt,
6652 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6653 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00006654 NULL, "(#all | List of (extension | restriction))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00006655 attrValue, NULL, NULL, NULL);
6656 }
6657 }
6658 }
6659 /*
6660 * Attribute "block".
6661 */
6662 attr = xmlSchemaGetPropNode(node, "block");
6663 if (attr == NULL) {
6664 ret->flags |= XML_SCHEMAS_ELEM_BLOCK_ABSENT;
6665 } else {
6666 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6667 if (xmlSchemaPValAttrBlockFinal(attrValue, &(ret->flags),
6668 -1,
6669 XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
6670 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
6671 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
6672 xmlSchemaPSimpleTypeErr(ctxt,
6673 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6674 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00006675 NULL, "(#all | List of (extension | "
Daniel Veillardc0826a72004-08-10 14:17:33 +00006676 "restriction | substitution))", attrValue,
6677 NULL, NULL, NULL);
6678 }
6679 }
6680 if (xmlGetBooleanProp(ctxt, &repName, (xmlSchemaTypePtr) ret,
6681 node, "nillable", 0))
6682 ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006683
Daniel Veillardc0826a72004-08-10 14:17:33 +00006684 xmlSchemaPValAttrQName(ctxt, schema,
6685 &repName, (xmlSchemaTypePtr) ret, node,
6686 "type", &(ret->namedTypeNs), NULL, &(ret->namedType));
Daniel Veillard4255d502002-04-16 15:50:10 +00006687
Daniel Veillardc0826a72004-08-10 14:17:33 +00006688 ret->value = xmlSchemaGetProp(ctxt, node, "default");
6689 attr = xmlSchemaGetPropNode(node, "fixed");
6690 if (attr != NULL) {
6691 fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6692 if (ret->value != NULL) {
6693 /*
6694 * 3.3.3 : 1
6695 * default and fixed must not both be present.
6696 */
6697 xmlSchemaPMutualExclAttrErr(ctxt,
6698 XML_SCHEMAP_SRC_ELEMENT_1,
6699 &repName, (xmlSchemaTypePtr) ret, attr,
6700 "default", "fixed");
6701 } else {
6702 ret->flags |= XML_SCHEMAS_ELEM_FIXED;
6703 ret->value = fixed;
6704 }
6705 }
6706 }
6707 /*
6708 * Extract/validate common attributes.
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006709 */
6710 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6711 node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006712 ret->minOccurs = minOccurs;
6713 ret->maxOccurs = maxOccurs;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006714 if (topLevel != 1)
6715 xmlSchemaPCheckParticleCorrect_2(ctxt, (xmlSchemaTypePtr) ret,
6716 node, minOccurs, maxOccurs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006717 /*
6718 * And now for the children...
6719 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006720 ctxt->container = ret->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006721 child = node->children;
6722 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006723 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6724 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006725 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006726 if (isRef) {
6727 if (child != NULL) {
6728 xmlSchemaPContentErr(ctxt,
6729 XML_SCHEMAP_SRC_ELEMENT_2_2,
6730 &repName, (xmlSchemaTypePtr) ret, node, child,
6731 NULL, "(annotation?)");
William M. Bracke7091952004-05-11 15:09:58 +00006732 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006733 } else {
William M. Bracke7091952004-05-11 15:09:58 +00006734 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006735 /*
6736 * 3.3.3 : 3
6737 * "type" and either <simpleType> or <complexType> are mutually
6738 * exclusive
6739 */
William M. Bracke7091952004-05-11 15:09:58 +00006740 if (ret->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006741 xmlSchemaPContentErr(ctxt,
6742 XML_SCHEMAP_SRC_ELEMENT_3,
6743 &repName, (xmlSchemaTypePtr) ret, node, child,
6744 "The attribute 'type' and the <complexType> child are "
6745 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006746 } else
Daniel Veillard3646d642004-06-02 19:19:14 +00006747 ret->subtypes = xmlSchemaParseComplexType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00006748 child = child->next;
6749 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006750 /*
6751 * 3.3.3 : 3
6752 * "type" and either <simpleType> or <complexType> are
6753 * mutually exclusive
6754 */
William M. Bracke7091952004-05-11 15:09:58 +00006755 if (ret->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006756 xmlSchemaPContentErr(ctxt,
6757 XML_SCHEMAP_SRC_ELEMENT_3,
6758 &repName, (xmlSchemaTypePtr) ret, node, child,
6759 "The attribute 'type' and the <simpleType> child are "
6760 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006761 } else
Daniel Veillard3646d642004-06-02 19:19:14 +00006762 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00006763 child = child->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006764 }
William M. Bracke7091952004-05-11 15:09:58 +00006765 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00006766 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006767#ifdef IDC_ENABLED
6768 if (IS_SCHEMA(child, "unique")) {
6769 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
6770 XML_SCHEMA_TYPE_IDC_UNIQUE, ret->targetNamespace);
6771 } else if (IS_SCHEMA(child, "key")) {
6772 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
6773 XML_SCHEMA_TYPE_IDC_KEY, ret->targetNamespace);
6774 } else if (IS_SCHEMA(child, "keyref")) {
6775 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
6776 XML_SCHEMA_TYPE_IDC_KEYREF, ret->targetNamespace);
6777 }
6778 if (lastIDC != NULL)
6779 lastIDC->next = curIDC;
6780 else
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006781 ret->idcs = (void *) curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006782 lastIDC = curIDC;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006783#else
6784 TODO
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006785#endif
6786 child = child->next;
William M. Bracke7091952004-05-11 15:09:58 +00006787 }
6788 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006789 xmlSchemaPContentErr(ctxt,
6790 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6791 &repName, (xmlSchemaTypePtr) ret, node, child,
6792 NULL, "(annotation?, ((simpleType | complexType)?, "
6793 "(unique | key | keyref)*))");
6794 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006795
Daniel Veillardc0826a72004-08-10 14:17:33 +00006796 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006797 ctxt->container = oldcontainer;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006798 /*
6799 * Cleanup.
6800 */
6801 if (repName != NULL)
6802 xmlFree(repName);
6803 /*
6804 * NOTE: Element Declaration Representation OK 4. will be checked at a
6805 * different layer.
6806 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006807 return (ret);
6808}
6809
6810/**
6811 * xmlSchemaParseUnion:
6812 * @ctxt: a schema validation context
6813 * @schema: the schema being built
6814 * @node: a subtree containing XML Schema informations
6815 *
6816 * parse a XML schema Union definition
6817 * *WARNING* this interface is highly subject to change
6818 *
William M. Bracke7091952004-05-11 15:09:58 +00006819 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00006820 * 1 in case of success.
6821 */
6822static xmlSchemaTypePtr
6823xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006824 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006825{
6826 xmlSchemaTypePtr type, subtype, last = NULL;
6827 xmlNodePtr child = NULL;
6828 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00006829 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006830
6831 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6832 return (NULL);
6833
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006834 snprintf((char *) name, 30, "#union%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00006835 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006836 if (type == NULL)
6837 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00006838 type->type = XML_SCHEMA_TYPE_UNION;
Daniel Veillard4255d502002-04-16 15:50:10 +00006839 type->node = node;
William M. Brack2f2a6632004-08-20 23:09:47 +00006840 /*
6841 * Check for illegal attributes.
6842 */
6843 attr = node->properties;
6844 while (attr != NULL) {
6845 if (attr->ns == NULL) {
6846 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6847 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
6848 xmlSchemaPIllegalAttrErr(ctxt,
6849 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6850 NULL, type, attr);
6851 }
6852 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6853 xmlSchemaPIllegalAttrErr(ctxt,
6854 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6855 NULL, type, attr);
6856 }
6857 attr = attr->next;
6858 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006859 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00006860 /*
6861 * Attribute "memberTypes". This is a list of QNames.
6862 * TODO: Validate the QNames.
6863 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00006864 type->base = xmlSchemaGetProp(ctxt, node, "memberTypes");
William M. Brack2f2a6632004-08-20 23:09:47 +00006865 /*
6866 * And now for the children...
6867 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006868 child = node->children;
6869 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006870 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6871 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006872 }
William M. Brack2f2a6632004-08-20 23:09:47 +00006873 while (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006874 subtype = (xmlSchemaTypePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00006875 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006876 if (subtype != NULL) {
6877 if (last == NULL) {
6878 type->subtypes = subtype;
6879 last = subtype;
6880 } else {
6881 last->next = subtype;
6882 last = subtype;
6883 }
6884 last->next = NULL;
6885 }
6886 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006887 }
6888 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006889 /* TODO: Think about the error code. */
6890 xmlSchemaPContentErr(ctxt,
6891 XML_SCHEMAP_UNKNOWN_UNION_CHILD,
6892 NULL, type, node, child, NULL, "(annotation?, simpleType*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006893 }
6894 return (type);
6895}
6896
6897/**
6898 * xmlSchemaParseList:
6899 * @ctxt: a schema validation context
6900 * @schema: the schema being built
6901 * @node: a subtree containing XML Schema informations
6902 *
6903 * parse a XML schema List definition
6904 * *WARNING* this interface is highly subject to change
6905 *
William M. Bracke7091952004-05-11 15:09:58 +00006906 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00006907 * 1 in case of success.
6908 */
6909static xmlSchemaTypePtr
6910xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006911 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006912{
6913 xmlSchemaTypePtr type, subtype;
6914 xmlNodePtr child = NULL;
6915 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00006916 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006917
6918 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6919 return (NULL);
6920
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006921 snprintf((char *) name, 30, "#list%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00006922 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006923 if (type == NULL)
6924 return (NULL);
6925 type->node = node;
6926 type->type = XML_SCHEMA_TYPE_LIST;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006927 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00006928 /*
6929 * Check for illegal attributes.
6930 */
6931 attr = node->properties;
6932 while (attr != NULL) {
6933 if (attr->ns == NULL) {
6934 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6935 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
6936 xmlSchemaPIllegalAttrErr(ctxt,
6937 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6938 NULL, type, attr);
6939 }
6940 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6941 xmlSchemaPIllegalAttrErr(ctxt,
6942 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6943 NULL, type, attr);
6944 }
6945 attr = attr->next;
6946 }
6947 /*
6948 * Attribute "itemType".
6949 */
6950 xmlSchemaPValAttrQName(ctxt, schema, NULL, NULL,
6951 node, "itemType", &(type->baseNs), NULL, &(type->base));
6952 /*
6953 * And now for the children...
6954 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006955 child = node->children;
6956 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006957 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6958 child = child->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00006959 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006960 subtype = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00006961 if (IS_SCHEMA(child, "simpleType")) {
6962 if (type->base != NULL) {
6963 xmlSchemaPCustomErr(ctxt,
6964 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
6965 NULL, type, node,
6966 "The attribute 'itemType' and the <simpleType> child "
6967 "are mutually exclusive", NULL);
6968 } else {
6969 subtype = (xmlSchemaTypePtr)
6970 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
6971 type->subtypes = subtype;
6972 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00006973 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006974 }
6975 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006976 /* TODO: Think about the error code. */
6977 xmlSchemaPContentErr(ctxt,
6978 XML_SCHEMAP_UNKNOWN_LIST_CHILD,
6979 NULL, type, node, child, NULL, "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006980 }
6981 return (type);
6982}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006983
Daniel Veillard4255d502002-04-16 15:50:10 +00006984/**
6985 * xmlSchemaParseSimpleType:
6986 * @ctxt: a schema validation context
6987 * @schema: the schema being built
6988 * @node: a subtree containing XML Schema informations
6989 *
6990 * parse a XML schema Simple Type definition
6991 * *WARNING* this interface is highly subject to change
6992 *
William M. Bracke7091952004-05-11 15:09:58 +00006993 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardc0826a72004-08-10 14:17:33 +00006994 * 1 in case of success.
Daniel Veillard4255d502002-04-16 15:50:10 +00006995 */
6996static xmlSchemaTypePtr
6997xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00006998 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006999{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007000 xmlSchemaTypePtr type, subtype, oldCtxtType, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00007001 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007002 const xmlChar *attrValue = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007003 xmlChar *des = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007004 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00007005
7006 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7007 return (NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007008
Daniel Veillardc0826a72004-08-10 14:17:33 +00007009 if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007010 attr = xmlSchemaGetPropNode(node, "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007011 if (attr == NULL) {
7012 xmlSchemaPMissingAttrErr(ctxt,
7013 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007014 (xmlChar **) &xmlSchemaElemDesST, NULL, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007015 "name", NULL);
7016 return (NULL);
7017 } else if (xmlSchemaPValAttrNode(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007018 (xmlChar **) &xmlSchemaElemDesST, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007019 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00007020 return (NULL);
7021 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007022 }
7023
7024 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007025 char buf[40];
Daniel Veillardc0826a72004-08-10 14:17:33 +00007026
Daniel Veillard01fa6152004-06-29 17:04:39 +00007027 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007028 * Parse as local simple type definition.
Daniel Veillard01fa6152004-06-29 17:04:39 +00007029 */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00007030 snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007031 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007032 if (type == NULL)
7033 return (NULL);
7034 type->node = node;
7035 type->type = XML_SCHEMA_TYPE_SIMPLE;
7036 /*
7037 * Check for illegal attributes.
7038 */
7039 attr = node->properties;
7040 while (attr != NULL) {
7041 if (attr->ns == NULL) {
7042 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
7043 xmlSchemaPIllegalAttrErr(ctxt,
7044 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007045 &des, type, attr);
Daniel Veillard01fa6152004-06-29 17:04:39 +00007046 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007047 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7048 xmlSchemaPIllegalAttrErr(ctxt,
7049 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007050 &des, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007051 }
7052 attr = attr->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +00007053 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007054 } else {
7055 /*
7056 * Parse as global simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007057 *
7058 * Note that attrValue is the value of the attribute "name" here.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007059 */
William M. Brack2f2a6632004-08-20 23:09:47 +00007060 type = xmlSchemaAddType(ctxt, schema, attrValue, schema->targetNamespace, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007061 if (type == NULL)
7062 return (NULL);
7063 type->node = node;
7064 type->type = XML_SCHEMA_TYPE_SIMPLE;
7065 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
7066 /*
7067 * Check for illegal attributes.
7068 */
7069 attr = node->properties;
7070 while (attr != NULL) {
7071 if (attr->ns == NULL) {
7072 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7073 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007074 (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007075 xmlSchemaPIllegalAttrErr(ctxt,
7076 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007077 &des, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007078 }
7079 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7080 xmlSchemaPIllegalAttrErr(ctxt,
7081 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007082 &des, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007083 }
7084 attr = attr->next;
7085 }
7086 /*
7087 * Attribute "final".
7088 */
7089 attr = xmlSchemaGetPropNode(node, "final");
7090 if (attr == NULL) {
7091 type->flags |= XML_SCHEMAS_TYPE_FINAL_DEFAULT;
7092 } else {
7093 attrValue = xmlSchemaGetProp(ctxt, node, "final");
7094 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
7095 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
7096 XML_SCHEMAS_TYPE_FINAL_LIST,
7097 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
7098
7099 xmlSchemaPSimpleTypeErr(ctxt,
7100 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007101 &des, type, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00007102 NULL, "(#all | List of (list | union | restriction)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00007103 attrValue, NULL, NULL, NULL);
7104 }
7105 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00007106 }
7107 type->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00007108 xmlSchemaPValAttrID(ctxt, NULL, type, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007109 /*
7110 * And now for the children...
7111 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007112 oldCtxtType = ctxt->ctxtType;
7113 oldParentItem = ctxt->parentItem;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007114 ctxt->ctxtType = type;
7115 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00007116 child = node->children;
7117 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007118 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7119 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007120 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007121 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00007122 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007123 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00007124 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007125 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007126 } else if (IS_SCHEMA(child, "list")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007127 subtype = (xmlSchemaTypePtr)
7128 xmlSchemaParseList(ctxt, schema, child);
7129 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007130 } else if (IS_SCHEMA(child, "union")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007131 subtype = (xmlSchemaTypePtr)
7132 xmlSchemaParseUnion(ctxt, schema, child);
7133 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007134 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007135 type->subtypes = subtype;
7136 if ((child != NULL) || (subtype == NULL)) {
7137 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007138 &des, type, node, child, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007139 "(annotation?, (restriction | list | union))");
Daniel Veillard4255d502002-04-16 15:50:10 +00007140 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007141 ctxt->parentItem = oldParentItem;
7142 ctxt->ctxtType = oldCtxtType;
7143 FREE_AND_NULL(des)
Daniel Veillard01fa6152004-06-29 17:04:39 +00007144
Daniel Veillard4255d502002-04-16 15:50:10 +00007145 return (type);
7146}
7147
7148
7149/**
7150 * xmlSchemaParseGroup:
7151 * @ctxt: a schema validation context
7152 * @schema: the schema being built
7153 * @node: a subtree containing XML Schema informations
7154 *
7155 * parse a XML schema Group definition
7156 * *WARNING* this interface is highly subject to change
7157 *
William M. Bracke7091952004-05-11 15:09:58 +00007158 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00007159 * 1 in case of success.
7160 */
7161static xmlSchemaTypePtr
7162xmlSchemaParseGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00007163 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00007164{
7165 xmlSchemaTypePtr type, subtype;
7166 xmlNodePtr child = NULL;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00007167 const xmlChar *name, *ns = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007168 const xmlChar *ref = NULL, *refNs = NULL;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00007169 char buf[50];
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00007170 int minOccurs, maxOccurs;
Daniel Veillard4255d502002-04-16 15:50:10 +00007171
7172 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7173 return (NULL);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00007174 /*
7175 * TODO: Validate the element even if no item is created
7176 * (i.e. min/maxOccurs == 0).
7177 */
7178 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
7179 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(nonNegativeInteger | unbounded)");
7180 if ((minOccurs == 0) && (maxOccurs == 0)) {
7181 return (NULL);
7182 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00007183 if (topLevel)
7184 ns = schema->targetNamespace;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007185 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00007186 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007187 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
7188 if (ref == NULL) {
7189 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007190 XML_SCHEMAP_GROUP_NONAME_NOREF,
7191 "Group definition or particle: One of the attributes \"name\" "
7192 "or \"ref\" must be present.\n", NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007193 return (NULL);
7194 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007195 if (refNs == NULL)
7196 refNs = schema->targetNamespace;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00007197 snprintf(buf, 49, "#grRef%d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007198 name = (const xmlChar *) buf;
Daniel Veillard4255d502002-04-16 15:50:10 +00007199 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00007200 type = xmlSchemaAddGroup(ctxt, schema, name, ns, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007201 if (type == NULL)
7202 return (NULL);
7203 type->node = node;
7204 type->type = XML_SCHEMA_TYPE_GROUP;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00007205 if (topLevel)
7206 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00007207 xmlSchemaPValAttrID(ctxt, NULL, type, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00007208 type->ref = ref;
7209 type->refNs = refNs;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00007210 type->minOccurs = minOccurs;
7211 type->maxOccurs = maxOccurs;
7212 xmlSchemaPCheckParticleCorrect_2(ctxt, type,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007213 node, type->minOccurs, type->maxOccurs);
Daniel Veillard4255d502002-04-16 15:50:10 +00007214
7215 child = node->children;
7216 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007217 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7218 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007219 }
7220 subtype = NULL;
7221 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007222 subtype = (xmlSchemaTypePtr)
7223 xmlSchemaParseAll(ctxt, schema, child);
7224 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007225 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007226 subtype = xmlSchemaParseChoice(ctxt, schema, child);
7227 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007228 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007229 subtype = (xmlSchemaTypePtr)
7230 xmlSchemaParseSequence(ctxt, schema, child);
7231 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007232 }
7233 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007234 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00007235 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007236 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_GROUP_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007237 "Group definition \"%s\" has unexpected content.\n", type->name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007238 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007239 }
7240
7241 return (type);
7242}
7243
7244/**
7245 * xmlSchemaParseAll:
7246 * @ctxt: a schema validation context
7247 * @schema: the schema being built
7248 * @node: a subtree containing XML Schema informations
7249 *
7250 * parse a XML schema All definition
7251 * *WARNING* this interface is highly subject to change
7252 *
William M. Bracke7091952004-05-11 15:09:58 +00007253 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00007254 * 1 in case of success.
7255 */
7256static xmlSchemaTypePtr
7257xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007258 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007259{
7260 xmlSchemaTypePtr type, subtype, last = NULL;
7261 xmlNodePtr child = NULL;
7262 xmlChar name[30];
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00007263 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007264
7265 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7266 return (NULL);
7267
7268
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00007269 snprintf((char *) name, 30, "#all%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007270 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007271 if (type == NULL)
7272 return (NULL);
7273 type->node = node;
Daniel Veillard7646b182002-04-20 06:41:40 +00007274 type->type = XML_SCHEMA_TYPE_ALL;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00007275
7276 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007277
7278 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
7279 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00007280
7281 oldcontainer = ctxt->container;
7282 ctxt->container = (const xmlChar *) name;
Daniel Veillard4255d502002-04-16 15:50:10 +00007283 child = node->children;
7284 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007285 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7286 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007287 }
7288 while (IS_SCHEMA(child, "element")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007289 subtype = (xmlSchemaTypePtr)
7290 xmlSchemaParseElement(ctxt, schema, child, 0);
7291 if (subtype != NULL) {
William M. Brackb15351e2003-12-27 04:34:42 +00007292 if (subtype->minOccurs > 1)
7293 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MINOCCURS,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007294 "invalid value for minOccurs (must be 0 or 1).\n",
William M. Brackb15351e2003-12-27 04:34:42 +00007295 NULL, NULL);
7296 if (subtype->maxOccurs > 1)
7297 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MAXOCCURS,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007298 "invalid value for maxOccurs (must be 0 or 1).\n",
William M. Brackb15351e2003-12-27 04:34:42 +00007299 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007300 if (last == NULL) {
7301 type->subtypes = subtype;
7302 last = subtype;
7303 } else {
7304 last->next = subtype;
7305 last = subtype;
7306 }
7307 last->next = NULL;
7308 }
7309 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007310 }
7311 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007312 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ALL_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007313 "<all> has unexpected content.\n", type->name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007314 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007315 }
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00007316 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007317 return (type);
7318}
7319
7320/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007321 * xmlSchemaCleanupDoc:
7322 * @ctxt: a schema validation context
7323 * @node: the root of the document.
7324 *
7325 * removes unwanted nodes in a schemas document tree
7326 */
7327static void
7328xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
7329{
7330 xmlNodePtr delete, cur;
7331
7332 if ((ctxt == NULL) || (root == NULL)) return;
7333
7334 /*
7335 * Remove all the blank text nodes
7336 */
7337 delete = NULL;
7338 cur = root;
7339 while (cur != NULL) {
7340 if (delete != NULL) {
7341 xmlUnlinkNode(delete);
7342 xmlFreeNode(delete);
7343 delete = NULL;
7344 }
7345 if (cur->type == XML_TEXT_NODE) {
7346 if (IS_BLANK_NODE(cur)) {
7347 if (xmlNodeGetSpacePreserve(cur) != 1) {
7348 delete = cur;
7349 }
7350 }
7351 } else if ((cur->type != XML_ELEMENT_NODE) &&
7352 (cur->type != XML_CDATA_SECTION_NODE)) {
7353 delete = cur;
7354 goto skip_children;
7355 }
7356
7357 /*
7358 * Skip to next node
7359 */
7360 if (cur->children != NULL) {
7361 if ((cur->children->type != XML_ENTITY_DECL) &&
7362 (cur->children->type != XML_ENTITY_REF_NODE) &&
7363 (cur->children->type != XML_ENTITY_NODE)) {
7364 cur = cur->children;
7365 continue;
7366 }
7367 }
7368 skip_children:
7369 if (cur->next != NULL) {
7370 cur = cur->next;
7371 continue;
7372 }
7373
7374 do {
7375 cur = cur->parent;
7376 if (cur == NULL)
7377 break;
7378 if (cur == root) {
7379 cur = NULL;
7380 break;
7381 }
7382 if (cur->next != NULL) {
7383 cur = cur->next;
7384 break;
7385 }
7386 } while (cur != NULL);
7387 }
7388 if (delete != NULL) {
7389 xmlUnlinkNode(delete);
7390 xmlFreeNode(delete);
7391 delete = NULL;
7392 }
7393}
7394
William M. Brack2f2a6632004-08-20 23:09:47 +00007395
7396/**
7397 * xmlSchemaImportSchema
7398 *
7399 * @ctxt: a schema validation context
7400 * @schemaLocation: an URI defining where to find the imported schema
7401 *
7402 * import a XML schema
7403 * *WARNING* this interface is highly subject to change
7404 *
7405 * Returns -1 in case of error and 1 in case of success.
7406 */
7407#if 0
7408static xmlSchemaImportPtr
7409xmlSchemaImportSchema(xmlSchemaParserCtxtPtr ctxt,
7410 const xmlChar *schemaLocation)
7411{
7412 xmlSchemaImportPtr import;
7413 xmlSchemaParserCtxtPtr newctxt;
7414
7415 newctxt = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
7416 if (newctxt == NULL) {
7417 xmlSchemaPErrMemory(ctxt, "allocating schema parser context",
7418 NULL);
7419 return (NULL);
7420 }
7421 memset(newctxt, 0, sizeof(xmlSchemaParserCtxt));
7422 /* Keep the same dictionnary for parsing, really */
7423 xmlDictReference(ctxt->dict);
7424 newctxt->dict = ctxt->dict;
7425 newctxt->includes = 0;
7426 newctxt->URL = xmlDictLookup(newctxt->dict, schemaLocation, -1);
7427
7428 xmlSchemaSetParserErrors(newctxt, ctxt->error, ctxt->warning,
7429 ctxt->userData);
7430
7431 import = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
7432 if (import == NULL) {
7433 xmlSchemaPErrMemory(NULL, "allocating imported schema",
7434 NULL);
7435 xmlSchemaFreeParserCtxt(newctxt);
7436 return (NULL);
7437 }
7438
7439 memset(import, 0, sizeof(xmlSchemaImport));
7440 import->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
7441 import->schema = xmlSchemaParse(newctxt);
7442
7443 if (import->schema == NULL) {
7444 /* FIXME use another error enum here ? */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00007445 xmlSchemaPErr(ctxt, NULL, XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00007446 "Failed to import schema from location \"%s\".\n",
7447 schemaLocation, NULL);
7448
7449 xmlSchemaFreeParserCtxt(newctxt);
7450 /* The schemaLocation is held by the dictionary.
7451 if (import->schemaLocation != NULL)
7452 xmlFree((xmlChar *)import->schemaLocation);
7453 */
7454 xmlFree(import);
7455 return NULL;
7456 }
7457
7458 xmlSchemaFreeParserCtxt(newctxt);
7459 return import;
7460}
7461#endif
7462
7463static void
7464xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
7465{
7466 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
7467 schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
7468
7469 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
7470 schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
7471
7472 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
7473 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
7474 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
7475 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
7476 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
7477 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
7478 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
7479 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
7480
7481 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
7482 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
7483 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
7484 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
7485 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
7486 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
7487}
7488
7489static void
7490xmlSchemaParseSchemaDefaults(xmlSchemaParserCtxtPtr ctxt,
7491 xmlSchemaPtr schema,
7492 xmlNodePtr node)
7493{
7494 xmlAttrPtr attr;
7495 const xmlChar *val;
7496
7497 attr = xmlSchemaGetPropNode(node, "elementFormDefault");
7498 if (attr != NULL) {
7499 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7500 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
7501 XML_SCHEMAS_QUALIF_ELEM) != 0) {
7502 xmlSchemaPSimpleTypeErr(ctxt,
7503 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
7504 NULL, NULL, (xmlNodePtr) attr, NULL,
7505 "(qualified | unqualified)", val, NULL, NULL, NULL);
7506 }
7507 }
7508
7509 attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
7510 if (attr != NULL) {
7511 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7512 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
7513 XML_SCHEMAS_QUALIF_ATTR) != 0) {
7514 xmlSchemaPSimpleTypeErr(ctxt,
7515 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
7516 NULL, NULL, (xmlNodePtr) attr, NULL,
7517 "(qualified | unqualified)", val, NULL, NULL, NULL);
7518 }
7519 }
7520
7521 attr = xmlSchemaGetPropNode(node, "finalDefault");
7522 if (attr != NULL) {
7523 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7524 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
7525 XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
7526 XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
7527 -1,
7528 XML_SCHEMAS_FINAL_DEFAULT_LIST,
7529 XML_SCHEMAS_FINAL_DEFAULT_UNION) != 0) {
7530 xmlSchemaPSimpleTypeErr(ctxt,
7531 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7532 NULL, NULL, (xmlNodePtr) attr, NULL,
7533 "(#all | List of (extension | restriction | list | union))",
7534 val, NULL, NULL, NULL);
7535 }
7536 }
7537
7538 attr = xmlSchemaGetPropNode(node, "blockDefault");
7539 if (attr != NULL) {
7540 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7541 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
7542 XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
7543 XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
7544 XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1) != 0) {
7545 xmlSchemaPSimpleTypeErr(ctxt,
7546 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7547 NULL, NULL, (xmlNodePtr) attr, NULL,
7548 "(#all | List of (extension | restriction | substitution))",
7549 val, NULL, NULL, NULL);
7550 }
7551 }
7552}
7553
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007554/**
7555 * xmlSchemaParseSchemaTopLevel:
7556 * @ctxt: a schema validation context
7557 * @schema: the schemas
7558 * @nodes: the list of top level nodes
7559 *
7560 * Returns the internal XML Schema structure built from the resource or
7561 * NULL in case of error
7562 */
7563static void
7564xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
7565 xmlSchemaPtr schema, xmlNodePtr nodes)
7566{
7567 xmlNodePtr child;
7568 xmlSchemaAnnotPtr annot;
7569
7570 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
7571 return;
7572
7573 child = nodes;
7574 while ((IS_SCHEMA(child, "include")) ||
7575 (IS_SCHEMA(child, "import")) ||
7576 (IS_SCHEMA(child, "redefine")) ||
7577 (IS_SCHEMA(child, "annotation"))) {
7578 if (IS_SCHEMA(child, "annotation")) {
7579 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7580 if (schema->annot == NULL)
7581 schema->annot = annot;
7582 else
7583 xmlSchemaFreeAnnot(annot);
7584 } else if (IS_SCHEMA(child, "import")) {
7585 xmlSchemaParseImport(ctxt, schema, child);
7586 } else if (IS_SCHEMA(child, "include")) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00007587 ctxt->includes++;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007588 xmlSchemaParseInclude(ctxt, schema, child);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00007589 ctxt->includes--;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007590 } else if (IS_SCHEMA(child, "redefine")) {
7591 TODO
7592 }
7593 child = child->next;
7594 }
7595 while (child != NULL) {
7596 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007597 xmlSchemaParseComplexType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007598 child = child->next;
7599 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007600 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007601 child = child->next;
7602 } else if (IS_SCHEMA(child, "element")) {
7603 xmlSchemaParseElement(ctxt, schema, child, 1);
7604 child = child->next;
7605 } else if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00007606 xmlSchemaParseAttribute(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007607 child = child->next;
7608 } else if (IS_SCHEMA(child, "attributeGroup")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007609 xmlSchemaParseAttributeGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007610 child = child->next;
7611 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007612 xmlSchemaParseGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007613 child = child->next;
7614 } else if (IS_SCHEMA(child, "notation")) {
7615 xmlSchemaParseNotation(ctxt, schema, child);
7616 child = child->next;
7617 } else {
7618 xmlSchemaPErr2(ctxt, NULL, child,
7619 XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007620 "Unexpected element \"%s\" as child of <schema>.\n",
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007621 child->name, NULL);
7622 child = child->next;
7623 }
7624 while (IS_SCHEMA(child, "annotation")) {
7625 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7626 if (schema->annot == NULL)
7627 schema->annot = annot;
7628 else
7629 xmlSchemaFreeAnnot(annot);
7630 child = child->next;
7631 }
7632 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00007633 ctxt->parentItem = NULL;
7634 ctxt->ctxtType = NULL;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007635}
7636
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007637static xmlSchemaImportPtr
7638xmlSchemaAddImport(xmlSchemaParserCtxtPtr ctxt,
7639 xmlHashTablePtr *imports,
7640 const xmlChar *nsName)
7641{
7642 xmlSchemaImportPtr ret;
7643
7644 if (*imports == NULL) {
Daniel Veillardb9e2f262005-01-23 23:48:34 +00007645 *imports = xmlHashCreateDict(10, ctxt->dict);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007646 if (*imports == NULL) {
7647 xmlSchemaPCustomErr(ctxt,
7648 XML_SCHEMAP_FAILED_BUILD_IMPORT,
7649 NULL, NULL, (xmlNodePtr) ctxt->doc,
7650 "Internal error: failed to build the import table",
7651 NULL);
7652 return (NULL);
7653 }
7654 }
7655 ret = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
7656 if (ret == NULL) {
7657 xmlSchemaPErrMemory(NULL, "allocating import struct", NULL);
7658 return (NULL);
7659 }
7660 memset(ret, 0, sizeof(xmlSchemaImport));
7661 if (nsName == NULL)
7662 nsName = XML_SCHEMAS_NO_NAMESPACE;
7663 xmlHashAddEntry(*imports, nsName, ret);
7664
7665 return (ret);
7666}
7667
7668static int
7669xmlSchemaAcquireSchemaDoc(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007670 xmlSchemaPtr schema,
7671 xmlNodePtr node,
7672 const xmlChar *nsName,
7673 const xmlChar *location,
7674 xmlDocPtr *doc,
7675 const xmlChar **targetNamespace,
7676 int absolute)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007677{
7678 xmlParserCtxtPtr parserCtxt;
7679 xmlSchemaImportPtr import;
7680 const xmlChar *ns;
7681 xmlNodePtr root;
7682
7683 /*
7684 * NOTE: This will be used for <import>, <xsi:schemaLocation> and
7685 * <xsi:noNamespaceSchemaLocation>.
7686 */
7687 *doc = NULL;
7688 /*
7689 * Given that the schemaLocation [attribute] is only a hint, it is open
7690 * to applications to ignore all but the first <import> for a given
7691 * namespace, regardless of the ·actual value· of schemaLocation, but
7692 * such a strategy risks missing useful information when new
7693 * schemaLocations are offered.
7694 *
7695 * XSV (ver 2.5-2) does use the first <import> which resolves to a valid schema.
7696 * Xerces-J (ver 2.5.1) ignores all but the first given <import> - regardless if
7697 * valid or not.
7698 * We will follow XSV here.
7699 */
7700 if (location == NULL) {
7701 /*
7702 * Schema Document Location Strategy:
7703 *
7704 * 3 Based on the namespace name, identify an existing schema document,
7705 * either as a resource which is an XML document or a <schema> element
7706 * information item, in some local schema repository;
7707 *
7708 * 5 Attempt to resolve the namespace name to locate such a resource.
7709 *
7710 * NOTE: Those stategies are not supported, so we will skip.
7711 */
7712 return (0);
7713 }
7714 if (nsName == NULL)
7715 ns = XML_SCHEMAS_NO_NAMESPACE;
7716 else
7717 ns = nsName;
7718
7719 import = xmlHashLookup(schema->schemasImports, ns);
7720 if (import != NULL) {
7721 /*
7722 * There was a valid resource for the specified namespace already
7723 * defined, so skip.
7724 * TODO: This might be changed someday to allow import of
7725 * components from multiple documents for a single target namespace.
7726 */
7727 return (0);
7728 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007729
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007730 /*
7731 * Schema Document Location Strategy:
7732 *
7733 * 2 Based on the location URI, identify an existing schema document,
7734 * either as a resource which is an XML document or a <schema> element
7735 * information item, in some local schema repository;
7736 *
7737 * 4 Attempt to resolve the location URI, to locate a resource on the
7738 * web which is or contains or references a <schema> element;
7739 * TODO: Hmm, I don't know if the reference stuff in 4. will work.
7740 *
7741 */
7742 if ((absolute == 0) && (node != NULL)) {
7743 xmlChar *base, *URI;
7744
7745 base = xmlNodeGetBase(node->doc, node);
7746 if (base == NULL) {
7747 URI = xmlBuildURI(location, node->doc->URL);
7748 } else {
7749 URI = xmlBuildURI(location, base);
7750 xmlFree(base);
7751 }
7752 if (URI != NULL) {
7753 location = xmlDictLookup(ctxt->dict, URI, -1);
7754 xmlFree(URI);
7755 }
7756 }
7757 parserCtxt = xmlNewParserCtxt();
7758 if (parserCtxt == NULL) {
7759 xmlSchemaPErrMemory(NULL, "xmlSchemaParseImport: "
7760 "allocating a parser context", NULL);
7761 return(-1);
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00007762 }
7763
7764 if ((ctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
7765 xmlDictFree(parserCtxt->dict);
7766 parserCtxt->dict = ctxt->dict;
7767 xmlDictReference(parserCtxt->dict);
7768 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007769
7770 *doc = xmlCtxtReadFile(parserCtxt, (const char *) location,
7771 NULL, SCHEMAS_PARSE_OPTIONS);
7772
7773 /*
7774 * 2.1 The referent is (a fragment of) a resource which is an
7775 * XML document (see clause 1.1), which in turn corresponds to
7776 * a <schema> element information item in a well-formed information
7777 * set, which in turn corresponds to a valid schema.
7778 * TODO: What to do with the "fragment" stuff?
7779 *
7780 * 2.2 The referent is a <schema> element information item in
7781 * a well-formed information set, which in turn corresponds
7782 * to a valid schema.
7783 * NOTE: 2.2 won't apply, since only XML documents will be processed
7784 * here.
7785 */
7786 if (*doc == NULL) {
7787 xmlErrorPtr lerr;
7788 /*
7789 * It is *not* an error for the application schema reference
7790 * strategy to fail.
7791 *
7792 * If the doc is NULL and the parser error is an IO error we
7793 * will assume that the resource could not be located or accessed.
7794 *
7795 * TODO: Try to find specific error codes to react only on
7796 * localisation failures.
7797 *
7798 * TODO, FIXME: Check the spec: is a namespace added to the imported
7799 * namespaces, even if the schemaLocation did not provide
7800 * a resource? I guess so, since omitting the "schemaLocation"
7801 * attribute, imports a namespace as well.
7802 */
7803 lerr = xmlGetLastError();
7804 if ((lerr != NULL) && (lerr->domain == XML_FROM_IO)) {
7805 xmlFreeParserCtxt(parserCtxt);
7806 return(0);
7807 }
7808
7809 xmlSchemaPCustomErr(ctxt,
7810 XML_SCHEMAP_SRC_IMPORT_2_1,
7811 NULL, NULL, node,
7812 "Failed to parse the resource '%s' for import",
7813 location);
7814 xmlFreeParserCtxt(parserCtxt);
7815 return(XML_SCHEMAP_SRC_IMPORT_2_1);
7816 }
7817 xmlFreeParserCtxt(parserCtxt);
7818
7819 root = xmlDocGetRootElement(*doc);
7820 if (root == NULL) {
7821 xmlSchemaPCustomErr(ctxt,
7822 XML_SCHEMAP_SRC_IMPORT_2_1,
7823 NULL, NULL, node,
7824 "The XML document '%s' to be imported has no document "
7825 "element", location);
7826 xmlFreeDoc(*doc);
7827 *doc = NULL;
7828 return (XML_SCHEMAP_SRC_IMPORT_2_1);
7829 }
7830
7831 xmlSchemaCleanupDoc(ctxt, root);
7832
7833 if (!IS_SCHEMA(root, "schema")) {
7834 xmlSchemaPCustomErr(ctxt,
7835 XML_SCHEMAP_SRC_IMPORT_2_1,
7836 NULL, NULL, node,
7837 "The XML document '%s' to be imported is not a XML schema document",
7838 location);
7839 xmlFreeDoc(*doc);
7840 *doc = NULL;
7841 return (XML_SCHEMAP_SRC_IMPORT_2_1);
7842 }
7843 *targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
7844 /*
7845 * Schema Representation Constraint: Import Constraints and Semantics
7846 */
7847 if (nsName == NULL) {
7848 if (*targetNamespace != NULL) {
7849 xmlSchemaPCustomErr(ctxt,
7850 XML_SCHEMAP_SRC_IMPORT_3_2,
7851 NULL, NULL, node,
7852 "The XML schema to be imported is not expected "
7853 "to have a target namespace; this differs from "
7854 "its target namespace of '%s'", *targetNamespace);
7855 xmlFreeDoc(*doc);
7856 *doc = NULL;
7857 return (XML_SCHEMAP_SRC_IMPORT_3_2);
7858 }
7859 } else {
7860 if (*targetNamespace == NULL) {
7861 xmlSchemaPCustomErr(ctxt,
7862 XML_SCHEMAP_SRC_IMPORT_3_1,
7863 NULL, NULL, node,
7864 "The XML schema to be imported is expected to have a target "
7865 "namespace of '%s'", nsName);
7866 xmlFreeDoc(*doc);
7867 *doc = NULL;
7868 return (XML_SCHEMAP_SRC_IMPORT_3_1);
7869 } else if (!xmlStrEqual(*targetNamespace, nsName)) {
7870 xmlSchemaPCustomErrExt(ctxt,
7871 XML_SCHEMAP_SRC_IMPORT_3_1,
7872 NULL, NULL, node,
7873 "The XML schema to be imported is expected to have a "
7874 "target namespace of '%s'; this differs from "
7875 "its target namespace of '%s'",
7876 nsName, *targetNamespace, NULL);
7877 xmlFreeDoc(*doc);
7878 *doc = NULL;
7879 return (XML_SCHEMAP_SRC_IMPORT_3_1);
7880 }
7881 }
7882
7883 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports), nsName);
7884 if (import == NULL) {
7885 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT,
7886 NULL, NULL, NULL,
7887 "Internal error: xmlSchemaAcquireSchemaDoc, "
7888 "failed to build import table", NULL);
7889 xmlFreeDoc(*doc);
7890 *doc = NULL;
7891 return (-1);
7892 }
7893 import->schemaLocation = location;
7894 import->doc = *doc;
7895 return (0);
7896}
William M. Brack2f2a6632004-08-20 23:09:47 +00007897
7898/**
7899 * xmlSchemaParseImport:
7900 * @ctxt: a schema validation context
7901 * @schema: the schema being built
7902 * @node: a subtree containing XML Schema informations
7903 *
7904 * parse a XML schema Import definition
7905 * *WARNING* this interface is highly subject to change
7906 *
7907 * Returns 0 in case of success, a positive error code if
7908 * not valid and -1 in case of an internal error.
7909 */
7910static int
7911xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
7912 xmlNodePtr node)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007913{
7914 xmlNodePtr child;
7915 const xmlChar *namespace = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00007916 const xmlChar *schemaLocation = NULL;
7917 const xmlChar *targetNamespace, *oldTNS, *url;
7918 xmlAttrPtr attr;
7919 xmlDocPtr doc;
7920 xmlNodePtr root;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007921 int flags, ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00007922
7923
7924 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7925 return (-1);
7926
7927 /*
7928 * Check for illegal attributes.
7929 */
7930 attr = node->properties;
7931 while (attr != NULL) {
7932 if (attr->ns == NULL) {
7933 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7934 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
7935 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
7936 xmlSchemaPIllegalAttrErr(ctxt,
7937 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7938 NULL, NULL, attr);
7939 }
7940 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7941 xmlSchemaPIllegalAttrErr(ctxt,
7942 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7943 NULL, NULL, attr);
7944 }
7945 attr = attr->next;
7946 }
7947 /*
7948 * Extract and validate attributes.
7949 */
7950 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
7951 "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
7952 &namespace) != 0) {
7953 xmlSchemaPSimpleTypeErr(ctxt,
7954 XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI,
7955 NULL, NULL, node,
7956 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
7957 NULL, namespace, NULL, NULL, NULL);
7958 return (XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI);
7959 }
7960
7961 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
7962 "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
7963 &schemaLocation) != 0) {
7964 xmlSchemaPSimpleTypeErr(ctxt,
7965 XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI,
7966 NULL, NULL, node,
7967 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
7968 NULL, namespace, NULL, NULL, NULL);
7969 return (XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI);
7970 }
7971 /*
7972 * And now for the children...
7973 */
7974 child = node->children;
7975 if (IS_SCHEMA(child, "annotation")) {
7976 /*
7977 * the annotation here is simply discarded ...
7978 */
7979 child = child->next;
7980 }
7981 if (child != NULL) {
7982 xmlSchemaPContentErr(ctxt,
7983 XML_SCHEMAP_UNKNOWN_IMPORT_CHILD,
7984 NULL, NULL, node, child, NULL,
7985 "(annotation?)");
7986 }
7987 /*
7988 * Apply additional constraints.
7989 */
7990 if (namespace != NULL) {
7991 /*
7992 * 1.1 If the namespace [attribute] is present, then its ·actual value·
7993 * must not match the ·actual value· of the enclosing <schema>'s
7994 * targetNamespace [attribute].
7995 */
7996 if (xmlStrEqual(schema->targetNamespace, namespace)) {
7997 xmlSchemaPCustomErr(ctxt,
7998 XML_SCHEMAP_SRC_IMPORT_1_1,
7999 NULL, NULL, node,
8000 "The value of the attribute 'namespace' must not match "
8001 "the target namespace '%s' of the importing schema",
8002 schema->targetNamespace);
8003 return (XML_SCHEMAP_SRC_IMPORT_1_1);
8004 }
8005 } else {
8006 /*
8007 * 1.2 If the namespace [attribute] is not present, then the enclosing
8008 * <schema> must have a targetNamespace [attribute].
8009 */
8010 if (schema->targetNamespace == NULL) {
8011 xmlSchemaPCustomErr(ctxt,
8012 XML_SCHEMAP_SRC_IMPORT_1_2,
8013 NULL, NULL, node,
8014 "The attribute 'namespace' must be existent if "
8015 "the importing schema has no target namespace",
8016 NULL);
8017 return (XML_SCHEMAP_SRC_IMPORT_1_2);
8018 }
8019 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008020 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008021 * Locate and aquire the schema document.
William M. Brack2f2a6632004-08-20 23:09:47 +00008022 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008023 ret = xmlSchemaAcquireSchemaDoc(ctxt, schema, node, namespace,
8024 schemaLocation, &doc, &targetNamespace, 0);
8025 if (ret != 0) {
8026 if (doc != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00008027 xmlFreeDoc(doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008028 return (ret);
8029 } else if (doc != NULL) {
8030 /*
8031 * Save and reset the context & schema.
8032 */
8033 url = ctxt->URL;
8034 /* TODO: Is using the doc->URL here correct? */
8035 ctxt->URL = doc->URL;
8036 flags = schema->flags;
8037 oldTNS = schema->targetNamespace;
8038 /*
8039 * Parse the schema.
8040 */
8041 root = xmlDocGetRootElement(doc);
8042 xmlSchemaClearSchemaDefaults(schema);
8043 xmlSchemaParseSchemaDefaults(ctxt, schema, root);
8044 schema->targetNamespace = targetNamespace;
8045 xmlSchemaParseSchemaTopLevel(ctxt, schema, root->children);
8046 /*
8047 * Restore the context & schema.
8048 */
8049 schema->flags = flags;
8050 schema->targetNamespace = oldTNS;
8051 ctxt->URL = url;
William M. Brack2f2a6632004-08-20 23:09:47 +00008052 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008053
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008054 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +00008055}
8056
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008057/**
8058 * xmlSchemaParseInclude:
8059 * @ctxt: a schema validation context
8060 * @schema: the schema being built
8061 * @node: a subtree containing XML Schema informations
8062 *
8063 * parse a XML schema Include definition
8064 *
William M. Bracke7091952004-05-11 15:09:58 +00008065 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008066 * 1 in case of success.
8067 */
8068static int
8069xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
8070 xmlNodePtr node)
8071{
8072 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008073 const xmlChar *schemaLocation, *targetNamespace;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008074 xmlDocPtr doc;
8075 xmlNodePtr root;
8076 xmlSchemaIncludePtr include;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008077 int wasConvertingNs = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00008078 xmlAttrPtr attr;
8079 int saveFlags;
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00008080 xmlParserCtxtPtr parserCtxt;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008081
8082
8083 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8084 return (-1);
8085
8086 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00008087 * Check for illegal attributes.
8088 */
8089 attr = node->properties;
8090 while (attr != NULL) {
8091 if (attr->ns == NULL) {
8092 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8093 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
8094 xmlSchemaPIllegalAttrErr(ctxt,
8095 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8096 NULL, NULL, attr);
8097 }
8098 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8099 xmlSchemaPIllegalAttrErr(ctxt,
8100 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8101 NULL, NULL, attr);
8102 }
8103 attr = attr->next;
8104 }
8105 /*
8106 * Extract and validate attributes.
8107 */
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00008108 xmlSchemaPValAttrID(ctxt, NULL, NULL,
8109 node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00008110 /*
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008111 * Preliminary step, extract the URI-Reference for the include and
8112 * make an URI from the base.
8113 */
William M. Brack2f2a6632004-08-20 23:09:47 +00008114 attr = xmlSchemaGetPropNode(node, "schemaLocation");
8115 if (attr != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008116 xmlChar *base = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00008117 xmlChar *uri = NULL;
8118
8119 if (xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
8120 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &schemaLocation) != 0)
8121 return (-1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008122 base = xmlNodeGetBase(node->doc, node);
8123 if (base == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008124 uri = xmlBuildURI(schemaLocation, node->doc->URL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008125 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00008126 uri = xmlBuildURI(schemaLocation, base);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008127 xmlFree(base);
8128 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008129 if (uri != NULL) {
8130 schemaLocation = xmlDictLookup(ctxt->dict, uri, -1);
8131 xmlFree(uri);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008132 }
8133 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00008134 xmlSchemaPMissingAttrErr(ctxt,
8135 XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI,
8136 NULL, NULL, node, "schemaLocation", NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008137 return (-1);
8138 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008139 /*
8140 * And now for the children...
8141 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008142 child = node->children;
8143 while (IS_SCHEMA(child, "annotation")) {
8144 /*
8145 * the annotations here are simply discarded ...
8146 */
8147 child = child->next;
8148 }
8149 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008150 xmlSchemaPContentErr(ctxt,
8151 XML_SCHEMAP_UNKNOWN_INCLUDE_CHILD,
8152 NULL, NULL, node, child, NULL,
8153 "(annotation?)");
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008154 }
8155
8156 /*
8157 * First step is to parse the input document into an DOM/Infoset
8158 */
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00008159 /*
8160 * TODO: Use xmlCtxtReadFile to share the dictionary.
8161 */
8162 parserCtxt = xmlNewParserCtxt();
8163 if (parserCtxt == NULL) {
8164 xmlSchemaPErrMemory(NULL, "xmlSchemaParseInclude: "
8165 "allocating a parser context", NULL);
8166 return(-1);
8167 }
8168
8169 if ((ctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
8170 xmlDictFree(parserCtxt->dict);
8171 parserCtxt->dict = ctxt->dict;
8172 xmlDictReference(parserCtxt->dict);
8173 }
8174
8175 doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
8176 NULL, SCHEMAS_PARSE_OPTIONS);
8177 xmlFreeParserCtxt(parserCtxt);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008178 if (doc == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008179 /*
8180 * TODO: It is not an error for the ·actual value· of the
8181 * schemaLocation [attribute] to fail to resolve it all, in which
8182 * case no corresponding inclusion is performed.
8183 * So do we need a warning report here?
8184 */
8185 xmlSchemaPCustomErr(ctxt,
8186 XML_SCHEMAP_FAILED_LOAD,
8187 NULL, NULL, node,
8188 "Failed to load the document '%s' for inclusion", schemaLocation);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008189 return(-1);
8190 }
8191
8192 /*
8193 * Then extract the root of the schema
8194 */
8195 root = xmlDocGetRootElement(doc);
8196 if (root == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008197 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008198 XML_SCHEMAP_NOROOT,
William M. Brack2f2a6632004-08-20 23:09:47 +00008199 NULL, NULL, node,
8200 "The included document '%s' has no document "
8201 "element", schemaLocation);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008202 xmlFreeDoc(doc);
8203 return (-1);
8204 }
8205
8206 /*
8207 * Remove all the blank text nodes
8208 */
8209 xmlSchemaCleanupDoc(ctxt, root);
8210
8211 /*
8212 * Check the schemas top level element
8213 */
8214 if (!IS_SCHEMA(root, "schema")) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008215 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008216 XML_SCHEMAP_NOT_SCHEMA,
William M. Brack2f2a6632004-08-20 23:09:47 +00008217 NULL, NULL, node,
8218 "The document '%s' to be included is not a schema document",
8219 schemaLocation);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008220 xmlFreeDoc(doc);
8221 return (-1);
8222 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008223
William M. Brack2f2a6632004-08-20 23:09:47 +00008224 targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008225 /*
8226 * 2.1 SII has a targetNamespace [attribute], and its ·actual
8227 * value· is identical to the ·actual value· of the targetNamespace
8228 * [attribute] of SIIÂ’ (which must have such an [attribute]).
8229 */
8230 if (targetNamespace != NULL) {
8231 if (schema->targetNamespace == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008232 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008233 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00008234 NULL, NULL, node,
8235 "The target namespace of the included schema "
8236 "'%s' has to be absent, since the including schema "
8237 "has no target namespace",
8238 schemaLocation);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008239 xmlFreeDoc(doc);
8240 return (-1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008241 } else if (!xmlStrEqual(targetNamespace, schema->targetNamespace)) {
8242 xmlSchemaPCustomErrExt(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008243 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00008244 NULL, NULL, node,
8245 "The target namespace '%s' of the included schema '%s' "
8246 "differs from '%s' of the including schema",
8247 targetNamespace, schemaLocation, schema->targetNamespace);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008248 xmlFreeDoc(doc);
8249 return (-1);
8250 }
8251 } else if (schema->targetNamespace != NULL) {
8252 if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
8253 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
8254 } else
8255 wasConvertingNs = 1;
8256 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008257 /*
8258 * register the include
8259 */
8260 include = (xmlSchemaIncludePtr) xmlMalloc(sizeof(xmlSchemaInclude));
8261 if (include == NULL) {
8262 xmlSchemaPErrMemory(ctxt, "allocating included schema", NULL);
8263 xmlFreeDoc(doc);
8264 return (-1);
8265 }
8266
8267 memset(include, 0, sizeof(xmlSchemaInclude));
8268 include->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
8269 include->doc = doc;
8270 include->next = schema->includes;
8271 schema->includes = include;
8272
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008273 /*
8274 * parse the declarations in the included file like if they
8275 * were in the original file.
Daniel Veillardc0826a72004-08-10 14:17:33 +00008276 */
8277 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00008278 * TODO: The complete validation of the <schema> element is not done.
Daniel Veillardc0826a72004-08-10 14:17:33 +00008279 */
William M. Brack2f2a6632004-08-20 23:09:47 +00008280 /*
8281 * The default values ("blockDefault", "elementFormDefault", etc.)
8282 * are set to the values of the included schema and restored afterwards.
8283 */
8284 saveFlags = schema->flags;
8285 xmlSchemaClearSchemaDefaults(schema);
8286 xmlSchemaParseSchemaDefaults(ctxt, schema, root);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008287 xmlSchemaParseSchemaTopLevel(ctxt, schema, root->children);
William M. Brack2f2a6632004-08-20 23:09:47 +00008288 schema->flags = saveFlags;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008289 /*
8290 * Remove the converting flag.
8291 */
William M. Brack2f2a6632004-08-20 23:09:47 +00008292 if ((wasConvertingNs == 0) &&
8293 (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS))
Daniel Veillardc0826a72004-08-10 14:17:33 +00008294 schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008295 return (1);
8296}
8297
8298/**
Daniel Veillard4255d502002-04-16 15:50:10 +00008299 * xmlSchemaParseChoice:
8300 * @ctxt: a schema validation context
8301 * @schema: the schema being built
8302 * @node: a subtree containing XML Schema informations
8303 *
8304 * parse a XML schema Choice definition
8305 * *WARNING* this interface is highly subject to change
8306 *
William M. Bracke7091952004-05-11 15:09:58 +00008307 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00008308 * 1 in case of success.
8309 */
8310static xmlSchemaTypePtr
8311xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008312 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008313{
8314 xmlSchemaTypePtr type, subtype, last = NULL;
8315 xmlNodePtr child = NULL;
8316 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00008317 xmlAttrPtr attr;
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00008318 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00008319
8320 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8321 return (NULL);
8322
8323
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008324 snprintf((char *) name, 30, "#ch%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008325 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00008326 if (type == NULL)
8327 return (NULL);
8328 type->node = node;
8329 type->type = XML_SCHEMA_TYPE_CHOICE;
William M. Brack2f2a6632004-08-20 23:09:47 +00008330 /*
8331 * Check for illegal attributes.
8332 */
8333 attr = node->properties;
8334 while (attr != NULL) {
8335 if (attr->ns == NULL) {
8336 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8337 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
8338 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
8339 xmlSchemaPIllegalAttrErr(ctxt,
8340 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8341 NULL, type, attr);
8342 }
8343 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8344 xmlSchemaPIllegalAttrErr(ctxt,
8345 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8346 NULL, type, attr);
8347 }
8348 attr = attr->next;
8349 }
8350 /*
8351 * Extract and validate attributes.
8352 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00008353 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008354 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
8355 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
8356 "(nonNegativeInteger | unbounded)");
William M. Brack2f2a6632004-08-20 23:09:47 +00008357 /*
8358 * And now for the children...
8359 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00008360 oldcontainer = ctxt->container;
8361 ctxt->container = (const xmlChar *) name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008362 child = node->children;
8363 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008364 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8365 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008366 }
8367 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008368 (IS_SCHEMA(child, "group")) ||
8369 (IS_SCHEMA(child, "any")) ||
8370 (IS_SCHEMA(child, "choice")) ||
8371 (IS_SCHEMA(child, "sequence"))) {
8372 subtype = NULL;
8373 if (IS_SCHEMA(child, "element")) {
8374 subtype = (xmlSchemaTypePtr)
8375 xmlSchemaParseElement(ctxt, schema, child, 0);
8376 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008377 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008378 } else if (IS_SCHEMA(child, "any")) {
8379 subtype = xmlSchemaParseAny(ctxt, schema, child);
8380 } else if (IS_SCHEMA(child, "sequence")) {
8381 subtype = xmlSchemaParseSequence(ctxt, schema, child);
8382 } else if (IS_SCHEMA(child, "choice")) {
8383 subtype = xmlSchemaParseChoice(ctxt, schema, child);
8384 }
8385 if (subtype != NULL) {
8386 if (last == NULL) {
8387 type->subtypes = subtype;
8388 last = subtype;
8389 } else {
8390 last->next = subtype;
8391 last = subtype;
8392 }
8393 last->next = NULL;
8394 }
8395 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008396 }
8397 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008398 /* TODO: error code. */
8399 xmlSchemaPContentErr(ctxt,
8400 XML_SCHEMAP_UNKNOWN_CHOICE_CHILD,
8401 NULL, type, node, child, NULL,
8402 "(annotation?, (element | group | choice | sequence | any)*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00008403 }
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00008404 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00008405 return (type);
8406}
8407
8408/**
8409 * xmlSchemaParseSequence:
8410 * @ctxt: a schema validation context
8411 * @schema: the schema being built
8412 * @node: a subtree containing XML Schema informations
8413 *
8414 * parse a XML schema Sequence definition
8415 * *WARNING* this interface is highly subject to change
8416 *
William M. Bracke7091952004-05-11 15:09:58 +00008417 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00008418 * 1 in case of success.
8419 */
8420static xmlSchemaTypePtr
8421xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008422 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008423{
8424 xmlSchemaTypePtr type, subtype, last = NULL;
8425 xmlNodePtr child = NULL;
8426 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00008427 xmlAttrPtr attr;
8428 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00008429
8430 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8431 return (NULL);
8432
William M. Brack2f2a6632004-08-20 23:09:47 +00008433 oldcontainer = ctxt->container;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008434 snprintf((char *) name, 30, "#seq%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008435 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00008436 if (type == NULL)
8437 return (NULL);
8438 type->node = node;
8439 type->type = XML_SCHEMA_TYPE_SEQUENCE;
William M. Brack2f2a6632004-08-20 23:09:47 +00008440 /*
8441 * Check for illegal attributes.
8442 */
8443 attr = node->properties;
8444 while (attr != NULL) {
8445 if (attr->ns == NULL) {
8446 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8447 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
8448 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
8449 xmlSchemaPIllegalAttrErr(ctxt,
8450 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8451 NULL, type, attr);
8452 }
8453 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8454 xmlSchemaPIllegalAttrErr(ctxt,
8455 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8456 NULL, type, attr);
8457 }
8458 attr = attr->next;
8459 }
8460 /*
8461 * Extract and validate attributes.
8462 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00008463 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008464 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
8465 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
8466 "(nonNegativeInteger | unbounded)");
William M. Brack2f2a6632004-08-20 23:09:47 +00008467 /*
8468 * And now for the children...
8469 */
8470 ctxt->container = (const xmlChar *) name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008471 child = node->children;
8472 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008473 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8474 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008475 }
8476 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008477 (IS_SCHEMA(child, "group")) ||
8478 (IS_SCHEMA(child, "any")) ||
8479 (IS_SCHEMA(child, "choice")) ||
8480 (IS_SCHEMA(child, "sequence"))) {
8481 subtype = NULL;
8482 if (IS_SCHEMA(child, "element")) {
8483 subtype = (xmlSchemaTypePtr)
8484 xmlSchemaParseElement(ctxt, schema, child, 0);
8485 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008486 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008487 } else if (IS_SCHEMA(child, "any")) {
8488 subtype = xmlSchemaParseAny(ctxt, schema, child);
8489 } else if (IS_SCHEMA(child, "choice")) {
8490 subtype = xmlSchemaParseChoice(ctxt, schema, child);
8491 } else if (IS_SCHEMA(child, "sequence")) {
8492 subtype = xmlSchemaParseSequence(ctxt, schema, child);
8493 }
8494 if (subtype != NULL) {
8495 if (last == NULL) {
8496 type->subtypes = subtype;
8497 last = subtype;
8498 } else {
8499 last->next = subtype;
8500 last = subtype;
8501 }
8502 last->next = NULL;
8503 }
8504 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008505 }
8506 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008507 xmlSchemaPContentErr(ctxt,
8508 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
8509 NULL, type, node, child, NULL,
8510 "(annotation?, (element | group | choice | sequence | any)*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00008511 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008512 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00008513
8514 return (type);
8515}
8516
8517/**
8518 * xmlSchemaParseRestriction:
8519 * @ctxt: a schema validation context
8520 * @schema: the schema being built
8521 * @node: a subtree containing XML Schema informations
Daniel Veillard4255d502002-04-16 15:50:10 +00008522 *
8523 * parse a XML schema Restriction definition
8524 * *WARNING* this interface is highly subject to change
8525 *
8526 * Returns the type definition or NULL in case of error
8527 */
8528static xmlSchemaTypePtr
8529xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00008530 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008531{
Daniel Veillard01fa6152004-06-29 17:04:39 +00008532 xmlSchemaTypePtr type, subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00008533 xmlNodePtr child = NULL;
8534 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008535 const xmlChar *oldcontainer;
William M. Brack2f2a6632004-08-20 23:09:47 +00008536 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00008537
8538 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8539 return (NULL);
8540
8541 oldcontainer = ctxt->container;
8542
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008543 snprintf((char *) name, 30, "#restr%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008544 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00008545 if (type == NULL)
8546 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00008547 type->type = XML_SCHEMA_TYPE_RESTRICTION;
Daniel Veillard4255d502002-04-16 15:50:10 +00008548 type->node = node;
William M. Brack2f2a6632004-08-20 23:09:47 +00008549 /*
8550 * Check for illegal attributes.
8551 */
8552 attr = node->properties;
8553 while (attr != NULL) {
8554 if (attr->ns == NULL) {
8555 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8556 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
8557 xmlSchemaPIllegalAttrErr(ctxt,
8558 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8559 NULL, type, attr);
8560 }
8561 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8562 xmlSchemaPIllegalAttrErr(ctxt,
8563 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8564 NULL, type, attr);
8565 }
8566 attr = attr->next;
8567 }
8568 /*
8569 * Extract and validate attributes.
8570 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00008571 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00008572 /*
8573 * Attribute "base".
8574 */
Daniel Veillard4255d502002-04-16 15:50:10 +00008575 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
Daniel Veillard01fa6152004-06-29 17:04:39 +00008576 if ((type->base == NULL) &&
William M. Brack2f2a6632004-08-20 23:09:47 +00008577 (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX)) {
8578 /* TODO: Think about the error code. */
8579 xmlSchemaPMissingAttrErr(ctxt,
8580 XML_SCHEMAP_RESTRICTION_NONAME_NOREF,
8581 NULL, type, node, "base", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008582 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008583 /*
8584 * And now for the children...
8585 */
Daniel Veillard4255d502002-04-16 15:50:10 +00008586 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008587 child = node->children;
8588 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008589 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8590 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008591 }
8592 subtype = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008593 if (ctxt->parentItem->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
8594 if (IS_SCHEMA(child, "all")) {
8595 subtype = (xmlSchemaTypePtr)
8596 xmlSchemaParseAll(ctxt, schema, child);
8597 child = child->next;
8598 type->subtypes = subtype;
8599 } else if (IS_SCHEMA(child, "choice")) {
8600 subtype = xmlSchemaParseChoice(ctxt, schema, child);
8601 child = child->next;
8602 type->subtypes = subtype;
8603 } else if (IS_SCHEMA(child, "sequence")) {
8604 subtype = (xmlSchemaTypePtr)
8605 xmlSchemaParseSequence(ctxt, schema, child);
8606 child = child->next;
8607 type->subtypes = subtype;
8608 } else if (IS_SCHEMA(child, "group")) {
8609 subtype = (xmlSchemaTypePtr)
8610 xmlSchemaParseGroup(ctxt, schema, child, 0);
8611 child = child->next;
8612 type->subtypes = subtype;
8613 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008614 } else if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_SIMPLE) {
8615 if (IS_SCHEMA(child, "simpleType")) {
8616 if (type->base != NULL) {
8617 /*
8618 * src-restriction-base-or-simpleType
8619 * Either the base [attribute] or the simpleType [child] of the
8620 * <restriction> element must be present, but not both.
8621 */
8622 xmlSchemaPContentErr(ctxt,
8623 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
8624 NULL, NULL, type->node, child,
8625 "The attribute 'base' and the <simpleType> child are "
8626 "mutually exclusive", NULL);
8627 } else {
8628 subtype = (xmlSchemaTypePtr)
8629 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
8630 type->baseType = subtype;
8631 }
8632 child = child->next;
8633 }
8634 } else if (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00008635 if (IS_SCHEMA(child, "simpleType")) {
8636 subtype = (xmlSchemaTypePtr)
8637 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008638 type->subtypes = subtype;
8639 child = child->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00008640 }
8641 }
8642 if ((ctxt->ctxtType->type == XML_SCHEMA_TYPE_SIMPLE) ||
8643 (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
8644 xmlSchemaFacetPtr facet, lastfacet = NULL;
8645
Daniel Veillard01fa6152004-06-29 17:04:39 +00008646 /*
8647 * Add the facets to the parent simpleType/complexType.
8648 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00008649 /*
8650 * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
8651 * Simple Type Definition Schema Representation Constraint:
8652 * *Single Facet Value*
8653 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00008654 while ((IS_SCHEMA(child, "minInclusive")) ||
8655 (IS_SCHEMA(child, "minExclusive")) ||
8656 (IS_SCHEMA(child, "maxInclusive")) ||
8657 (IS_SCHEMA(child, "maxExclusive")) ||
8658 (IS_SCHEMA(child, "totalDigits")) ||
8659 (IS_SCHEMA(child, "fractionDigits")) ||
8660 (IS_SCHEMA(child, "pattern")) ||
8661 (IS_SCHEMA(child, "enumeration")) ||
8662 (IS_SCHEMA(child, "whiteSpace")) ||
8663 (IS_SCHEMA(child, "length")) ||
8664 (IS_SCHEMA(child, "maxLength")) ||
8665 (IS_SCHEMA(child, "minLength"))) {
8666 facet = xmlSchemaParseFacet(ctxt, schema, child);
8667 if (facet != NULL) {
8668 if (lastfacet == NULL)
8669 ctxt->ctxtType->facets = facet;
8670 else
8671 lastfacet->next = facet;
8672 lastfacet = facet;
8673 lastfacet->next = NULL;
8674 }
8675 child = child->next;
8676 }
8677 /*
8678 * Create links for derivation and validation.
8679 */
8680 if (lastfacet != NULL) {
8681 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
8682
8683 facet = ctxt->ctxtType->facets;
8684 do {
8685 facetLink = (xmlSchemaFacetLinkPtr) xmlMalloc(sizeof(xmlSchemaFacetLink));
8686 if (facetLink == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008687 xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008688 xmlFree(facetLink);
8689 return (NULL);
8690 }
8691 facetLink->facet = facet;
8692 facetLink->next = NULL;
8693 if (lastFacetLink == NULL)
8694 ctxt->ctxtType->facetSet = facetLink;
8695 else
8696 lastFacetLink->next = facetLink;
8697 lastFacetLink = facetLink;
8698 facet = facet->next;
8699 } while (facet != NULL);
8700 }
8701 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008702 if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX) {
8703 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
8704 if (IS_SCHEMA(child, "anyAttribute")) {
8705 ctxt->ctxtType->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
8706 child = child->next;
8707 }
8708 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008709 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008710 /* TODO: Think about the error code. */
8711 if (ctxt->parentItem->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
8712 xmlSchemaPContentErr(ctxt,
8713 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
8714 NULL, type, node, child, NULL,
8715 "annotation?, (group | all | choice | sequence)?, "
8716 "((attribute | attributeGroup)*, anyAttribute?))");
8717 } else if (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
8718 xmlSchemaPContentErr(ctxt,
8719 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
8720 NULL, type, node, child, NULL,
8721 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
8722 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
8723 "length | minLength | maxLength | enumeration | whiteSpace | "
8724 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
8725 } else {
8726 /* Simple type */
8727 xmlSchemaPContentErr(ctxt,
8728 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
8729 NULL, type, node, child, NULL,
8730 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
8731 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
8732 "length | minLength | maxLength | enumeration | whiteSpace | "
8733 "pattern)*))");
8734 }
8735 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008736 ctxt->container = oldcontainer;
8737 return (type);
8738}
8739
8740/**
8741 * xmlSchemaParseExtension:
8742 * @ctxt: a schema validation context
8743 * @schema: the schema being built
8744 * @node: a subtree containing XML Schema informations
8745 *
8746 * parse a XML schema Extension definition
8747 * *WARNING* this interface is highly subject to change
8748 *
8749 * Returns the type definition or NULL in case of error
8750 */
8751static xmlSchemaTypePtr
8752xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008753 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008754{
8755 xmlSchemaTypePtr type, subtype;
8756 xmlNodePtr child = NULL;
8757 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008758 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00008759
8760 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8761 return (NULL);
8762
8763 oldcontainer = ctxt->container;
8764
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008765 snprintf((char *) name, 30, "#ext%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008766 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00008767 if (type == NULL)
8768 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00008769 type->type = XML_SCHEMA_TYPE_EXTENSION;
Daniel Veillard4255d502002-04-16 15:50:10 +00008770 type->node = node;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00008771
8772 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
8773
Daniel Veillard4255d502002-04-16 15:50:10 +00008774 ctxt->container = name;
8775
8776 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
8777 if (type->base == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008778 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_EXTENSION_NO_BASE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008779 "<extension>: The attribute \"base\" is missing.\n",
8780 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008781 }
8782 child = node->children;
8783 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008784 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8785 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008786 }
8787 subtype = NULL;
8788
8789 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008790 subtype = xmlSchemaParseAll(ctxt, schema, child);
8791 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008792 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008793 subtype = xmlSchemaParseChoice(ctxt, schema, child);
8794 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008795 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008796 subtype = xmlSchemaParseSequence(ctxt, schema, child);
8797 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008798 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008799 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008800 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008801 }
8802 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008803 type->subtypes = subtype;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008804 if ((ctxt->ctxtType != NULL) &&
8805 (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX)) {
8806 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
8807 if (IS_SCHEMA(child, "anyAttribute")) {
8808 ctxt->ctxtType->attributeWildcard =
8809 xmlSchemaParseAnyAttribute(ctxt, schema, child);
8810 child = child->next;
8811 }
8812 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008813 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008814 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008815 XML_SCHEMAP_UNKNOWN_EXTENSION_CHILD,
8816 "<extension> has unexpected content.\n", type->name,
8817 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008818 }
8819 ctxt->container = oldcontainer;
8820 return (type);
8821}
8822
8823/**
8824 * xmlSchemaParseSimpleContent:
8825 * @ctxt: a schema validation context
8826 * @schema: the schema being built
8827 * @node: a subtree containing XML Schema informations
8828 *
8829 * parse a XML schema SimpleContent definition
8830 * *WARNING* this interface is highly subject to change
8831 *
8832 * Returns the type definition or NULL in case of error
8833 */
8834static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008835xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
8836 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008837{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008838 xmlSchemaTypePtr type, subtype, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00008839 xmlNodePtr child = NULL;
8840 xmlChar name[30];
8841
8842 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8843 return (NULL);
8844
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008845 snprintf((char *) name, 30, "#SC%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008846 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00008847 if (type == NULL)
8848 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00008849 type->type = XML_SCHEMA_TYPE_SIMPLE_CONTENT;
Daniel Veillard4255d502002-04-16 15:50:10 +00008850 type->node = node;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00008851
8852 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00008853
8854 child = node->children;
8855 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008856 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8857 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008858 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008859 oldParentItem = ctxt->parentItem;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008860 ctxt->parentItem = type;
8861 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00008862 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008863 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00008864 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008865 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008866 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008867 subtype = (xmlSchemaTypePtr)
8868 xmlSchemaParseExtension(ctxt, schema, child);
8869 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008870 }
8871 type->subtypes = subtype;
8872 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008873 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008874 XML_SCHEMAP_UNKNOWN_SIMPLECONTENT_CHILD,
8875 "<simpleContent> has unexpected content.\n",
8876 NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008877 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008878 ctxt->parentItem = oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00008879 return (type);
8880}
8881
8882/**
8883 * xmlSchemaParseComplexContent:
8884 * @ctxt: a schema validation context
8885 * @schema: the schema being built
8886 * @node: a subtree containing XML Schema informations
8887 *
8888 * parse a XML schema ComplexContent definition
8889 * *WARNING* this interface is highly subject to change
8890 *
8891 * Returns the type definition or NULL in case of error
8892 */
8893static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008894xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
8895 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008896{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008897 xmlSchemaTypePtr type, subtype, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00008898 xmlNodePtr child = NULL;
8899 xmlChar name[30];
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008900 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00008901
8902 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8903 return (NULL);
8904
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008905 snprintf((char *) name, 30, "#CC%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008906 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00008907 if (type == NULL)
8908 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00008909 type->type = XML_SCHEMA_TYPE_COMPLEX_CONTENT;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008910 type->node = node;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008911 /*
8912 * Check for illegal attributes.
8913 */
8914 attr = node->properties;
8915 while (attr != NULL) {
8916 if (attr->ns == NULL) {
8917 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8918 (!xmlStrEqual(attr->name, BAD_CAST "mixed")))
8919 {
8920 xmlSchemaPIllegalAttrErr(ctxt,
8921 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8922 NULL, NULL, attr);
8923 }
8924 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8925 xmlSchemaPIllegalAttrErr(ctxt,
8926 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8927 NULL, NULL, attr);
8928 }
8929 attr = attr->next;
8930 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00008931
8932 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
8933
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008934 /*
8935 * Handle attribute 'mixed'.
8936 */
8937 if (xmlGetBooleanProp(ctxt, NULL, type, node, "mixed", 0)) {
8938 if ((ctxt->ctxtType->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
8939 ctxt->ctxtType->flags |= XML_SCHEMAS_TYPE_MIXED;
8940 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008941 child = node->children;
8942 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008943 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8944 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008945 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008946 oldParentItem = ctxt->parentItem;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008947 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008948 subtype = NULL;
8949 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008950 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00008951 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008952 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008953 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008954 subtype = (xmlSchemaTypePtr)
8955 xmlSchemaParseExtension(ctxt, schema, child);
8956 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008957 }
8958 type->subtypes = subtype;
8959 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008960 xmlSchemaPContentErr(ctxt,
8961 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8962 NULL, NULL, node, child,
8963 NULL, "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +00008964 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008965 ctxt->parentItem = oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00008966 return (type);
8967}
8968
8969/**
8970 * xmlSchemaParseComplexType:
8971 * @ctxt: a schema validation context
8972 * @schema: the schema being built
8973 * @node: a subtree containing XML Schema informations
8974 *
8975 * parse a XML schema Complex Type definition
8976 * *WARNING* this interface is highly subject to change
8977 *
8978 * Returns the type definition or NULL in case of error
8979 */
8980static xmlSchemaTypePtr
8981xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00008982 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00008983{
Daniel Veillard01fa6152004-06-29 17:04:39 +00008984 xmlSchemaTypePtr type, subtype, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00008985 xmlNodePtr child = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008986 const xmlChar *name = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00008987 const xmlChar *oldcontainer;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008988 xmlAttrPtr attr;
8989 const xmlChar *attrValue;
8990 xmlChar *des = NULL; /* The reported designation. */
Daniel Veillard1a380b82004-10-21 16:00:06 +00008991 char buf[40];
8992
Daniel Veillard4255d502002-04-16 15:50:10 +00008993
8994 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8995 return (NULL);
8996
Daniel Veillard01fa6152004-06-29 17:04:39 +00008997 ctxtType = ctxt->ctxtType;
8998
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008999 if (topLevel) {
9000 attr = xmlSchemaGetPropNode(node, "name");
9001 if (attr == NULL) {
9002 xmlSchemaPMissingAttrErr(ctxt,
9003 XML_SCHEMAP_S4S_ATTR_MISSING,
9004 (xmlChar **) &xmlSchemaElemDesCT, NULL, node,
9005 "name", NULL);
9006 return (NULL);
9007 } else if (xmlSchemaPValAttrNode(ctxt,
9008 (xmlChar **) &xmlSchemaElemDesCT, NULL, attr,
9009 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
9010 return (NULL);
9011 }
9012 }
9013
9014 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009015 /*
9016 * Parse as local complex type definition.
9017 */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00009018 snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009019 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
9020 if (type == NULL)
9021 return (NULL);
9022 name = (const xmlChar *) buf;
9023 type->node = node;
9024 type->type = XML_SCHEMA_TYPE_COMPLEX;
9025 /*
9026 * TODO: We need the target namespace.
9027 */
9028 } else {
9029 /*
9030 * Parse as global complex type definition.
9031 */
William M. Brack2f2a6632004-08-20 23:09:47 +00009032 type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace, node);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009033 if (type == NULL)
9034 return (NULL);
9035 type->node = node;
9036 type->type = XML_SCHEMA_TYPE_COMPLEX;
9037 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
9038 /*
9039 * Set defaults.
9040 */
9041 type->flags |= XML_SCHEMAS_TYPE_FINAL_DEFAULT;
9042 type->flags |= XML_SCHEMAS_TYPE_BLOCK_DEFAULT;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00009043 }
9044 type->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009045 /*
9046 * Handle attributes.
9047 */
9048 attr = node->properties;
9049 while (attr != NULL) {
9050 if (attr->ns == NULL) {
9051 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
9052 /*
9053 * Attribute "id".
9054 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00009055 xmlSchemaPValAttrID(ctxt, NULL, type, node,
9056 BAD_CAST "id");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009057 } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
9058 /*
9059 * Attribute "mixed".
9060 */
9061 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
9062 (xmlNodePtr) attr))
9063 type->flags |= XML_SCHEMAS_TYPE_MIXED;
9064 } else if (topLevel) {
9065 /*
9066 * Attributes of global complex type definitions.
9067 */
9068 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
9069 /* Pass. */
9070 } else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
9071 /*
9072 * Attribute "abstract".
9073 */
9074 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
9075 (xmlNodePtr) attr))
9076 type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
9077 } else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
9078 /*
9079 * Attribute "final".
9080 */
9081 attrValue = xmlSchemaGetNodeContent(ctxt,
9082 (xmlNodePtr) attr);
9083 if (xmlSchemaPValAttrBlockFinal(attrValue,
9084 &(type->flags),
9085 -1,
9086 XML_SCHEMAS_TYPE_FINAL_EXTENSION,
9087 XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
9088 -1, -1, -1) != 0)
9089 {
9090 xmlSchemaPSimpleTypeErr(ctxt,
9091 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9092 &des, type, (xmlNodePtr) attr,
9093 NULL,
9094 "(#all | List of (extension | restriction))",
9095 attrValue, NULL, NULL, NULL);
9096 }
9097 } else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
9098 /*
9099 * Attribute "block".
9100 */
9101 attrValue = xmlSchemaGetNodeContent(ctxt,
9102 (xmlNodePtr) attr);
9103 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
9104 -1,
9105 XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
9106 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
9107 -1, -1, -1) != 0) {
9108 xmlSchemaPSimpleTypeErr(ctxt,
9109 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9110 &des, type, (xmlNodePtr) attr,
9111 NULL,
9112 "(#all | List of (extension | restriction)) ",
9113 attrValue, NULL, NULL, NULL);
9114 }
9115 } else {
9116 xmlSchemaPIllegalAttrErr(ctxt,
9117 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9118 &des, type, attr);
9119 }
9120 } else {
9121 xmlSchemaPIllegalAttrErr(ctxt,
9122 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9123 &des, type, attr);
9124 }
9125 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9126 xmlSchemaPIllegalAttrErr(ctxt,
9127 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9128 &des, type, attr);
9129 }
9130 attr = attr->next;
9131 }
9132 /*
9133 * Set as default for attribute wildcards.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009134 * This will be only changed if a complex type
9135 * inherits an attribute wildcard from a base type.
9136 */
9137 type->flags |= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009138 /*
9139 * And now for the children...
9140 */
9141 oldcontainer = ctxt->container;
9142 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +00009143 child = node->children;
9144 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009145 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
9146 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009147 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00009148 ctxt->ctxtType = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00009149 if (IS_SCHEMA(child, "simpleContent")) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009150 /*
9151 * 3.4.3 : 2.2
9152 * Specifying mixed='true' when the <simpleContent>
9153 * alternative is chosen has no effect
9154 */
William M. Bracke7091952004-05-11 15:09:58 +00009155 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
9156 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009157 type->subtypes = xmlSchemaParseSimpleContent(ctxt, schema, child);
9158 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009159 } else if (IS_SCHEMA(child, "complexContent")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009160 type->subtypes = xmlSchemaParseComplexContent(ctxt, schema, child);
9161 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009162 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009163 subtype = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009164 /*
9165 * Parse model groups.
9166 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009167 if (IS_SCHEMA(child, "all")) {
9168 subtype = xmlSchemaParseAll(ctxt, schema, child);
9169 child = child->next;
9170 } else if (IS_SCHEMA(child, "choice")) {
9171 subtype = xmlSchemaParseChoice(ctxt, schema, child);
9172 child = child->next;
9173 } else if (IS_SCHEMA(child, "sequence")) {
9174 subtype = xmlSchemaParseSequence(ctxt, schema, child);
9175 child = child->next;
9176 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009177 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009178 child = child->next;
9179 }
9180 if (subtype != NULL)
9181 type->subtypes = subtype;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009182 /*
9183 * Parse attribute decls/refs.
9184 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009185 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009186 /*
9187 * Parse attribute wildcard.
9188 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009189 if (IS_SCHEMA(child, "anyAttribute")) {
9190 type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
9191 child = child->next;
9192 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009193 }
9194 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009195 xmlSchemaPContentErr(ctxt,
9196 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9197 &des, type, node, child,
9198 NULL, "(annotation?, (simpleContent | complexContent | "
9199 "((group | all | choice | sequence)?, ((attribute | "
9200 "attributeGroup)*, anyAttribute?))))");
Daniel Veillard4255d502002-04-16 15:50:10 +00009201 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009202 FREE_AND_NULL(des);
Daniel Veillard4255d502002-04-16 15:50:10 +00009203 ctxt->container = oldcontainer;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009204 ctxt->ctxtType = ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00009205 return (type);
9206}
9207
Daniel Veillard4255d502002-04-16 15:50:10 +00009208/**
9209 * xmlSchemaParseSchema:
9210 * @ctxt: a schema validation context
9211 * @node: a subtree containing XML Schema informations
9212 *
9213 * parse a XML schema definition from a node set
9214 * *WARNING* this interface is highly subject to change
9215 *
9216 * Returns the internal XML Schema structure built from the resource or
9217 * NULL in case of error
9218 */
9219static xmlSchemaPtr
9220xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
9221{
9222 xmlSchemaPtr schema = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009223 const xmlChar *val;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00009224 int nberrors;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009225 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00009226
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009227 /*
9228 * This one is called by xmlSchemaParse only and is used if
9229 * the schema to be parsed was specified via the API; i.e. not
9230 * automatically by the validated instance document.
9231 */
Daniel Veillard4255d502002-04-16 15:50:10 +00009232 if ((ctxt == NULL) || (node == NULL))
9233 return (NULL);
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00009234 nberrors = ctxt->nberrors;
9235 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00009236 if (IS_SCHEMA(node, "schema")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009237 xmlSchemaImportPtr import;
9238
Daniel Veillard4255d502002-04-16 15:50:10 +00009239 schema = xmlSchemaNewSchema(ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009240 if (schema == NULL)
9241 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009242 /*
9243 * Disable build of list of items.
9244 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00009245 attr = xmlSchemaGetPropNode(node, "targetNamespace");
9246 if (attr != NULL) {
9247 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
9248 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &val);
9249 /*
9250 * TODO: Should we proceed with an invalid target namespace?
9251 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009252 schema->targetNamespace = xmlDictLookup(ctxt->dict, val, -1);
9253 } else {
9254 schema->targetNamespace = NULL;
9255 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009256 /*
9257 * Add the current ns name and location to the import table;
9258 * this is needed to have a consistent mechanism, regardless
9259 * if all schemata are constructed dynamically fired by the
9260 * instance or if the schema to be used was specified via
9261 * the API.
9262 */
9263 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports),
9264 schema->targetNamespace);
9265 if (import == NULL) {
9266 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT,
9267 NULL, NULL, (xmlNodePtr) ctxt->doc,
9268 "Internal error: xmlSchemaParseSchema, "
9269 "failed to add an import entry", NULL);
9270 xmlSchemaFree(schema);
9271 schema = NULL;
9272 return (NULL);
9273 }
9274 import->schemaLocation = ctxt->URL;
9275 /*
9276 * NOTE: We won't set the doc here, otherwise it will be freed
9277 * if the import struct is freed.
9278 * import->doc = ctxt->doc;
9279 */
9280
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00009281 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00009282 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
9283 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &(schema->version));
9284
William M. Brack2f2a6632004-08-20 23:09:47 +00009285 xmlSchemaParseSchemaDefaults(ctxt, schema, node);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009286 xmlSchemaParseSchemaTopLevel(ctxt, schema, node->children);
9287 } else {
9288 xmlDocPtr doc;
9289
9290 doc = node->doc;
9291
9292 if ((doc != NULL) && (doc->URL != NULL)) {
9293 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
9294 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009295 "The file \"%s\" is not a XML schema.\n", doc->URL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009296 } else {
9297 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
9298 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009299 "The file is not a XML schema.\n", NULL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009300 }
9301 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009302 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00009303 if (ctxt->nberrors != 0) {
9304 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009305 xmlSchemaFree(schema);
9306 schema = NULL;
9307 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00009308 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009309 if (schema != NULL)
9310 schema->counter = ctxt->counter;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00009311 ctxt->nberrors = nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00009312#ifdef DEBUG
9313 if (schema == NULL)
9314 xmlGenericError(xmlGenericErrorContext,
9315 "xmlSchemaParse() failed\n");
9316#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00009317 return (schema);
9318}
9319
9320/************************************************************************
9321 * *
9322 * Validating using Schemas *
9323 * *
9324 ************************************************************************/
9325
9326/************************************************************************
9327 * *
9328 * Reading/Writing Schemas *
9329 * *
9330 ************************************************************************/
9331
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009332#if 0 /* Will be enabled if it is clear what options are needed. */
9333/**
9334 * xmlSchemaParserCtxtSetOptions:
9335 * @ctxt: a schema parser context
9336 * @options: a combination of xmlSchemaParserOption
9337 *
9338 * Sets the options to be used during the parse.
9339 *
9340 * Returns 0 in case of success, -1 in case of an
9341 * API error.
9342 */
9343static int
9344xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
9345 int options)
9346
9347{
9348 int i;
9349
9350 if (ctxt == NULL)
9351 return (-1);
9352 /*
9353 * WARNING: Change the start value if adding to the
9354 * xmlSchemaParseOption.
9355 */
9356 for (i = 1; i < (int) sizeof(int) * 8; i++) {
9357 if (options & 1<<i) {
9358 return (-1);
9359 }
9360 }
9361 ctxt->options = options;
9362 return (0);
9363}
9364
9365/**
9366 * xmlSchemaValidCtxtGetOptions:
9367 * @ctxt: a schema parser context
9368 *
9369 * Returns the option combination of the parser context.
9370 */
9371static int
9372xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
9373
9374{
9375 if (ctxt == NULL)
9376 return (-1);
9377 else
9378 return (ctxt->options);
9379}
9380
9381 void *curItems; /* used for dynamic addition of schemata */
9382 int nbCurItems; /* used for dynamic addition of schemata */
9383 int sizeCurItems; /* used for dynamic addition of schemata */
9384
9385#endif
9386
Daniel Veillard4255d502002-04-16 15:50:10 +00009387/**
9388 * xmlSchemaNewParserCtxt:
9389 * @URL: the location of the schema
9390 *
9391 * Create an XML Schemas parse context for that file/resource expected
9392 * to contain an XML Schemas file.
9393 *
9394 * Returns the parser context or NULL in case of error
9395 */
9396xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009397xmlSchemaNewParserCtxt(const char *URL)
9398{
Daniel Veillard4255d502002-04-16 15:50:10 +00009399 xmlSchemaParserCtxtPtr ret;
9400
9401 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009402 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009403
9404 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9405 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009406 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009407 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009408 return (NULL);
9409 }
9410 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009411 ret->dict = xmlDictCreate();
9412 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00009413 ret->includes = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00009414 return (ret);
9415}
9416
9417/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009418 * xmlSchemaNewParserCtxtUseDict:
9419 * @URL: the location of the schema
9420 * @dict: the dictionary to be used
9421 *
9422 * Create an XML Schemas parse context for that file/resource expected
9423 * to contain an XML Schemas file.
9424 *
9425 * Returns the parser context or NULL in case of error
9426 */
9427static xmlSchemaParserCtxtPtr
9428xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
9429{
9430 xmlSchemaParserCtxtPtr ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009431 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009432 if (URL == NULL)
9433 return (NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009434 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009435
9436 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9437 if (ret == NULL) {
9438 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
9439 NULL);
9440 return (NULL);
9441 }
9442 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
9443 ret->dict = dict;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009444 xmlDictReference(dict);
9445 if (URL != NULL)
9446 ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009447 ret->includes = 0;
9448 return (ret);
9449}
9450
9451
9452/**
Daniel Veillard6045c902002-10-09 21:13:59 +00009453 * xmlSchemaNewMemParserCtxt:
9454 * @buffer: a pointer to a char array containing the schemas
9455 * @size: the size of the array
9456 *
9457 * Create an XML Schemas parse context for that memory buffer expected
9458 * to contain an XML Schemas file.
9459 *
9460 * Returns the parser context or NULL in case of error
9461 */
9462xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009463xmlSchemaNewMemParserCtxt(const char *buffer, int size)
9464{
Daniel Veillard6045c902002-10-09 21:13:59 +00009465 xmlSchemaParserCtxtPtr ret;
9466
9467 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009468 return (NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00009469
9470 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9471 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009472 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009473 NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00009474 return (NULL);
9475 }
9476 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
9477 ret->buffer = buffer;
9478 ret->size = size;
William M. Brackcf9eadf2003-12-25 13:24:05 +00009479 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +00009480 return (ret);
9481}
9482
9483/**
Daniel Veillard9d751502003-10-29 13:21:47 +00009484 * xmlSchemaNewDocParserCtxt:
9485 * @doc: a preparsed document tree
9486 *
9487 * Create an XML Schemas parse context for that document.
9488 * NB. The document may be modified during the parsing process.
9489 *
9490 * Returns the parser context or NULL in case of error
9491 */
9492xmlSchemaParserCtxtPtr
9493xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
9494{
9495 xmlSchemaParserCtxtPtr ret;
9496
9497 if (doc == NULL)
9498 return (NULL);
9499
9500 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9501 if (ret == NULL) {
9502 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
9503 NULL);
9504 return (NULL);
9505 }
9506 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
9507 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +00009508 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +00009509 /* The application has responsibility for the document */
9510 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +00009511
9512 return (ret);
9513}
9514
9515/**
Daniel Veillard4255d502002-04-16 15:50:10 +00009516 * xmlSchemaFreeParserCtxt:
9517 * @ctxt: the schema parser context
9518 *
9519 * Free the resources associated to the schema parser context
9520 */
9521void
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009522xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
9523{
Daniel Veillard4255d502002-04-16 15:50:10 +00009524 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009525 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +00009526 if (ctxt->doc != NULL && !ctxt->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009527 xmlFreeDoc(ctxt->doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009528 if (ctxt->assemble != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009529 xmlFree((xmlSchemaTypePtr *) ctxt->assemble->items);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009530 xmlFree(ctxt->assemble);
9531 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009532 if (ctxt->vctxt != NULL) {
9533 xmlSchemaFreeValidCtxt(ctxt->vctxt);
9534 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009535 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00009536 xmlFree(ctxt);
9537}
9538
9539/************************************************************************
9540 * *
9541 * Building the content models *
9542 * *
9543 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009544
Daniel Veillard4255d502002-04-16 15:50:10 +00009545/**
9546 * xmlSchemaBuildAContentModel:
9547 * @type: the schema type definition
9548 * @ctxt: the schema parser context
9549 * @name: the element name whose content is being built
9550 *
9551 * Generate the automata sequence needed for that type
9552 */
9553static void
9554xmlSchemaBuildAContentModel(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009555 xmlSchemaParserCtxtPtr ctxt,
9556 const xmlChar * name)
9557{
Daniel Veillard4255d502002-04-16 15:50:10 +00009558 if (type == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009559 xmlGenericError(xmlGenericErrorContext,
9560 "Found unexpected type = NULL in %s content model\n",
9561 name);
9562 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00009563 }
9564 switch (type->type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009565 case XML_SCHEMA_TYPE_ANY: {
9566 xmlAutomataStatePtr start, end;
9567 xmlSchemaWildcardPtr wild;
9568 xmlSchemaWildcardNsPtr ns;
Daniel Veillard32370232002-10-16 14:08:14 +00009569
Daniel Veillardc0826a72004-08-10 14:17:33 +00009570 wild = type->attributeWildcard;
9571
9572 if (wild == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00009573 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009574 "Internal error: xmlSchemaBuildAContentModel, "
9575 "no wildcard on xsd:any.\n", NULL, NULL);
9576 return;
9577 }
9578
9579 start = ctxt->state;
9580 end = xmlAutomataNewState(ctxt->am);
9581
9582 if (type->maxOccurs == 1) {
9583 if (wild->any == 1) {
9584 /*
9585 * We need to add both transitions:
9586 *
9587 * 1. the {"*", "*"} for elements in a namespace.
9588 */
9589 ctxt->state =
9590 xmlAutomataNewTransition2(ctxt->am,
9591 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
9592 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9593 /*
9594 * 2. the {"*"} for elements in no namespace.
9595 */
9596 ctxt->state =
9597 xmlAutomataNewTransition2(ctxt->am,
9598 start, NULL, BAD_CAST "*", NULL, type);
9599 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9600
9601 } else if (wild->nsSet != NULL) {
9602 ns = wild->nsSet;
9603 do {
9604 ctxt->state = start;
9605 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9606 ctxt->state, NULL, BAD_CAST "*", ns->value, type);
9607 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9608 ns = ns->next;
9609 } while (ns != NULL);
9610
9611 } else if (wild->negNsSet != NULL) {
9612 xmlAutomataStatePtr deadEnd;
9613
9614 deadEnd = xmlAutomataNewState(ctxt->am);
9615 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9616 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, type);
9617 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9618 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
9619 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9620 }
9621 } else {
9622 int counter;
9623 xmlAutomataStatePtr hop;
9624 int maxOccurs =
9625 type->maxOccurs == UNBOUNDED ? UNBOUNDED : type->maxOccurs - 1;
9626 int minOccurs =
9627 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
9628
9629 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
9630 hop = xmlAutomataNewState(ctxt->am);
9631 if (wild->any == 1) {
9632 ctxt->state =
9633 xmlAutomataNewTransition2(ctxt->am,
9634 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
9635 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
9636 ctxt->state =
9637 xmlAutomataNewTransition2(ctxt->am,
9638 start, NULL, BAD_CAST "*", NULL, type);
9639 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
9640 } else if (wild->nsSet != NULL) {
9641 ns = wild->nsSet;
9642 do {
9643 ctxt->state =
9644 xmlAutomataNewTransition2(ctxt->am,
9645 start, NULL, BAD_CAST "*", ns->value, type);
9646 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
9647 ns = ns->next;
9648 } while (ns != NULL);
9649
9650 } else if (wild->negNsSet != NULL) {
9651 xmlAutomataStatePtr deadEnd;
9652
9653 deadEnd = xmlAutomataNewState(ctxt->am);
9654 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9655 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, type);
9656 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9657 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
9658 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
9659 }
9660 xmlAutomataNewCountedTrans(ctxt->am, hop, start, counter);
9661 xmlAutomataNewCounterTrans(ctxt->am, hop, end, counter);
9662 }
9663 if (type->minOccurs == 0) {
9664 xmlAutomataNewEpsilon(ctxt->am, start, end);
9665 }
9666 ctxt->state = end;
9667 break;
9668 }
9669 case XML_SCHEMA_TYPE_ELEMENT:{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009670 xmlAutomataStatePtr oldstate;
9671 xmlSchemaElementPtr particle, elemDecl;
Daniel Veillard32370232002-10-16 14:08:14 +00009672
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009673 /*
9674 * IMPORTANT: This puts element declarations
9675 * (and never element decl. references) into the
9676 * automaton. This is crucial and should not be changed,
9677 * since validating functions rely now on it.
9678 */
9679 particle = (xmlSchemaElementPtr) type;
9680 if (particle->ref != NULL) {
9681 if (particle->refDecl == NULL) {
9682 /*
9683 * Skip content model creation if the reference
9684 * did not resolve to a declaration.
9685 */
9686 break;
9687 } else {
9688 /*
9689 * Referenced global element declaration.
9690 */
9691 elemDecl = particle->refDecl;
9692 }
9693 } else {
9694 /*
9695 * Anonymous element declaration.
9696 */
9697 elemDecl = particle;
9698 }
9699
9700 oldstate = ctxt->state;
9701
9702 if (particle->maxOccurs >= UNBOUNDED) {
9703 if (particle->minOccurs > 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009704 xmlAutomataStatePtr tmp;
9705 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00009706
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009707 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009708 oldstate, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009709 oldstate = ctxt->state;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009710 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009711 particle->minOccurs - 1, UNBOUNDED);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00009712 ctxt->state =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009713 xmlAutomataNewTransition2(ctxt->am,
9714 ctxt->state, NULL,
9715 elemDecl->name,
9716 elemDecl->targetNamespace,
9717 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009718 tmp = ctxt->state;
9719 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009720 counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009721 ctxt->state =
9722 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009723 counter);
Daniel Veillard32370232002-10-16 14:08:14 +00009724
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009725 } else {
9726 ctxt->state =
9727 xmlAutomataNewTransition2(ctxt->am,
9728 ctxt->state, NULL,
9729 elemDecl->name,
9730 elemDecl->targetNamespace,
9731 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009732 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
9733 oldstate);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009734 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009735 /* basically an elem* */
9736 xmlAutomataNewEpsilon(ctxt->am, oldstate,
9737 ctxt->state);
9738 }
9739 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009740 } else if ((particle->maxOccurs > 1) || (particle->minOccurs > 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009741 xmlAutomataStatePtr tmp;
9742 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00009743
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009744 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
9745 oldstate, NULL);
9746 oldstate = ctxt->state;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009747 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009748 particle->minOccurs - 1,
9749 particle->maxOccurs - 1);
9750 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9751 ctxt->state,
9752 NULL,
9753 elemDecl->name,
9754 elemDecl->targetNamespace,
9755 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009756 tmp = ctxt->state;
9757 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009758 counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009759 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, tmp,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009760 NULL, counter);
9761 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009762 /* basically an elem? */
9763 xmlAutomataNewEpsilon(ctxt->am, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009764 ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009765 }
Daniel Veillardb39bc392002-10-26 19:29:51 +00009766
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009767 } else {
9768 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9769 ctxt->state,
9770 NULL,
9771 elemDecl->name,
9772 elemDecl->targetNamespace,
9773 (xmlSchemaTypePtr) elemDecl);
9774 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009775 /* basically an elem? */
9776 xmlAutomataNewEpsilon(ctxt->am, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009777 ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009778 }
9779 }
9780 break;
9781 }
9782 case XML_SCHEMA_TYPE_SEQUENCE:{
9783 xmlSchemaTypePtr subtypes;
Daniel Veillardb39bc392002-10-26 19:29:51 +00009784
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009785 /*
9786 * If max and min occurances are default (1) then
9787 * simply iterate over the subtypes
9788 */
9789 if ((type->minOccurs == 1) && (type->maxOccurs == 1)) {
9790 subtypes = type->subtypes;
9791 while (subtypes != NULL) {
9792 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
9793 subtypes = subtypes->next;
9794 }
9795 } else {
9796 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00009797
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009798 if (type->maxOccurs >= UNBOUNDED) {
9799 if (type->minOccurs > 1) {
9800 xmlAutomataStatePtr tmp;
9801 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00009802
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009803 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
9804 oldstate,
9805 NULL);
9806 oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00009807
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009808 counter = xmlAutomataNewCounter(ctxt->am,
9809 type->
9810 minOccurs - 1,
9811 UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +00009812
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009813 subtypes = type->subtypes;
9814 while (subtypes != NULL) {
9815 xmlSchemaBuildAContentModel(subtypes, ctxt,
9816 name);
9817 subtypes = subtypes->next;
9818 }
9819 tmp = ctxt->state;
9820 xmlAutomataNewCountedTrans(ctxt->am, tmp,
9821 oldstate, counter);
9822 ctxt->state =
9823 xmlAutomataNewCounterTrans(ctxt->am, tmp,
9824 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +00009825
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009826 } else {
9827 subtypes = type->subtypes;
9828 while (subtypes != NULL) {
9829 xmlSchemaBuildAContentModel(subtypes, ctxt,
9830 name);
9831 subtypes = subtypes->next;
9832 }
9833 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
9834 oldstate);
9835 if (type->minOccurs == 0) {
9836 xmlAutomataNewEpsilon(ctxt->am, oldstate,
9837 ctxt->state);
9838 }
9839 }
9840 } else if ((type->maxOccurs > 1)
9841 || (type->minOccurs > 1)) {
9842 xmlAutomataStatePtr tmp;
9843 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00009844
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009845 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
9846 oldstate,
9847 NULL);
9848 oldstate = ctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +00009849
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009850 counter = xmlAutomataNewCounter(ctxt->am,
9851 type->minOccurs -
9852 1,
9853 type->maxOccurs -
9854 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00009855
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009856 subtypes = type->subtypes;
9857 while (subtypes != NULL) {
9858 xmlSchemaBuildAContentModel(subtypes, ctxt,
9859 name);
9860 subtypes = subtypes->next;
9861 }
9862 tmp = ctxt->state;
9863 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
9864 counter);
9865 ctxt->state =
9866 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
9867 counter);
9868 if (type->minOccurs == 0) {
9869 xmlAutomataNewEpsilon(ctxt->am, oldstate,
9870 ctxt->state);
9871 }
Daniel Veillardb509f152002-04-17 16:28:10 +00009872
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009873 } else {
9874 subtypes = type->subtypes;
9875 while (subtypes != NULL) {
9876 xmlSchemaBuildAContentModel(subtypes, ctxt,
9877 name);
9878 subtypes = subtypes->next;
9879 }
9880 if (type->minOccurs == 0) {
9881 xmlAutomataNewEpsilon(ctxt->am, oldstate,
9882 ctxt->state);
9883 }
9884 }
9885 }
9886 break;
9887 }
9888 case XML_SCHEMA_TYPE_CHOICE:{
9889 xmlSchemaTypePtr subtypes;
9890 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +00009891
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009892 start = ctxt->state;
9893 end = xmlAutomataNewState(ctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +00009894
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009895 /*
9896 * iterate over the subtypes and remerge the end with an
9897 * epsilon transition
9898 */
9899 if (type->maxOccurs == 1) {
9900 subtypes = type->subtypes;
9901 while (subtypes != NULL) {
9902 ctxt->state = start;
9903 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
9904 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9905 subtypes = subtypes->next;
9906 }
9907 } else {
9908 int counter;
9909 xmlAutomataStatePtr hop;
9910 int maxOccurs = type->maxOccurs == UNBOUNDED ?
9911 UNBOUNDED : type->maxOccurs - 1;
9912 int minOccurs =
9913 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +00009914
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009915 /*
9916 * use a counter to keep track of the number of transtions
9917 * which went through the choice.
9918 */
9919 counter =
9920 xmlAutomataNewCounter(ctxt->am, minOccurs,
9921 maxOccurs);
9922 hop = xmlAutomataNewState(ctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +00009923
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009924 subtypes = type->subtypes;
9925 while (subtypes != NULL) {
9926 ctxt->state = start;
9927 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
9928 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
9929 subtypes = subtypes->next;
9930 }
9931 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
9932 counter);
9933 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
9934 counter);
9935 }
9936 if (type->minOccurs == 0) {
9937 xmlAutomataNewEpsilon(ctxt->am, start, end);
9938 }
9939 ctxt->state = end;
9940 break;
9941 }
9942 case XML_SCHEMA_TYPE_ALL:{
9943 xmlAutomataStatePtr start;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00009944 xmlSchemaElementPtr elemDecl, particle;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009945 int lax;
9946
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00009947 particle = (xmlSchemaElementPtr) type->subtypes;
9948 if (particle == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009949 break;
9950 start = ctxt->state;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00009951 while (particle != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009952 ctxt->state = start;
William M. Brack9989c7d2004-05-12 14:39:38 +00009953 /*
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00009954 * Changed to put the element declaration and
9955 * never the element decl. reference into the
9956 * automaton. This fixes bug 139897 and bug 167754.
William M. Brack9989c7d2004-05-12 14:39:38 +00009957 */
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00009958 if (particle->ref != NULL) {
9959 if (particle->refDecl == NULL) {
9960 /*
9961 * TODO: Note that we break on missing
9962 * sub-components.
9963 */
9964 break;
9965 } else
9966 elemDecl = particle->refDecl;
9967 } else
9968 elemDecl = particle;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009969 /*
9970 * NOTE: The {max occurs} of all the particles in the
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00009971 * {particles} of the group must be 0 or 1; this is
9972 * already ensured during the parse of the content of
9973 * <all>.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009974 */
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00009975 if ((particle->minOccurs == 1) &&
9976 (particle->maxOccurs == 1)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009977 xmlAutomataNewOnceTrans2(ctxt->am, ctxt->state,
9978 ctxt->state,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00009979 elemDecl->name,
9980 elemDecl->targetNamespace,
9981 1, 1, elemDecl);
9982 } else if ((particle->minOccurs == 0) &&
9983 (particle->maxOccurs == 1)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009984
9985 xmlAutomataNewCountTrans2(ctxt->am, ctxt->state,
9986 ctxt->state,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00009987 elemDecl->name,
9988 elemDecl->targetNamespace,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009989 0,
9990 1,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00009991 elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009992 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00009993 particle = (xmlSchemaElementPtr) particle->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009994 }
9995 lax = type->minOccurs == 0;
9996 ctxt->state =
9997 xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL,
9998 lax);
9999 break;
10000 }
10001 case XML_SCHEMA_TYPE_RESTRICTION:
10002 if (type->subtypes != NULL)
10003 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
10004 break;
10005 case XML_SCHEMA_TYPE_EXTENSION:
10006 if (type->baseType != NULL) {
10007 xmlSchemaTypePtr subtypes;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010008
10009 /*
10010 * TODO: Circular definitions will be checked at the
10011 * constraint level. So remove this when the complex type
10012 * constraints are implemented.
10013 */
Daniel Veillardf7627552004-04-22 07:15:40 +000010014 if (type->recurse) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010015 /* TODO: Change the error code. */
10016 xmlSchemaPCustomErr(ctxt,
10017 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
10018 NULL, type, type->node,
10019 "This item is circular", NULL);
Daniel Veillardf7627552004-04-22 07:15:40 +000010020 return;
10021 }
10022 type->recurse = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010023 xmlSchemaBuildAContentModel(type->baseType, ctxt, name);
Daniel Veillardf7627552004-04-22 07:15:40 +000010024 type->recurse = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010025 subtypes = type->subtypes;
10026 while (subtypes != NULL) {
10027 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
10028 subtypes = subtypes->next;
10029 }
10030 } else if (type->subtypes != NULL)
10031 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
10032 break;
10033 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000010034 /*
10035 * Handle model group definition references.
10036 * NOTE: type->subtypes is the referenced model grop definition;
10037 * and type->subtypes->subtypes is the model group (i.e. <all> or
10038 * <choice> or <sequence>).
10039 */
10040 if ((type->ref != NULL) && (type->subtypes != NULL) &&
10041 (type->subtypes->subtypes != NULL)) {
10042 xmlSchemaTypePtr modelGr;
10043 xmlAutomataStatePtr start, end;
10044
10045 modelGr = type->subtypes->subtypes;
10046 start = ctxt->state;
10047 end = xmlAutomataNewState(ctxt->am);
10048 if (type->maxOccurs == 1) {
10049 ctxt->state = start;
10050 xmlSchemaBuildAContentModel(modelGr, ctxt, name);
10051 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
10052 } else {
10053 int counter;
10054 xmlAutomataStatePtr hop;
10055 int maxOccurs = type->maxOccurs == UNBOUNDED ?
10056 UNBOUNDED : type->maxOccurs - 1;
10057 int minOccurs =
10058 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
10059
10060 counter =
10061 xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
10062 hop = xmlAutomataNewState(ctxt->am);
10063 ctxt->state = start;
10064 xmlSchemaBuildAContentModel(modelGr, ctxt, name);
10065 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
10066 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
10067 counter);
10068 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
10069 counter);
10070 }
10071 if (type->minOccurs == 0) {
10072 xmlAutomataNewEpsilon(ctxt->am, start, end);
10073 }
10074 ctxt->state = end;
10075 break;
10076 }
10077 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010078 case XML_SCHEMA_TYPE_COMPLEX:
10079 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
10080 if (type->subtypes != NULL)
10081 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
10082 break;
William M. Brack2f2a6632004-08-20 23:09:47 +000010083 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
10084 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010085 default:
10086 xmlGenericError(xmlGenericErrorContext,
10087 "Found unexpected type %d in %s content model\n",
10088 type->type, name);
10089 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000010090 }
10091}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010092
Daniel Veillard4255d502002-04-16 15:50:10 +000010093/**
10094 * xmlSchemaBuildContentModel:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010095 * @type: the type definition (or reference)
Daniel Veillard4255d502002-04-16 15:50:10 +000010096 * @ctxt: the schema parser context
Daniel Veillarda84c0b32003-06-02 16:58:46 +000010097 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +000010098 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010099 * Builds the content model of the complex type.
Daniel Veillard4255d502002-04-16 15:50:10 +000010100 */
10101static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010102xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010103 xmlSchemaParserCtxtPtr ctxt,
10104 const xmlChar * name)
10105{
Daniel Veillard4255d502002-04-16 15:50:10 +000010106 xmlAutomataStatePtr start;
10107
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010108 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) || (type->ref != NULL) ||
10109 (type->contentType == XML_SCHEMA_CONTENT_BASIC) ||
10110 (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
10111 (type->contModel != NULL))
10112 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +000010113
10114#ifdef DEBUG_CONTENT
10115 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010116 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000010117#endif
10118
Daniel Veillard4255d502002-04-16 15:50:10 +000010119 ctxt->am = xmlNewAutomata();
10120 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010121 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010122 "Cannot create automata for complex tpye %s\n", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010123 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000010124 }
10125 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010126 xmlSchemaBuildAContentModel(type, ctxt, name);
Daniel Veillard4255d502002-04-16 15:50:10 +000010127 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010128 type->contModel = xmlAutomataCompile(ctxt->am);
10129 if (type->contModel == NULL) {
10130 xmlSchemaPCustomErr(ctxt,
10131 XML_SCHEMAP_INTERNAL,
10132 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010133 "Failed to compile the content model", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010134 } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010135 xmlSchemaPCustomErr(ctxt,
10136 XML_SCHEMAP_NOT_DETERMINISTIC,
10137 /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010138 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010139 "The content model is not determinist", NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +000010140 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +000010141#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010142 xmlGenericError(xmlGenericErrorContext,
10143 "Content model of %s:\n", name);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010144 xmlRegexpPrint(stderr, type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +000010145#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +000010146 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +000010147 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000010148 xmlFreeAutomata(ctxt->am);
10149 ctxt->am = NULL;
10150}
10151
10152/**
10153 * xmlSchemaRefFixupCallback:
10154 * @elem: the schema element context
10155 * @ctxt: the schema parser context
10156 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000010157 * Resolves the references of an element declaration
10158 * or particle, which has an element declaration as it's
10159 * term.
Daniel Veillard4255d502002-04-16 15:50:10 +000010160 */
10161static void
10162xmlSchemaRefFixupCallback(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010163 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010164 const xmlChar * name ATTRIBUTE_UNUSED,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010165 const xmlChar * context ATTRIBUTE_UNUSED,
10166 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000010167{
Daniel Veillardc0826a72004-08-10 14:17:33 +000010168 if ((ctxt == NULL) || (elem == NULL) ||
10169 ((elem != NULL) && (elem->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010170 return;
Daniel Veillardc0826a72004-08-10 14:17:33 +000010171 elem->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
Daniel Veillard4255d502002-04-16 15:50:10 +000010172 if (elem->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010173 xmlSchemaElementPtr elemDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +000010174
Daniel Veillardc0826a72004-08-10 14:17:33 +000010175 /*
10176 * TODO: Evaluate, what errors could occur if the declaration is not
10177 * found. It might be possible that the "typefixup" might crash if
10178 * no ref declaration was found.
10179 */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010180 elemDecl = xmlSchemaGetElem(ctxt->schema, elem->ref, elem->refNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +000010181 if (elemDecl == NULL) {
10182 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010183 XML_SCHEMAP_SRC_RESOLVE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010184 NULL, (xmlSchemaTypePtr) elem, elem->node,
10185 "ref", elem->ref, elem->refNs,
10186 XML_SCHEMA_TYPE_ELEMENT, NULL);
10187 } else
10188 elem->refDecl = elemDecl;
10189 } else {
10190 if ((elem->subtypes == NULL) && (elem->namedType != NULL)) {
10191 xmlSchemaTypePtr type;
10192
10193 /* (type definition) ... otherwise the type definition ·resolved·
10194 * to by the ·actual value· of the type [attribute] ...
10195 */
10196 type = xmlSchemaGetType(ctxt->schema, elem->namedType,
10197 elem->namedTypeNs);
10198 if (type == NULL) {
10199 xmlSchemaPResCompAttrErr(ctxt,
10200 XML_SCHEMAP_SRC_RESOLVE,
10201 NULL, (xmlSchemaTypePtr) elem, elem->node,
10202 "type", elem->namedType, elem->namedTypeNs,
10203 XML_SCHEMA_TYPE_BASIC, "type definition");
10204 } else
10205 elem->subtypes = type;
10206 }
10207 if (elem->substGroup != NULL) {
10208 xmlSchemaElementPtr substHead;
10209
10210 /*
10211 * FIXME TODO: Do we need a new field in _xmlSchemaElement for
10212 * substitutionGroup?
10213 */
10214 substHead = xmlSchemaGetElem(ctxt->schema, elem->substGroup,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010215 elem->substGroupNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +000010216 if (substHead == NULL) {
10217 xmlSchemaPResCompAttrErr(ctxt,
10218 XML_SCHEMAP_SRC_RESOLVE,
10219 NULL, (xmlSchemaTypePtr) elem, NULL,
10220 "substitutionGroup", elem->substGroup, elem->substGroupNs,
10221 XML_SCHEMA_TYPE_ELEMENT, NULL);
10222 } else {
10223 xmlSchemaRefFixupCallback(substHead, ctxt, NULL, NULL, NULL);
10224 /*
10225 * (type definition)...otherwise the {type definition} of the
10226 * element declaration ·resolved· to by the ·actual value· of
10227 * the substitutionGroup [attribute], if present
10228 */
10229 if (elem->subtypes == NULL)
10230 elem->subtypes = substHead->subtypes;
10231 }
10232 }
10233 if ((elem->subtypes == NULL) && (elem->namedType == NULL) &&
10234 (elem->substGroup == NULL))
10235 elem->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
10236 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010237}
10238
William M. Bracke7091952004-05-11 15:09:58 +000010239/**
10240 * xmlSchemaParseListRefFixup:
10241 * @type: the schema type definition
10242 * @ctxt: the schema parser context
10243 *
10244 * Fixup of the itemType reference of the list type.
10245 */
Daniel Veillard377e1a92004-04-16 16:30:05 +000010246static void
William M. Bracke7091952004-05-11 15:09:58 +000010247xmlSchemaParseListRefFixup(xmlSchemaTypePtr type, xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010248{
Daniel Veillardc0826a72004-08-10 14:17:33 +000010249
Daniel Veillard01fa6152004-06-29 17:04:39 +000010250 if (((type->base == NULL) &&
10251 (type->subtypes == NULL)) ||
10252 ((type->base != NULL) &&
10253 (type->subtypes != NULL))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010254 /*
10255 * src-list-itemType-or-simpleType
10256 * Either the itemType [attribute] or the <simpleType> [child] of
10257 * the <list> element must be present, but not both.
Daniel Veillard01fa6152004-06-29 17:04:39 +000010258 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000010259 /*
10260 * TODO: Move this to the parse function.
10261 */
10262 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010263 XML_SCHEMAP_SRC_LIST_ITEMTYPE_OR_SIMPLETYPE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010264 NULL, type, type->node,
10265 "The attribute 'itemType' and the <simpleType> child "
10266 "are mutually exclusive", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010267 } else if (type->base!= NULL) {
10268 type->subtypes = xmlSchemaGetType(ctxt->schema, type->base, type->baseNs);
10269 if (type->subtypes == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010270 xmlSchemaPResCompAttrErr(ctxt,
10271 XML_SCHEMAP_SRC_RESOLVE,
10272 NULL, type, type->node,
10273 "itemType", type->base, type->baseNs,
10274 XML_SCHEMA_TYPE_SIMPLE, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010275 }
10276 }
10277 if ((type->subtypes != NULL) &&
10278 (type->subtypes->contentType == XML_SCHEMA_CONTENT_UNKNOWN))
10279 xmlSchemaTypeFixup(type->subtypes, ctxt, NULL);
William M. Bracke7091952004-05-11 15:09:58 +000010280}
10281
10282/**
10283 * xmlSchemaParseUnionRefCheck:
10284 * @typeDecl: the schema type definition
10285 * @ctxt: the schema parser context
10286 *
Daniel Veillard01fa6152004-06-29 17:04:39 +000010287 * Checks and builds the memberTypes of the union type.
10288 * Returns -1 in case of an internal error, 0 otherwise.
William M. Bracke7091952004-05-11 15:09:58 +000010289 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010290static int
William M. Bracke7091952004-05-11 15:09:58 +000010291xmlSchemaParseUnionRefCheck(xmlSchemaTypePtr type,
Daniel Veillard377e1a92004-04-16 16:30:05 +000010292 xmlSchemaParserCtxtPtr ctxt)
10293{
Daniel Veillardc0826a72004-08-10 14:17:33 +000010294
Daniel Veillard01fa6152004-06-29 17:04:39 +000010295 xmlSchemaTypeLinkPtr link, lastLink = NULL, prevLink, subLink, newLink;
10296 xmlSchemaTypePtr memberType, ctxtType;
Daniel Veillard377e1a92004-04-16 16:30:05 +000010297
Daniel Veillard01fa6152004-06-29 17:04:39 +000010298 /* 1 If the <union> alternative is chosen, then [Definition:]
10299 * define the explicit members as the type definitions ·resolved·
10300 * to by the items in the ·actual value· of the memberTypes [attribute],
10301 * if any, followed by the type definitions corresponding to the
10302 * <simpleType>s among the [children] of <union>, if any.
10303 */
Daniel Veillard377e1a92004-04-16 16:30:05 +000010304
Daniel Veillard01fa6152004-06-29 17:04:39 +000010305 if (type->type != XML_SCHEMA_TYPE_UNION)
10306 return (-1);
10307 if (ctxt->ctxtType == NULL) {
10308 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010309 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010310 "Internal error: xmlSchemaParseUnionRefCheck, no parent type "
10311 "available", NULL, NULL);
10312 return (-1);
10313 }
10314 /*
10315 * src-union-memberTypes-or-simpleTypes
10316 * Either the memberTypes [attribute] of the <union> element must
10317 * be non-empty or there must be at least one simpleType [child].
10318 */
10319 if ((type->base == NULL) &&
10320 (type->subtypes == NULL)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010321 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010322 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010323 NULL, NULL, type->node,
10324 "Either the attribute 'memberTypes' must be non-empty "
10325 "or there must be at least one <simpleType> child", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010326 }
10327
10328 ctxtType = ctxt->ctxtType;
10329 if (type->base != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010330 xmlAttrPtr attr;
10331 const xmlChar *cur, *end;
10332 xmlChar *tmp;
10333 const xmlChar *localName, *uri;
10334
10335 attr = xmlSchemaGetPropNode(type->node, "memberTypes");
Daniel Veillard01fa6152004-06-29 17:04:39 +000010336 cur = type->base;
10337 do {
10338 while (IS_BLANK_CH(*cur))
10339 cur++;
10340 end = cur;
10341 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
10342 end++;
10343 if (end == cur)
10344 break;
10345 tmp = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +000010346 xmlSchemaPValAttrNodeQNameValue(ctxt, ctxt->schema, NULL,
10347 NULL, attr, BAD_CAST tmp, &uri, NULL, &localName);
10348 memberType = xmlSchemaGetType(ctxt->schema, localName, uri);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010349 if (memberType == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010350 xmlSchemaPResCompAttrErr(ctxt,
10351 XML_SCHEMAP_UNKNOWN_MEMBER_TYPE,
10352 NULL, NULL, type->node, "memberTypes", localName, uri,
10353 XML_SCHEMA_TYPE_SIMPLE, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010354 } else {
10355 if (memberType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
10356 xmlSchemaTypeFixup(memberType, ctxt, NULL);
10357 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
10358 if (link == NULL) {
10359 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
10360 return (-1);
10361 }
10362 link->type = memberType;
10363 link->next = NULL;
10364 if (lastLink == NULL)
10365 ctxtType->memberTypes = link;
10366 else
10367 lastLink->next = link;
10368 lastLink = link;
10369 }
10370 xmlFree(tmp);
10371 cur = end;
10372 } while (*cur != 0);
10373 }
10374 /*
10375 * Add local simple types,
10376 */
10377 memberType = type->subtypes;
10378 while (memberType != NULL) {
10379 if (memberType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
10380 xmlSchemaTypeFixup(memberType, ctxt, NULL);
10381 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
10382 if (link == NULL) {
10383 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
10384 return (-1);
10385 }
10386 link->type = memberType;
10387 link->next = NULL;
10388 if (lastLink == NULL)
10389 ctxtType->memberTypes = link;
10390 else
10391 lastLink->next = link;
10392 lastLink = link;
10393 memberType = memberType->next;
10394 }
10395 /*
10396 * The actual value is then formed by replacing any union type
10397 * definition in the ·explicit members· with the members of their
10398 * {member type definitions}, in order.
10399 */
10400 link = ctxtType->memberTypes;
10401 while (link != NULL) {
10402 if (link->type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
10403 subLink = link->type->memberTypes;
10404 if (subLink != NULL) {
10405 link->type = subLink->type;
10406 if (subLink->next != NULL) {
10407 lastLink = link->next;
10408 subLink = subLink->next;
10409 prevLink = link;
10410 while (subLink != NULL) {
10411 newLink = (xmlSchemaTypeLinkPtr)
10412 xmlMalloc(sizeof(xmlSchemaTypeLink));
10413 if (newLink == NULL) {
10414 xmlSchemaPErrMemory(ctxt, "allocating a type link",
10415 NULL);
10416 return (-1);
10417 }
10418 newLink->type = memberType;
10419 prevLink->next = newLink;
10420 prevLink = newLink;
10421 newLink->next = lastLink;
10422
10423 subLink = subLink->next;
10424 }
10425 }
10426 }
10427 }
10428 link = link->next;
10429 }
10430
10431 return (0);
Daniel Veillard377e1a92004-04-16 16:30:05 +000010432}
10433
Daniel Veillard4255d502002-04-16 15:50:10 +000010434/**
Daniel Veillard3646d642004-06-02 19:19:14 +000010435 * xmlSchemaIsDerivedFromBuiltInType:
10436 * @ctxt: the schema parser context
10437 * @type: the type definition
10438 * @valType: the value type
10439 *
10440 *
10441 * Returns 1 if the type has the given value type, or
10442 * is derived from such a type.
10443 */
William M. Brack803812b2004-06-03 02:11:24 +000010444static int
Daniel Veillard3646d642004-06-02 19:19:14 +000010445xmlSchemaIsDerivedFromBuiltInType(xmlSchemaParserCtxtPtr ctxt,
10446 xmlSchemaTypePtr type, int valType)
10447{
10448 /* TODO: Check if this works in every case. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010449 if ((type->type == XML_SCHEMA_TYPE_BASIC) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000010450 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000010451 if (type->builtInType == valType)
Daniel Veillard3646d642004-06-02 19:19:14 +000010452 return(1);
10453 } else if (type->type == XML_SCHEMA_TYPE_ATTRIBUTE) {
10454 if (((xmlSchemaAttributePtr) type)->subtypes != NULL)
10455 return(xmlSchemaIsDerivedFromBuiltInType(ctxt,
10456 ((xmlSchemaAttributePtr) type)->subtypes, valType));
10457 } else if ((type->type == XML_SCHEMA_TYPE_RESTRICTION) ||
10458 (type->type == XML_SCHEMA_TYPE_EXTENSION)) {
10459 if (type->baseType != NULL)
10460 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->baseType,
10461 valType));
10462 } else if ((type->subtypes != NULL) &&
10463 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX) ||
10464 (type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
10465 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE) ||
10466 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
10467 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->subtypes,
10468 valType));
10469 }
10470
10471 return (0);
10472}
10473
10474/**
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000010475 * xmlSchemaGetPrimitiveType:
Daniel Veillard01fa6152004-06-29 17:04:39 +000010476 * @type: the simpleType definition
10477 *
10478 * Returns the primitive type of the given type or
10479 * NULL in case of error.
10480 */
10481static xmlSchemaTypePtr
10482xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
10483{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000010484
Daniel Veillard01fa6152004-06-29 17:04:39 +000010485 while (type != NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000010486 /*
10487 * Note that anySimpleType is actually not a primitive type
10488 * but we need that here.
10489 */
10490 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
10491 (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
Daniel Veillard01fa6152004-06-29 17:04:39 +000010492 return (type);
10493 type = type->baseType;
10494 }
10495
10496 return (NULL);
10497}
10498
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000010499#if 0
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000010500/**
10501 * xmlSchemaGetBuiltInTypeAncestor:
10502 * @type: the simpleType definition
10503 *
10504 * Returns the primitive type of the given type or
10505 * NULL in case of error.
10506 */
10507static xmlSchemaTypePtr
10508xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
10509{
10510 while (type != NULL) {
10511 if (type->type == XML_SCHEMA_TYPE_BASIC)
10512 return (type);
10513 type = type->baseType;
10514 }
10515
10516 return (NULL);
10517}
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000010518#endif
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000010519
Daniel Veillard01fa6152004-06-29 17:04:39 +000010520
10521/**
Daniel Veillard3646d642004-06-02 19:19:14 +000010522 * xmlSchemaBuildAttributeUsesOwned:
10523 * @ctxt: the schema parser context
10524 * @type: the complex type definition
10525 * @cur: the attribute declaration list
10526 * @lastUse: the top of the attribute use list
10527 *
10528 * Builds the attribute uses list on the given complex type.
10529 * This one is supposed to be called by
10530 * xmlSchemaBuildAttributeValidation only.
10531 */
10532static int
10533xmlSchemaBuildAttributeUsesOwned(xmlSchemaParserCtxtPtr ctxt,
10534 xmlSchemaAttributePtr cur,
10535 xmlSchemaAttributeLinkPtr *uses,
10536 xmlSchemaAttributeLinkPtr *lastUse)
10537{
10538 xmlSchemaAttributeLinkPtr tmp;
10539 while (cur != NULL) {
10540 if (cur->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
10541 /*
10542 * W3C: "2 The {attribute uses} of the attribute groups ·resolved·
10543 * to by the ·actual value·s of the ref [attribute] of the
10544 * <attributeGroup> [children], if any."
10545 */
10546 if (xmlSchemaBuildAttributeUsesOwned(ctxt,
10547 ((xmlSchemaAttributeGroupPtr) cur)->attributes, uses,
10548 lastUse) == -1) {
10549 return (-1);
10550 }
10551 } else {
10552 /* W3C: "1 The set of attribute uses corresponding to the
10553 * <attribute> [children], if any."
10554 */
10555 tmp = (xmlSchemaAttributeLinkPtr)
10556 xmlMalloc(sizeof(xmlSchemaAttributeLink));
10557 if (tmp == NULL) {
10558 xmlSchemaPErrMemory(ctxt, "building attribute uses", NULL);
10559 return (-1);
10560 }
10561 tmp->attr = cur;
10562 tmp->next = NULL;
10563 if (*uses == NULL)
10564 *uses = tmp;
10565 else
10566 (*lastUse)->next = tmp;
10567 *lastUse = tmp;
10568 }
10569 cur = cur->next;
10570 }
10571 return (0);
10572}
10573
Daniel Veillard50355f02004-06-08 17:52:16 +000010574/**
10575 * xmlSchemaCloneWildcardNsConstraints:
10576 * @ctxt: the schema parser context
10577 * @dest: the destination wildcard
10578 * @source: the source wildcard
10579 *
10580 * Clones the namespace constraints of source
10581 * and assignes them to dest.
10582 * Returns -1 on internal error, 0 otherwise.
10583 */
Daniel Veillard3646d642004-06-02 19:19:14 +000010584static int
10585xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
10586 xmlSchemaWildcardPtr *dest,
10587 xmlSchemaWildcardPtr source)
10588{
10589 xmlSchemaWildcardNsPtr cur, tmp, last;
10590
10591 if ((source == NULL) || (*dest == NULL))
10592 return(-1);
10593 (*dest)->any = source->any;
10594 cur = source->nsSet;
10595 last = NULL;
10596 while (cur != NULL) {
10597 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
10598 if (tmp == NULL)
10599 return(-1);
10600 tmp->value = cur->value;
10601 if (last == NULL)
10602 (*dest)->nsSet = tmp;
10603 else
10604 last->next = tmp;
10605 last = tmp;
10606 cur = cur->next;
10607 }
10608 if ((*dest)->negNsSet != NULL)
10609 xmlSchemaFreeWildcardNsSet((*dest)->negNsSet);
10610 if (source->negNsSet != NULL) {
10611 (*dest)->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
10612 if ((*dest)->negNsSet == NULL)
10613 return(-1);
10614 (*dest)->negNsSet->value = source->negNsSet->value;
10615 } else
10616 (*dest)->negNsSet = NULL;
10617 return(0);
10618}
10619
Daniel Veillard50355f02004-06-08 17:52:16 +000010620/**
10621 * xmlSchemaUnionWildcards:
10622 * @ctxt: the schema parser context
10623 * @completeWild: the first wildcard
10624 * @curWild: the second wildcard
10625 *
10626 * Unions the namespace constraints of the given wildcards.
10627 * @completeWild will hold the resulting union.
10628 * Returns a positive error code on failure, -1 in case of an
10629 * internal error, 0 otherwise.
10630 */
Daniel Veillard3646d642004-06-02 19:19:14 +000010631static int
10632xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
10633 xmlSchemaWildcardPtr completeWild,
10634 xmlSchemaWildcardPtr curWild)
10635{
10636 xmlSchemaWildcardNsPtr cur, curB, tmp;
10637
10638 /*
10639 * 1 If O1 and O2 are the same value, then that value must be the
10640 * value.
10641 */
10642 if ((completeWild->any == curWild->any) &&
10643 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
10644 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
10645
10646 if ((completeWild->negNsSet == NULL) ||
10647 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
10648
10649 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000010650 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000010651
10652 /*
10653 * Check equality of sets.
10654 */
10655 cur = completeWild->nsSet;
10656 while (cur != NULL) {
10657 found = 0;
10658 curB = curWild->nsSet;
10659 while (curB != NULL) {
10660 if (cur->value == curB->value) {
10661 found = 1;
10662 break;
10663 }
10664 curB = curB->next;
10665 }
10666 if (!found)
10667 break;
10668 cur = cur->next;
10669 }
10670 if (found)
10671 return(0);
10672 } else
10673 return(0);
10674 }
10675 }
10676 /*
10677 * 2 If either O1 or O2 is any, then any must be the value
10678 */
Daniel Veillard50355f02004-06-08 17:52:16 +000010679 if (completeWild->any != curWild->any) {
Daniel Veillard3646d642004-06-02 19:19:14 +000010680 if (completeWild->any == 0) {
10681 completeWild->any = 1;
10682 if (completeWild->nsSet != NULL) {
10683 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
10684 completeWild->nsSet = NULL;
10685 }
10686 if (completeWild->negNsSet != NULL) {
10687 xmlFree(completeWild->negNsSet);
10688 completeWild->negNsSet = NULL;
10689 }
10690 }
Daniel Veillard50355f02004-06-08 17:52:16 +000010691 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000010692 }
10693 /*
10694 * 3 If both O1 and O2 are sets of (namespace names or ·absent·),
10695 * then the union of those sets must be the value.
10696 */
10697 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
10698 int found;
10699 xmlSchemaWildcardNsPtr start;
10700
10701 cur = curWild->nsSet;
10702 start = completeWild->nsSet;
10703 while (cur != NULL) {
10704 found = 0;
10705 curB = start;
10706 while (curB != NULL) {
10707 if (cur->value == curB->value) {
10708 found = 1;
10709 break;
10710 }
10711 curB = curB->next;
10712 }
10713 if (!found) {
10714 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
10715 if (tmp == NULL)
10716 return (-1);
10717 tmp->value = cur->value;
10718 tmp->next = completeWild->nsSet;
10719 completeWild->nsSet = tmp;
10720 }
10721 cur = cur->next;
10722 }
10723
10724 return(0);
10725 }
10726 /*
10727 * 4 If the two are negations of different values (namespace names
10728 * or ·absent·), then a pair of not and ·absent· must be the value.
10729 */
10730 if ((completeWild->negNsSet != NULL) &&
10731 (curWild->negNsSet != NULL) &&
10732 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
10733 completeWild->negNsSet->value = NULL;
Daniel Veillard50355f02004-06-08 17:52:16 +000010734
10735 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +000010736 }
10737 /*
10738 * 5.
10739 */
10740 if (((completeWild->negNsSet != NULL) &&
10741 (completeWild->negNsSet->value != NULL) &&
10742 (curWild->nsSet != NULL)) ||
10743 ((curWild->negNsSet != NULL) &&
10744 (curWild->negNsSet->value != NULL) &&
10745 (completeWild->nsSet != NULL))) {
10746
10747 int nsFound, absentFound = 0;
10748
10749 if (completeWild->nsSet != NULL) {
10750 cur = completeWild->nsSet;
10751 curB = curWild->negNsSet;
10752 } else {
10753 cur = curWild->nsSet;
10754 curB = completeWild->negNsSet;
10755 }
10756 nsFound = 0;
10757 while (cur != NULL) {
10758 if (cur->value == NULL)
10759 absentFound = 1;
10760 else if (cur->value == curB->value)
10761 nsFound = 1;
10762 if (nsFound && absentFound)
10763 break;
10764 cur = cur->next;
10765 }
10766
10767 if (nsFound && absentFound) {
10768 /*
10769 * 5.1 If the set S includes both the negated namespace
10770 * name and ·absent·, then any must be the value.
10771 */
10772 completeWild->any = 1;
10773 if (completeWild->nsSet != NULL) {
10774 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
10775 completeWild->nsSet = NULL;
10776 }
10777 if (completeWild->negNsSet != NULL) {
10778 xmlFree(completeWild->negNsSet);
10779 completeWild->negNsSet = NULL;
10780 }
10781 } else if (nsFound && (!absentFound)) {
10782 /*
10783 * 5.2 If the set S includes the negated namespace name
10784 * but not ·absent·, then a pair of not and ·absent· must
10785 * be the value.
10786 */
10787 if (completeWild->nsSet != NULL) {
10788 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
10789 completeWild->nsSet = NULL;
10790 }
10791 if (completeWild->negNsSet == NULL) {
10792 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
10793 if (completeWild->negNsSet == NULL)
10794 return (-1);
10795 }
10796 completeWild->negNsSet->value = NULL;
10797 } else if ((!nsFound) && absentFound) {
10798 /*
10799 * 5.3 If the set S includes ·absent· but not the negated
10800 * namespace name, then the union is not expressible.
10801 */
10802 xmlSchemaPErr(ctxt, completeWild->node,
10803 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010804 "The union of the wilcard is not expressible.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +000010805 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000010806 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +000010807 } else if ((!nsFound) && (!absentFound)) {
10808 /*
10809 * 5.4 If the set S does not include either the negated namespace
10810 * name or ·absent·, then whichever of O1 or O2 is a pair of not
10811 * and a namespace name must be the value.
10812 */
10813 if (completeWild->negNsSet == NULL) {
10814 if (completeWild->nsSet != NULL) {
10815 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
10816 completeWild->nsSet = NULL;
10817 }
10818 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
10819 if (completeWild->negNsSet == NULL)
10820 return (-1);
10821 completeWild->negNsSet->value = curWild->negNsSet->value;
10822 }
10823 }
10824 return (0);
10825 }
10826 /*
10827 * 6.
10828 */
10829 if (((completeWild->negNsSet != NULL) &&
10830 (completeWild->negNsSet->value == NULL) &&
10831 (curWild->nsSet != NULL)) ||
10832 ((curWild->negNsSet != NULL) &&
10833 (curWild->negNsSet->value == NULL) &&
10834 (completeWild->nsSet != NULL))) {
10835
10836 if (completeWild->nsSet != NULL) {
10837 cur = completeWild->nsSet;
10838 } else {
10839 cur = curWild->nsSet;
10840 }
10841 while (cur != NULL) {
10842 if (cur->value == NULL) {
10843 /*
10844 * 6.1 If the set S includes ·absent·, then any must be the
10845 * value.
10846 */
10847 completeWild->any = 1;
10848 if (completeWild->nsSet != NULL) {
10849 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
10850 completeWild->nsSet = NULL;
10851 }
10852 if (completeWild->negNsSet != NULL) {
10853 xmlFree(completeWild->negNsSet);
10854 completeWild->negNsSet = NULL;
10855 }
10856 return (0);
10857 }
10858 cur = cur->next;
10859 }
10860 if (completeWild->negNsSet == NULL) {
10861 /*
10862 * 6.2 If the set S does not include ·absent·, then a pair of not
10863 * and ·absent· must be the value.
10864 */
10865 if (completeWild->nsSet != NULL) {
10866 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
10867 completeWild->nsSet = NULL;
10868 }
10869 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
10870 if (completeWild->negNsSet == NULL)
10871 return (-1);
10872 completeWild->negNsSet->value = NULL;
10873 }
10874 return (0);
10875 }
10876 return (0);
10877
10878}
10879
Daniel Veillard50355f02004-06-08 17:52:16 +000010880/**
10881 * xmlSchemaIntersectWildcards:
10882 * @ctxt: the schema parser context
10883 * @completeWild: the first wildcard
10884 * @curWild: the second wildcard
10885 *
10886 * Intersects the namespace constraints of the given wildcards.
10887 * @completeWild will hold the resulting intersection.
10888 * Returns a positive error code on failure, -1 in case of an
10889 * internal error, 0 otherwise.
10890 */
Daniel Veillard3646d642004-06-02 19:19:14 +000010891static int
10892xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
10893 xmlSchemaWildcardPtr completeWild,
10894 xmlSchemaWildcardPtr curWild)
10895{
William M. Brack803812b2004-06-03 02:11:24 +000010896 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000010897
10898 /*
10899 * 1 If O1 and O2 are the same value, then that value must be the
10900 * value.
10901 */
10902 if ((completeWild->any == curWild->any) &&
10903 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
10904 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
10905
10906 if ((completeWild->negNsSet == NULL) ||
10907 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
10908
10909 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000010910 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000010911
10912 /*
10913 * Check equality of sets.
10914 */
10915 cur = completeWild->nsSet;
10916 while (cur != NULL) {
10917 found = 0;
10918 curB = curWild->nsSet;
10919 while (curB != NULL) {
10920 if (cur->value == curB->value) {
10921 found = 1;
10922 break;
10923 }
10924 curB = curB->next;
10925 }
10926 if (!found)
10927 break;
10928 cur = cur->next;
10929 }
10930 if (found)
10931 return(0);
10932 } else
10933 return(0);
10934 }
10935 }
10936 /*
10937 * 2 If either O1 or O2 is any, then the other must be the value.
10938 */
10939 if ((completeWild->any != curWild->any) && (completeWild->any)) {
10940 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
10941 return(-1);
10942 return(0);
10943 }
10944 /*
10945 * 3 If either O1 or O2 is a pair of not and a value (a namespace
10946 * name or ·absent·) and the other is a set of (namespace names or
10947 * ·absent·), then that set, minus the negated value if it was in
10948 * the set, minus ·absent· if it was in the set, must be the value.
10949 */
10950 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
10951 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
10952 const xmlChar *neg;
10953
10954 if (completeWild->nsSet == NULL) {
10955 neg = completeWild->negNsSet->value;
10956 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
10957 return(-1);
10958 } else
10959 neg = curWild->negNsSet->value;
10960 /*
10961 * Remove absent and negated.
10962 */
10963 prev = NULL;
10964 cur = completeWild->nsSet;
10965 while (cur != NULL) {
10966 if (cur->value == NULL) {
10967 if (prev == NULL)
10968 completeWild->nsSet = cur->next;
10969 else
10970 prev->next = cur->next;
10971 xmlFree(cur);
10972 break;
10973 }
10974 prev = cur;
10975 cur = cur->next;
10976 }
10977 if (neg != NULL) {
10978 prev = NULL;
10979 cur = completeWild->nsSet;
10980 while (cur != NULL) {
10981 if (cur->value == neg) {
10982 if (prev == NULL)
10983 completeWild->nsSet = cur->next;
10984 else
10985 prev->next = cur->next;
10986 xmlFree(cur);
10987 break;
10988 }
10989 prev = cur;
10990 cur = cur->next;
10991 }
10992 }
10993
10994 return(0);
10995 }
10996 /*
10997 * 4 If both O1 and O2 are sets of (namespace names or ·absent·),
10998 * then the intersection of those sets must be the value.
10999 */
11000 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
11001 int found;
11002
11003 cur = completeWild->nsSet;
11004 prev = NULL;
11005 while (cur != NULL) {
11006 found = 0;
11007 curB = curWild->nsSet;
11008 while (curB != NULL) {
11009 if (cur->value == curB->value) {
11010 found = 1;
11011 break;
11012 }
11013 curB = curB->next;
11014 }
11015 if (!found) {
11016 if (prev == NULL)
11017 completeWild->nsSet = cur->next;
11018 else
11019 prev->next = cur->next;
11020 tmp = cur->next;
11021 xmlFree(cur);
11022 cur = tmp;
11023 continue;
11024 }
11025 prev = cur;
11026 cur = cur->next;
11027 }
11028
11029 return(0);
11030 }
11031 /* 5 If the two are negations of different namespace names,
11032 * then the intersection is not expressible
11033 */
11034 if ((completeWild->negNsSet != NULL) &&
11035 (curWild->negNsSet != NULL) &&
11036 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
11037 (completeWild->negNsSet->value != NULL) &&
11038 (curWild->negNsSet->value != NULL)) {
11039
11040 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011041 "The intersection of the wilcard is not expressible.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +000011042 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000011043 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +000011044 }
11045 /*
11046 * 6 If the one is a negation of a namespace name and the other
11047 * is a negation of ·absent·, then the one which is the negation
11048 * of a namespace name must be the value.
11049 */
11050 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
11051 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
11052 (completeWild->negNsSet->value == NULL)) {
11053 completeWild->negNsSet->value = curWild->negNsSet->value;
11054 }
11055 return(0);
11056}
11057
Daniel Veillard50355f02004-06-08 17:52:16 +000011058/**
11059 * xmlSchemaIsWildcardNsConstraintSubset:
11060 * @ctxt: the schema parser context
11061 * @wildA: the first wildcard
11062 * @wildB: the second wildcard
11063 *
11064 * Returns 1 if the namespace constraint of @wildA is an intensional
11065 * subset of @wildB, 0 otherwise.
11066 */
11067static int
Daniel Veillardc0826a72004-08-10 14:17:33 +000011068xmlSchemaIsWildcardNsConstraintSubset(xmlSchemaWildcardPtr wildA,
11069 xmlSchemaWildcardPtr wildB)
Daniel Veillard50355f02004-06-08 17:52:16 +000011070{
Daniel Veillard3646d642004-06-02 19:19:14 +000011071
Daniel Veillard50355f02004-06-08 17:52:16 +000011072 /*
11073 * Schema Component Constraint: Wildcard Subset
11074 */
11075 /*
11076 * 1 super must be any.
11077 */
11078 if (wildB->any)
11079 return (1);
11080 /*
11081 * 2.1 sub must be a pair of not and a namespace name or ·absent·.
11082 * 2.2 super must be a pair of not and the same value.
11083 */
11084 if ((wildA->negNsSet != NULL) &&
11085 (wildB->negNsSet != NULL) &&
11086 (wildA->negNsSet->value == wildA->negNsSet->value))
11087 return (1);
11088 /*
11089 * 3.1 sub must be a set whose members are either namespace names or ·absent·.
11090 */
11091 if (wildA->nsSet != NULL) {
11092 /*
11093 * 3.2.1 super must be the same set or a superset thereof.
11094 */
11095 if (wildB->nsSet != NULL) {
11096 xmlSchemaWildcardNsPtr cur, curB;
11097 int found = 0;
11098
11099 cur = wildA->nsSet;
11100 while (cur != NULL) {
11101 found = 0;
11102 curB = wildB->nsSet;
11103 while (curB != NULL) {
11104 if (cur->value == curB->value) {
11105 found = 1;
11106 break;
11107 }
11108 curB = curB->next;
11109 }
11110 if (!found)
11111 return (0);
11112 cur = cur->next;
11113 }
11114 if (found)
11115 return (1);
11116 } else if (wildB->negNsSet != NULL) {
11117 xmlSchemaWildcardNsPtr cur;
11118 /*
11119 * 3.2.2 super must be a pair of not and a namespace name or
11120 * ·absent· and that value must not be in sub's set.
11121 */
11122 cur = wildA->nsSet;
11123 while (cur != NULL) {
11124 if (cur->value == wildB->negNsSet->value)
11125 return (0);
11126 cur = cur->next;
11127 }
11128 return (1);
11129 }
11130 }
11131 return (0);
11132}
11133
11134/**
11135 * xmlSchemaBuildCompleteAttributeWildcard:
11136 * @ctxt: the schema parser context
11137 * @attrs: the attribute list
11138 * @completeWild: the resulting complete wildcard
11139 *
11140 * Returns -1 in case of an internal error, 0 otherwise.
11141 */
11142static int
11143xmlSchemaBuildCompleteAttributeWildcard(xmlSchemaParserCtxtPtr ctxt,
11144 xmlSchemaAttributePtr attrs,
11145 xmlSchemaWildcardPtr *completeWild)
Daniel Veillard3646d642004-06-02 19:19:14 +000011146{
11147 while (attrs != NULL) {
11148 if (attrs->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
11149 xmlSchemaAttributeGroupPtr group;
11150
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011151 group = (xmlSchemaAttributeGroupPtr) attrs;
11152 /*
11153 * Handle attribute group references.
11154 */
11155 if (group->ref != NULL) {
11156 if (group->refItem == NULL) {
11157 /*
11158 * TODO: Should we raise a warning here?
11159 */
11160 /*
11161 * The referenced attribute group definition could not
11162 * be resolved beforehand, so skip.
11163 */
11164 attrs = attrs->next;
11165 continue;
11166 } else
11167 group = group->refItem;
11168 }
11169 /*
11170 * For every attribute group definition, an intersected wildcard
11171 * will be created (assumed that a wildcard exists on the
11172 * particular attr. gr. def. or on any contained attr. gr. def
11173 * at all).
11174 * The flag XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED ensures
11175 * that the intersection will be performed only once.
11176 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011177 if ((group->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
11178 if (group->attributes != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000011179 if (xmlSchemaBuildCompleteAttributeWildcard(ctxt,
11180 group->attributes, &group->attributeWildcard) == -1)
11181 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000011182 }
11183 group->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
11184 }
11185 if (group->attributeWildcard != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000011186 if (*completeWild == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011187 /*
11188 * Copy the first encountered wildcard as context, except for the annotation.
11189 */
Daniel Veillard50355f02004-06-08 17:52:16 +000011190 *completeWild = xmlSchemaAddWildcard(ctxt);
11191 (*completeWild)->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
11192 if (xmlSchemaCloneWildcardNsConstraints(ctxt,
11193 completeWild, group->attributeWildcard) == -1)
11194 return (-1);
11195 (*completeWild)->processContents = group->attributeWildcard->processContents;
Daniel Veillard3646d642004-06-02 19:19:14 +000011196 /*
11197 * Although the complete wildcard might not correspond to any
11198 * node in the schema, we will save this context node.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011199 * TODO: Hmm, is this sane?
Daniel Veillard3646d642004-06-02 19:19:14 +000011200 */
Daniel Veillard50355f02004-06-08 17:52:16 +000011201 (*completeWild)->node = group->attributeWildcard->node;
11202
11203 } else if (xmlSchemaIntersectWildcards(ctxt, *completeWild, group->attributeWildcard) == -1) {
11204 xmlSchemaFreeWildcard(*completeWild);
11205 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000011206 }
11207 }
11208 }
11209 attrs = attrs->next;
11210 }
11211
Daniel Veillard50355f02004-06-08 17:52:16 +000011212 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000011213}
11214
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011215static int
11216xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributePtr item,
11217 int *fixed,
11218 const xmlChar **value,
11219 xmlSchemaValPtr *val)
11220{
11221 *fixed = 0;
11222 *value = NULL;
11223 if (val != 0)
11224 *val = NULL;
11225
11226 if (item->defValue == NULL)
11227 item = item->refDecl;
11228
11229 if (item == NULL)
11230 return (0);
11231
11232 if (item->defValue != NULL) {
11233 *value = item->defValue;
11234 if (val != 0)
11235 *val = item->defVal;
11236 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
11237 *fixed = 1;
11238 return (1);
11239 }
11240 return (0);
11241}
Daniel Veillard3646d642004-06-02 19:19:14 +000011242/**
11243 * xmlSchemaMatchesWildcardNs:
11244 * @wild: the wildcard
11245 * @ns: the namespace
11246 *
11247 *
11248 * Returns 1 if the given namespace matches the wildcard,
11249 * 0 otherwise.
11250 */
11251static int
11252xmlSchemaMatchesWildcardNs(xmlSchemaWildcardPtr wild, const xmlChar* ns)
11253{
11254 if (wild == NULL)
11255 return(0);
11256
11257 if (wild->any)
11258 return(1);
11259 else if (wild->nsSet != NULL) {
11260 xmlSchemaWildcardNsPtr cur;
11261
11262 cur = wild->nsSet;
11263 while (cur != NULL) {
11264 if (xmlStrEqual(cur->value, ns))
11265 return(1);
11266 cur = cur->next;
11267 }
11268 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
11269 (!xmlStrEqual(wild->negNsSet->value, ns)))
11270 return(1);
11271
11272 return(0);
11273}
11274
11275/**
11276 * xmlSchemaBuildAttributeValidation:
11277 * @ctxt: the schema parser context
11278 * @type: the complex type definition
11279 *
11280 *
11281 * Builds the wildcard and the attribute uses on the given complex type.
11282 * Returns -1 if an internal error occurs, 0 otherwise.
11283 */
11284static int
11285xmlSchemaBuildAttributeValidation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaTypePtr type)
11286{
11287 xmlSchemaTypePtr baseType = NULL;
11288 xmlSchemaAttributeLinkPtr cur, base, tmp, id = NULL, prev = NULL, uses = NULL,
William M. Brack803812b2004-06-03 02:11:24 +000011289 lastUse = NULL, lastBaseUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000011290 xmlSchemaAttributePtr attrs;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011291 xmlSchemaTypePtr anyType;
Daniel Veillard50355f02004-06-08 17:52:16 +000011292 int baseIsAnyType = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011293 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000011294 int err = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000011295
Daniel Veillard01fa6152004-06-29 17:04:39 +000011296 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Daniel Veillard3646d642004-06-02 19:19:14 +000011297 /*
11298 * Complex Type Definition with complex content Schema Component.
11299 *
11300 * Attribute uses.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011301 * TODO: Add checks for absent referenced attribute declarations and
11302 * simple types.
Daniel Veillard3646d642004-06-02 19:19:14 +000011303 */
11304 if (type->attributeUses != NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011305 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011306 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillard3646d642004-06-02 19:19:14 +000011307 "attribute uses already builded.\n",
11308 NULL, NULL);
11309 return (-1);
11310 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011311 if (type->baseType == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011312 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011313 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011314 "complex type '%s' has no base type.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011315 type->name, NULL);
11316 return (-1);
11317 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011318 baseType = type->baseType;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011319 if (baseType == anyType)
11320 baseIsAnyType = 1;
11321 /*
11322 * Inherit the attribute uses of the base type.
11323 */
11324 /*
11325 * NOTE: It is allowed to "extend" the anyType complex type.
11326 */
11327 if (!baseIsAnyType) {
11328 if (baseType != NULL) {
11329 for (cur = baseType->attributeUses; cur != NULL; cur = cur->next) {
11330 tmp = (xmlSchemaAttributeLinkPtr)
11331 xmlMalloc(sizeof(xmlSchemaAttributeLink));
11332 if (tmp == NULL) {
11333 xmlSchemaPErrMemory(ctxt,
11334 "building attribute uses of complexType", NULL);
11335 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000011336 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011337 tmp->attr = cur->attr;
11338 tmp->next = NULL;
11339 if (type->attributeUses == NULL) {
11340 type->attributeUses = tmp;
11341 } else
11342 lastBaseUse->next = tmp;
11343 lastBaseUse = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000011344 }
11345 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011346 }
11347 if ((type->subtypes != NULL) &&
11348 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
11349 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011350 /*
11351 * type --> (<simpleContent>|<complexContent>)
11352 * --> (<restriction>|<extension>) --> attributes
11353 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011354 attrs = type->subtypes->subtypes->attributes;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011355 } else {
11356 /* Short hand form of the complexType. */
11357 attrs = type->attributes;
11358 }
11359 /*
11360 * Handle attribute wildcards.
11361 */
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000011362 err = xmlSchemaBuildCompleteAttributeWildcard(ctxt,
11363 attrs, &type->attributeWildcard);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011364 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011365 * NOTE: During the parse time, the wildcard is created on the complexType
11366 * directly, if encountered in a <restriction> or <extension> element.
Daniel Veillard01fa6152004-06-29 17:04:39 +000011367 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011368 if (err == -1) {
11369 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
11370 "Internal error: xmlSchemaBuildAttributeValidation: "
11371 "failed to build an intersected attribute wildcard.\n",
11372 NULL, NULL);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000011373 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011374 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011375
11376 if ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
11377 ((baseIsAnyType) ||
11378 ((baseType != NULL) &&
11379 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
11380 (baseType->attributeWildcard != NULL)))) {
11381 if (type->attributeWildcard != NULL) {
11382 /*
11383 * Union the complete wildcard with the base wildcard.
11384 */
11385 if (xmlSchemaUnionWildcards(ctxt, type->attributeWildcard,
11386 baseType->attributeWildcard) == -1)
11387 return (-1);
11388 } else {
11389 /*
11390 * Just inherit the wildcard.
11391 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011392 /*
11393 * NOTE: This is the only case where an attribute
11394 * wildcard is shared.
11395 */
11396 if (type->flags & XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD)
11397 type->flags ^= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011398 type->attributeWildcard = baseType->attributeWildcard;
Daniel Veillard50355f02004-06-08 17:52:16 +000011399 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011400 }
11401
11402 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
11403 if (type->attributeWildcard != NULL) {
11404 /*
11405 * Derivation Valid (Restriction, Complex)
11406 * 4.1 The {base type definition} must also have one.
11407 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011408 if (baseType->attributeWildcard == NULL) {
11409 xmlSchemaPCustomErr(ctxt,
11410 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
11411 NULL, type, NULL,
11412 "The type has an attribute wildcard, "
11413 "but the base type %s does not have one",
11414 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11415 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011416 return (1);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011417 } else if (xmlSchemaIsWildcardNsConstraintSubset(
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011418 type->attributeWildcard, baseType->attributeWildcard) == 0) {
11419 /* 4.2 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011420 xmlSchemaPCustomErr(ctxt,
11421 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
11422 NULL, type, NULL,
11423 "The attribute wildcard is not a valid "
11424 "subset of the wildcard in the base type %s",
11425 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11426 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011427 return (1);
11428 }
11429 /* 4.3 Unless the {base type definition} is the ·ur-type
11430 * definition·, the complex type definition's {attribute
11431 * wildcard}'s {process contents} must be identical to or
11432 * stronger than the {base type definition}'s {attribute
11433 * wildcard}'s {process contents}, where strict is stronger
11434 * than lax is stronger than skip.
11435 */
11436 if ((type->baseType != anyType) &&
11437 (type->attributeWildcard->processContents <
11438 baseType->attributeWildcard->processContents)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011439 xmlSchemaPCustomErr(ctxt,
11440 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
11441 NULL, type, NULL,
11442 "The 'process contents' of the attribute wildcard is weaker than "
11443 "the one in the base type %s",
11444 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11445 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011446 return (1);
11447 }
11448 }
11449 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
11450 /*
11451 * Derivation Valid (Extension)
11452 * At this point the type and the base have both, either
11453 * no wildcard or a wildcard.
11454 */
11455 if ((baseType->attributeWildcard != NULL) &&
11456 (baseType->attributeWildcard != type->attributeWildcard)) {
11457 /* 1.3 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011458 if (xmlSchemaIsWildcardNsConstraintSubset(
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011459 baseType->attributeWildcard, type->attributeWildcard) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011460 xmlSchemaPCustomErr(ctxt,
11461 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
11462 NULL, type, NULL,
11463 "The attribute wildcard is not a valid "
11464 "superset of the one in the base type %s",
11465 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11466 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011467 return (1);
11468 }
11469 }
11470 }
11471
Daniel Veillard3646d642004-06-02 19:19:14 +000011472 /*
11473 * Gather attribute uses defined by this type.
11474 */
11475 if (attrs != NULL) {
11476 if (xmlSchemaBuildAttributeUsesOwned(ctxt, attrs,
11477 &uses, &lastUse) == -1) {
11478 return (-1);
11479 }
11480 }
11481 /* 3.4.6 -> Complex Type Definition Properties Correct 4.
11482 * "Two distinct attribute declarations in the {attribute uses} must
11483 * not have identical {name}s and {target namespace}s."
11484 *
11485 * For "extension" this is done further down.
11486 */
11487 if ((uses != NULL) && ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
11488 cur = uses;
11489 while (cur != NULL) {
11490 tmp = cur->next;
11491 while (tmp != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011492 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
11493 xmlSchemaGetAttrName(tmp->attr))) &&
11494 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
11495 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
11496
11497 xmlSchemaPAttrUseErr(ctxt,
11498 XML_SCHEMAP_CT_PROPS_CORRECT_4,
11499 NULL, type, NULL, cur->attr,
11500 "Duplicate attribute use %s specified",
11501 xmlSchemaFormatNsUriLocal(&str,
11502 xmlSchemaGetAttrTargetNsURI(tmp->attr),
11503 xmlSchemaGetAttrName(tmp->attr))
11504 );
11505 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000011506 break;
11507 }
11508 tmp = tmp->next;
11509 }
11510 cur = cur->next;
11511 }
11512 }
11513 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
11514 /*
11515 * Derive by restriction.
11516 */
11517 if (baseIsAnyType) {
11518 type->attributeUses = uses;
11519 } else {
11520 int found;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011521 const xmlChar *bEffValue;
11522 int effFixed;
Daniel Veillard3646d642004-06-02 19:19:14 +000011523
11524 cur = uses;
11525 while (cur != NULL) {
11526 found = 0;
11527 base = type->attributeUses;
11528 while (base != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011529 if (xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
11530 xmlSchemaGetAttrName(base->attr)) &&
11531 xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
11532 xmlSchemaGetAttrTargetNsURI(base->attr))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011533
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011534 found = 1;
11535
Daniel Veillard3646d642004-06-02 19:19:14 +000011536 if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
11537 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
11538 /*
11539 * derivation-ok-restriction 2.1.1
Daniel Veillardc0826a72004-08-10 14:17:33 +000011540 */
11541 xmlSchemaPAttrUseErr(ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000011542 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011543 NULL, type, NULL, cur->attr,
11544 "The 'optional' use is inconsistent with a matching "
11545 "'required' use of the base type", NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000011546 } else if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
11547 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
11548 /*
11549 * derivation-ok-restriction 3
11550 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011551 xmlSchemaPCustomErr(ctxt,
11552 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
11553 NULL, type, NULL,
11554 "A matching attribute use for the 'required' "
11555 "attribute use %s of the base type is missing",
11556 xmlSchemaFormatNsUriLocal(&str,
11557 xmlSchemaGetAttrTargetNsURI(base->attr),
11558 xmlSchemaGetAttrName(base->attr)));
11559 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000011560 } else {
11561 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011562 * 2.1.3 [Definition:] Let the effective value
11563 * constraint of an attribute use be its {value
11564 * constraint}, if present, otherwise its {attribute
11565 * declaration}'s {value constraint} .
11566 */
11567 xmlSchemaGetEffectiveValueConstraint(base->attr, &effFixed,
11568 &bEffValue, 0);
11569 /*
11570 * 2.1.3 ... one of the following must be true
11571 *
11572 * 2.1.3.1 B's ·effective value constraint· is
11573 * ·absent· or default.
11574 */
11575 if ((bEffValue != NULL) &&
11576 (effFixed == 1)) {
11577 const xmlChar *rEffValue = NULL;
11578
11579 xmlSchemaGetEffectiveValueConstraint(base->attr, &effFixed,
11580 &rEffValue, 0);
11581 /*
11582 * 2.1.3.2 R's ·effective value constraint· is
11583 * fixed with the same string as B's.
11584 */
11585 if ((effFixed == 0) ||
11586 (! xmlStrEqual(rEffValue, bEffValue))) {
11587 xmlSchemaPAttrUseErr(ctxt,
11588 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
11589 NULL, type, NULL, cur->attr,
11590 "The effective value constraint of the "
11591 "attribute use is inconsistent with "
11592 "its correspondent of the base type",
11593 NULL);
11594 }
11595 }
11596 /*
11597 * TODO: derivation-ok-restriction 2.1.2 ({type definition} must be validly derived)
11598 */
11599 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000011600 * Override the attribute use.
11601 */
11602 base->attr = cur->attr;
11603 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011604
Daniel Veillard3646d642004-06-02 19:19:14 +000011605 break;
11606 }
11607 base = base->next;
11608 }
11609
11610 if (!found) {
11611 if (cur->attr->occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
11612 /*
11613 * derivation-ok-restriction 2.2
11614 */
11615 if ((type->attributeWildcard != NULL) &&
11616 xmlSchemaMatchesWildcardNs(type->attributeWildcard,
11617 cur->attr->targetNamespace))
11618 found = 1;
11619
11620 if (!found) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011621 xmlSchemaPAttrUseErr(ctxt,
11622 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
11623 NULL, type, NULL, cur->attr,
11624 "Neither a matching attribute use, "
11625 "nor a matching wildcard in the base type does exist",
11626 NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000011627 } else {
11628 /*
11629 * Add the attribute use.
11630 *
11631 * Note that this may lead to funny derivation error reports, if
11632 * multiple equal attribute uses exist; but this is not
11633 * allowed anyway, and it will be reported beforehand.
11634 */
11635 tmp = cur;
11636 if (prev != NULL)
11637 prev->next = cur->next;
11638 else
11639 uses = cur->next;
11640 cur = cur->next;
11641 if (type->attributeUses == NULL) {
11642 type->attributeUses = tmp;
11643 } else
11644 lastBaseUse->next = tmp;
11645 lastBaseUse = tmp;
11646
11647 continue;
11648 }
11649 }
11650 }
11651 prev = cur;
11652 cur = cur->next;
11653 }
11654 if (uses != NULL)
11655 xmlSchemaFreeAttributeUseList(uses);
11656 }
11657 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
11658 /*
11659 * The spec allows only appending, and not other kinds of extensions.
11660 *
11661 * This ensures: Schema Component Constraint: Derivation Valid (Extension) : 1.2
11662 */
11663 if (uses != NULL) {
11664 if (type->attributeUses == NULL) {
11665 type->attributeUses = uses;
11666 } else
11667 lastBaseUse->next = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000011668 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011669 } else {
11670 /*
Daniel Veillard50355f02004-06-08 17:52:16 +000011671 * Derive implicitely from the ur-type.
11672 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011673 type->attributeUses = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000011674 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011675 /*
11676 * 3.4.6 -> Complex Type Definition Properties Correct
11677 */
11678 if (type->attributeUses != NULL) {
11679 cur = type->attributeUses;
11680 prev = NULL;
11681 while (cur != NULL) {
11682 /*
11683 * 4. Two distinct attribute declarations in the {attribute uses} must
11684 * not have identical {name}s and {target namespace}s.
Daniel Veillard50355f02004-06-08 17:52:16 +000011685 *
Daniel Veillard3646d642004-06-02 19:19:14 +000011686 * Note that this was already done for "restriction" and types derived from
11687 * the ur-type.
Daniel Veillard50355f02004-06-08 17:52:16 +000011688 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011689 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
11690 tmp = cur->next;
11691 while (tmp != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011692 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
11693 xmlSchemaGetAttrName(tmp->attr))) &&
11694 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
11695 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011696
Daniel Veillardc0826a72004-08-10 14:17:33 +000011697 xmlSchemaPAttrUseErr(ctxt,
11698 XML_SCHEMAP_CT_PROPS_CORRECT_4,
11699 NULL, type, NULL, tmp->attr,
11700 "Duplicate attribute use specified", NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000011701 break;
11702 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011703 tmp = tmp->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000011704 }
11705 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011706 /*
11707 * 5. Two distinct attribute declarations in the {attribute uses} must
11708 * not have {type definition}s which are or are derived from ID.
11709 */
11710 if ((cur->attr->subtypes != NULL) &&
Daniel Veillard01fa6152004-06-29 17:04:39 +000011711 (xmlSchemaIsDerivedFromBuiltInType(ctxt, (xmlSchemaTypePtr) cur->attr, XML_SCHEMAS_ID))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011712 if (id != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011713 xmlSchemaPAttrUseErr(ctxt,
11714 XML_SCHEMAP_CT_PROPS_CORRECT_5,
11715 NULL, type, NULL, cur->attr,
11716 "There must not exist more than one attribute use, "
11717 "declared of type 'ID' or derived from it",
11718 NULL);
11719 FREE_AND_NULL(str)
Daniel Veillard50355f02004-06-08 17:52:16 +000011720 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011721 id = cur;
11722 }
11723 /*
11724 * Remove "prohibited" attribute uses. The reason this is done at this late
11725 * stage is to be able to catch dublicate attribute uses. So we had to keep
11726 * prohibited uses in the list as well.
11727 */
11728 if (cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
11729 tmp = cur;
11730 if (prev == NULL)
11731 type->attributeUses = cur->next;
11732 else
11733 prev->next = cur->next;
11734 cur = cur->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000011735 xmlFree(tmp);
Daniel Veillard3646d642004-06-02 19:19:14 +000011736 } else {
11737 prev = cur;
11738 cur = cur->next;
11739 }
11740 }
11741 }
11742 /*
11743 * TODO: This check should be removed if we are 100% sure of
11744 * the base type attribute uses already being built.
11745 */
11746 if ((baseType != NULL) && (!baseIsAnyType) &&
11747 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
11748 (baseType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011749 xmlSchemaPErr(ctxt, baseType->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011750 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011751 "attribute uses not builded on base type '%s'.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +000011752 baseType->name, NULL);
11753 }
11754 return (0);
11755}
11756
11757/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000011758 * xmlSchemaTypeFinalContains:
11759 * @schema: the schema
11760 * @type: the type definition
11761 * @final: the final
11762 *
11763 * Evaluates if a type definition contains the given "final".
11764 * This does take "finalDefault" into account as well.
11765 *
11766 * Returns 1 if the type does containt the given "final",
11767 * 0 otherwise.
11768 */
11769static int
11770xmlSchemaTypeFinalContains(xmlSchemaPtr schema, xmlSchemaTypePtr type, int final)
11771{
11772 int tfinal = final, tflags = type->flags;
11773
11774 if (type == NULL)
11775 return (0);
11776 if (type->flags & XML_SCHEMAS_TYPE_FINAL_DEFAULT) {
11777 switch (final) {
11778 case XML_SCHEMAS_TYPE_FINAL_RESTRICTION:
11779 tfinal = XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
11780 break;
11781 case XML_SCHEMAS_TYPE_FINAL_EXTENSION:
11782 tfinal = XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
11783 break;
11784 case XML_SCHEMAS_TYPE_FINAL_LIST:
11785 tfinal = XML_SCHEMAS_FINAL_DEFAULT_LIST;
11786 break;
11787 case XML_SCHEMAS_TYPE_FINAL_UNION:
11788 tfinal = XML_SCHEMAS_FINAL_DEFAULT_UNION;
11789 break;
11790 }
11791 tflags = schema->flags;
11792 }
11793 if (tflags & tfinal)
11794 return (1);
11795 else
11796 return (0);
11797
11798}
11799
11800/**
11801 * xmlSchemaGetUnionSimpleTypeMemberTypes:
11802 * @type: the Union Simple Type
11803 *
11804 * Returns a list of member types of @type if existing,
11805 * returns NULL otherwise.
11806 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011807static xmlSchemaTypeLinkPtr
Daniel Veillard01fa6152004-06-29 17:04:39 +000011808xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
11809{
11810 while (type != NULL) {
11811 if (type->memberTypes != NULL)
11812 return (type->memberTypes);
11813 else
11814 type = type->baseType;
11815 }
11816 return (NULL);
11817}
11818
11819/**
11820 * xmlSchemaGetListSimpleTypeItemType:
11821 * @type: the simple type definition
11822 *
11823 * Returns the item type definition of the list simple type.
11824 */
11825static xmlSchemaTypePtr
11826xmlSchemaGetListSimpleTypeItemType(xmlSchemaTypePtr type)
11827{
11828 if ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)
11829 return (NULL);
11830 /*
11831 * Note: In libxml2, the built-in types do not reflect
11832 * the datatype hierarchy (yet?) - we have to treat them
11833 * in a special way.
11834 */
11835 if (type->type == XML_SCHEMA_TYPE_BASIC)
11836 return (xmlSchemaGetBuiltInListSimpleTypeItemType(type));
11837 if (type->subtypes->type == XML_SCHEMA_TYPE_LIST)
11838 /* 1 If the <list> alternative is chosen, then the type
11839 * definition ·resolved· to by the ·actual value· of the
11840 * itemType [attribute] of <list>, if present, otherwise
11841 * the type definition corresponding to the <simpleType>
11842 * among the [children] of <list>.
11843 */
11844 return (type->subtypes->subtypes);
11845 else {
11846 /* 2 If the <restriction> option is chosen, then the
11847 * {item type definition} of the {base type definition}.
11848 */
11849 return (xmlSchemaGetListSimpleTypeItemType(type->baseType));
11850 }
11851}
11852
11853/**
11854 * xmlSchemaCheckCOSSTDerivedOK:
11855 * @type: the derived simple type definition
11856 * @baseType: the base type definition
11857 *
11858 * Checks wheter @type can be validly
11859 * derived from @baseType.
11860 *
11861 * Returns 0 on success, an positive error code otherwise.
11862 */
11863static int
11864xmlSchemaCheckCOSSTDerivedOK(xmlSchemaPtr schema,
11865 xmlSchemaTypePtr type,
11866 xmlSchemaTypePtr baseType,
11867 int subset)
11868{
11869 /*
11870 * Schema Component Constraint: Type Derivation OK (Simple)
11871 *
11872 *
11873 * 1 They are the same type definition.
11874 * TODO: The identy check might have to be more complex than this.
11875 */
11876 if (type == baseType)
11877 return (0);
11878 /*
11879 * 2.1 restriction is not in the subset, or in the {final}
11880 * of its own {base type definition};
11881 */
11882 if ((subset & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) ||
11883 (xmlSchemaTypeFinalContains(schema,
11884 type->baseType, XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
11885 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
11886 }
11887 /* 2.2 */
11888 if (type->baseType == baseType) {
11889 /*
11890 * 2.2.1 D's ·base type definition· is B.
11891 */
11892 return (0);
11893 }
11894 /*
11895 * 2.2.2 D's ·base type definition· is not the ·ur-type definition·
11896 * and is validly derived from B given the subset, as defined by this
11897 * constraint.
11898 */
11899 if ((type->baseType != xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE)) &&
11900 (xmlSchemaCheckCOSSTDerivedOK(schema, type->baseType, baseType, subset) == 0)) {
11901 return (0);
11902 }
11903 /*
11904 * 2.2.3 D's {variety} is list or union and B is the ·simple ur-type
11905 * definition·.
11906 */
11907 if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
11908 (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)) &&
11909 (baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE))) {
11910 return (0);
11911 }
11912 /*
11913 * 2.2.4 B's {variety} is union and D is validly derived from a type
11914 * definition in B's {member type definitions} given the subset, as
11915 * defined by this constraint.
11916 *
11917 * NOTE: This seems not to involve built-in types, since there is no
11918 * built-in Union Simple Type.
11919 */
11920 if (baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
11921 xmlSchemaTypeLinkPtr cur;
11922
11923 cur = baseType->memberTypes;
11924 while (cur != NULL) {
11925 if (xmlSchemaCheckCOSSTDerivedOK(schema, type,
11926 cur->type, subset) == 0)
11927 return (0);
11928 cur = cur->next;
11929 }
11930 }
11931
11932 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
11933}
11934
11935
11936/**
11937 * xmlSchemaCheckSTPropsCorrect:
11938 * @ctxt: the schema parser context
11939 * @type: the simple type definition
11940 *
11941 * Checks st-props-correct.
11942 *
11943 * Returns 0 if the properties are correct,
11944 * if not, a positive error code and -1 on internal
11945 * errors.
11946 */
11947static int
11948xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
11949 xmlSchemaTypePtr type)
11950{
11951 xmlSchemaTypePtr baseType = type->baseType, anySimpleType,
11952 anyType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011953 xmlChar *str = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011954
Daniel Veillardc0826a72004-08-10 14:17:33 +000011955 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011956 /*
11957 * Schema Component Constraint: Simple Type Definition Properties Correct
11958 *
11959 * NOTE: This is somehow redundant, since we actually built a simple type
11960 * to have all the needed information; this acts as an self test.
11961 */
11962 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
11963 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
11964 /*
11965 * TODO: 1 The values of the properties of a simple type definition must be as
11966 * described in the property tableau in Datatype definition, modulo the
11967 * impact of Missing Sub-components (§5.3).
11968 */
11969 /* Base type: If the datatype has been ·derived· by ·restriction·
11970 * then the Simple Type Definition component from which it is ·derived·,
11971 * otherwise the Simple Type Definition for anySimpleType (§4.1.6).
11972 */
11973 if (baseType == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011974 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011975 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011976 NULL, type, NULL,
11977 "No base type existent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011978 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
11979 }
11980 if ((baseType->type != XML_SCHEMA_TYPE_SIMPLE) &&
11981 ((baseType->type != XML_SCHEMA_TYPE_BASIC) ||
11982 (baseType == anyType))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011983 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011984 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011985 NULL, type, NULL,
11986 "The base type %s is not a simple type",
11987 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11988 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011989 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
11990 }
11991 if ((baseType != anySimpleType) &&
11992 (type->subtypes->type != XML_SCHEMA_TYPE_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011993 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011994 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011995 NULL, type, NULL,
11996 "A type, derived by list or union, must have"
11997 "the simple ur-type definition as base type, not %s",
11998 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11999 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012000 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
12001 }
12002 /*
12003 * Variety: One of {atomic, list, union}.
12004 */
12005 if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
12006 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) &&
12007 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012008 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012009 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012010 NULL, type, NULL,
12011 "The variety is absent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012012 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
12013 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000012014 /* TODO: Finish this. Hmm, is this finished? */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012015
12016 /*
12017 * 2 All simple type definitions must be derived ultimately from the ·simple
12018 * ur-type definition (so· circular definitions are disallowed). That is, it
12019 * must be possible to reach a built-in primitive datatype or the ·simple
12020 * ur-type definition· by repeatedly following the {base type definition}.
12021 */
12022 baseType = type->baseType;
12023 while ((baseType != NULL) && (baseType->type != XML_SCHEMA_TYPE_BASIC)) {
12024 if (baseType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
12025 xmlSchemaTypeFixup(baseType, ctxt, NULL);
12026 if (baseType == anySimpleType)
12027 break;
12028 else if (baseType == type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012029 xmlSchemaPCustomErr(ctxt,
12030 XML_SCHEMAP_ST_PROPS_CORRECT_2,
12031 NULL, type, NULL,
12032 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012033 return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
12034 }
12035 baseType = baseType->baseType;
12036 }
12037 /*
12038 * 3 The {final} of the {base type definition} must not contain restriction.
12039 */
12040 if (xmlSchemaTypeFinalContains(ctxt->schema, baseType,
12041 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012042 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012043 XML_SCHEMAP_ST_PROPS_CORRECT_3,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012044 NULL, type, NULL,
12045 "The 'final' of its base type %s must not contain "
12046 "'restriction'",
12047 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
12048 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012049 return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
12050 }
12051 return (0);
12052}
12053
12054/**
12055 * xmlSchemaCheckDerivationValidSimpleRestriction:
12056 * @ctxt: the schema parser context
12057 * @type: the simple type definition
12058 *
12059 * Checks if the given @type (simpleType) is derived
12060 * validly by restriction.
12061 *
12062 * Returns -1 on internal errors, 0 if the type is validly derived,
12063 * a positive error code otherwise.
12064 */
12065static int
12066xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012067 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012068{
Daniel Veillardc0826a72004-08-10 14:17:33 +000012069 xmlChar *str = NULL;
12070
12071 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012072
12073 if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
12074 xmlSchemaPErr(ctxt, type->node,
12075 XML_ERR_INTERNAL_ERROR,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012076 "xmlSchemaCheckDerivationValidSimpleRestriction: The given "
12077 "type '%s' is not a user-derived simpleType.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012078 type->name, NULL);
12079 return (-1);
12080 }
12081
12082 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
12083 xmlSchemaTypePtr primitive;
12084 /*
12085 * 1.1 The {base type definition} must be an atomic simple
12086 * type definition or a built-in primitive datatype.
12087 */
12088 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012089 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012090 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012091 NULL, type, NULL,
12092 "The base type %s is not an atomic simple type",
12093 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
12094 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012095 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
12096 }
12097 /* 1.2 The {final} of the {base type definition} must not contain
12098 * restriction.
12099 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000012100 /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012101 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
12102 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012103 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012104 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012105 NULL, type, NULL,
12106 "The final of its base type %s must not contain 'restriction'",
12107 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
12108 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012109 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
12110 }
12111
12112 /*
12113 * 1.3.1 DF must be an allowed constraining facet for the {primitive
12114 * type definition}, as specified in the appropriate subsection of 3.2
12115 * Primitive datatypes.
12116 */
12117 if (type->facets != NULL) {
12118 xmlSchemaFacetPtr facet;
12119 int ok = 1;
12120
12121 primitive = xmlSchemaGetPrimitiveType(type);
12122 if (primitive == NULL) {
12123 xmlSchemaPErr(ctxt, type->node,
12124 XML_ERR_INTERNAL_ERROR,
12125 "xmlSchemaCheckDerivationValidSimpleRestriction: failed "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012126 "to get primitive type of type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012127 type->name, NULL);
12128 return (-1);
12129 }
12130 facet = type->facets;
12131 do {
12132 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012133 ok = 0;
12134 xmlSchemaPIllegalFacetAtomicErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012135 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012136 NULL, type, primitive, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012137 }
12138 facet = facet->next;
12139 } while (facet != NULL);
12140 if (ok == 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +000012141 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012142 }
12143 /*
12144 * TODO: 1.3.2 (facet derivation)
12145 */
12146 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
12147 xmlSchemaTypePtr itemType = NULL;
12148
12149 itemType = xmlSchemaGetListSimpleTypeItemType(type);
12150 if (itemType == NULL) {
12151 xmlSchemaPErr(ctxt, type->node,
12152 XML_ERR_INTERNAL_ERROR,
12153 "Internal error: xmlSchemaCheckDerivationValidSimpleRestriction: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012154 "failed to evaluate the item type of type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012155 type->name, NULL);
12156 return (-1);
12157 }
12158 /*
12159 * 2.1 The {item type definition} must have a {variety} of atomic or
12160 * union (in which case all the {member type definitions}
12161 * must be atomic).
12162 */
12163 if (((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
12164 ((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012165 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012166 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012167 NULL, type, NULL,
12168 "The item type %s must have a variety of atomic or union",
12169 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1));
12170 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012171 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
12172 } else if (itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
12173 xmlSchemaTypeLinkPtr member;
12174
12175 member = itemType->memberTypes;
12176 while (member != NULL) {
12177 if ((member->type->flags &
12178 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012179 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012180 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012181 NULL, type, NULL,
12182 "The item type is a union type, but the "
12183 "member type %s of this item type is not atomic",
12184 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
12185 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012186 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
12187 }
12188 member = member->next;
12189 }
12190 }
12191
12192 if (type->baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE)) {
12193 xmlSchemaFacetPtr facet;
12194 /*
12195 * This is the case if we have: <simpleType><list ..
12196 */
12197 /*
12198 * 2.3.1
12199 * 2.3.1.1 The {final} of the {item type definition} must not
12200 * contain list.
12201 */
12202 if (xmlSchemaTypeFinalContains(ctxt->schema,
12203 itemType, XML_SCHEMAS_TYPE_FINAL_LIST)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012204 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012205 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012206 NULL, type, NULL,
12207 "The final of its item type %s must not contain 'list'",
12208 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1));
12209 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012210 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
12211 }
12212 /*
12213 * 2.3.1.2 The {facets} must only contain the whiteSpace
12214 * facet component.
12215 */
12216 if (type->facets != NULL) {
12217 facet = type->facets;
12218 do {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012219 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
12220 xmlSchemaPIllegalFacetListUnionErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012221 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012222 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012223 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
12224 }
12225 facet = facet->next;
12226 } while (facet != NULL);
12227 }
12228 /*
12229 * TODO: Datatypes states:
12230 * A ·list· datatype can be ·derived· from an ·atomic· datatype
12231 * whose ·lexical space· allows space (such as string or anyURI)or
12232 * a ·union· datatype any of whose {member type definitions}'s
12233 * ·lexical space· allows space.
12234 */
12235 } else {
12236 /*
12237 * This is the case if we have: <simpleType><restriction ...
12238 */
12239 /*
12240 * 2.3.2
12241 * 2.3.2.1 The {base type definition} must have a {variety} of list.
12242 */
12243 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012244 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012245 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012246 NULL, type, NULL,
12247 "The base type %s must be a list type",
12248 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
12249 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012250 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
12251 }
12252 /*
12253 * 2.3.2.2 The {final} of the {base type definition} must not
12254 * contain restriction.
12255 */
12256 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
12257 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012258 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012259 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012260 NULL, type, NULL,
12261 "The final of the base type %s must not contain 'restriction'",
12262 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
12263 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012264 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
12265 }
12266 /*
12267 * 2.3.2.3 The {item type definition} must be validly derived
12268 * from the {base type definition}'s {item type definition} given
12269 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6).
12270 */
12271 {
12272 xmlSchemaTypePtr baseItemType;
12273
12274 baseItemType = xmlSchemaGetListSimpleTypeItemType(type->baseType);
12275 if (baseItemType == NULL) {
12276 xmlSchemaPErr(ctxt, type->node,
12277 XML_ERR_INTERNAL_ERROR,
12278 "xmlSchemaCheckDerivationValidSimpleRestriction: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012279 "List simple type '%s': Failed to "
12280 "evaluate the item type of its base type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012281 type->name, type->baseType->name);
12282 return (-1);
12283 }
12284 if ((itemType != baseItemType) &&
12285 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema, itemType,
12286 baseItemType, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012287 xmlChar *strBIT = NULL, *strBT = NULL;
12288 xmlSchemaPCustomErrExt(ctxt,
12289 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
12290 NULL, type, NULL,
12291 "The item type %s is not validly derived from the "
12292 "item type %s of the base type %s",
12293 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1),
12294 xmlSchemaFormatItemForReport(&strBIT, NULL, baseItemType, NULL, 1),
12295 xmlSchemaFormatItemForReport(&strBT, NULL, type->baseType, NULL, 1));
12296
12297 FREE_AND_NULL(str)
12298 FREE_AND_NULL(strBIT)
12299 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012300 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
12301 }
12302 }
12303
12304 if (type->facets != NULL) {
12305 xmlSchemaFacetPtr facet;
12306 int ok = 1;
12307 /*
12308 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
12309 * and enumeration facet components are allowed among the {facets}.
12310 */
12311 facet = type->facets;
12312 do {
12313 switch (facet->type) {
12314 case XML_SCHEMA_FACET_LENGTH:
12315 case XML_SCHEMA_FACET_MINLENGTH:
12316 case XML_SCHEMA_FACET_MAXLENGTH:
12317 case XML_SCHEMA_FACET_WHITESPACE:
12318 /*
12319 * TODO: 2.5.1.2 List datatypes
12320 * The value of ·whiteSpace· is fixed to the value collapse.
12321 */
12322 case XML_SCHEMA_FACET_PATTERN:
12323 case XML_SCHEMA_FACET_ENUMERATION:
12324 break;
12325 default: {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012326 xmlSchemaPIllegalFacetListUnionErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012327 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012328 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012329 /*
12330 * We could return, but it's nicer to report all
12331 * invalid facets.
12332 */
12333 ok = 0;
12334 }
12335 }
12336 facet = facet->next;
12337 } while (facet != NULL);
12338 if (ok == 0)
12339 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
12340 /*
12341 * TODO: 2.3.2.5 For each facet in the {facets} (call this DF), if there
12342 * is a facet of the same kind in the {facets} of the {base type
12343 * definition} (call this BF),then the DF's {value} must be a valid
12344 * restriction of BF's {value} as defined in [XML Schemas: Datatypes].
12345 */
12346 }
12347
12348
12349 }
12350 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
12351 /*
12352 * 3.1 The {member type definitions} must all have {variety} of
12353 * atomic or list.
12354 */
12355 xmlSchemaTypeLinkPtr member;
12356
12357 member = type->memberTypes;
12358 while (member != NULL) {
12359 if (((member->type->flags &
12360 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
12361 ((member->type->flags &
12362 XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012363 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012364 XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012365 NULL, type, NULL,
12366 "The member type %s is neither an atomic, nor a list type",
12367 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
12368 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012369 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
12370 }
12371 member = member->next;
12372 }
12373 /*
12374 * 3.3.1 If the {base type definition} is the ·simple ur-type
12375 * definition·
12376 */
12377 if (type->baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE)) {
12378 /*
12379 * 3.3.1.1 All of the {member type definitions} must have a
12380 * {final} which does not contain union.
12381 */
12382 member = type->memberTypes;
12383 while (member != NULL) {
12384 if (xmlSchemaTypeFinalContains(ctxt->schema, member->type,
12385 XML_SCHEMAS_TYPE_FINAL_UNION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012386 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012387 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012388 NULL, type, NULL,
12389 "The final of member type %s contains 'union'",
12390 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
12391 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012392 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
12393 }
12394 member = member->next;
12395 }
12396 /*
12397 * 3.3.1.2 The {facets} must be empty.
12398 */
12399 if (type->facetSet != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012400 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012401 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012402 NULL, type, NULL,
12403 "No facets allowed", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012404 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
12405 }
12406 } else {
12407 /*
12408 * 3.3.2.1 The {base type definition} must have a {variety} of union.
12409 */
12410 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012411 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012412 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012413 NULL, type, NULL,
12414 "The base type %s is not a union type",
12415 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
12416 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012417 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
12418 }
12419 /*
12420 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
12421 */
12422 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
12423 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012424 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012425 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012426 NULL, type, NULL,
12427 "The final of its base type %s must not contain 'restriction'",
12428 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
12429 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012430 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
12431 }
12432 /*
12433 * 3.3.2.3 The {member type definitions}, in order, must be validly
12434 * derived from the corresponding type definitions in the {base
12435 * type definition}'s {member type definitions} given the empty set,
12436 * as defined in Type Derivation OK (Simple) (§3.14.6).
12437 */
12438 {
12439 xmlSchemaTypeLinkPtr baseMember;
12440
12441 /*
12442 * OPTIMIZE: if the type is restricting, it has no local defined
12443 * member types and inherits the member types of the base type;
12444 * thus a check for equality can be skipped.
12445 */
12446 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000012447 * Even worse: I cannot see a scenario where a restricting
Daniel Veillard01fa6152004-06-29 17:04:39 +000012448 * union simple type can have other member types as the member
12449 * types of it's base type. This check seems not necessary with
12450 * respect to the derivation process in libxml2.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000012451 * But necessary if constructing types with an API.
Daniel Veillard01fa6152004-06-29 17:04:39 +000012452 */
12453 if (type->memberTypes != NULL) {
12454 member = type->memberTypes;
12455 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
12456 if ((member == NULL) && (baseMember != NULL)) {
12457 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012458 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012459 "Internal error: "
12460 "xmlSchemaCheckDerivationValidSimpleRestriction "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012461 "(3.3.2.3), union simple type '%s', unequal number "
Daniel Veillard01fa6152004-06-29 17:04:39 +000012462 "of member types in the base type\n",
12463 type->name, NULL);
12464 }
12465 while (member != NULL) {
12466 if (baseMember == NULL) {
12467 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012468 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012469 "Internal error: "
12470 "xmlSchemaCheckDerivationValidSimpleRestriction "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012471 "(3.3.2.3), union simple type '%s', unequal number "
12472 "of member types in the base type.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012473 type->name, NULL);
12474 }
12475 if ((member->type != baseMember->type) &&
12476 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema,
12477 member->type, baseMember->type, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012478 xmlChar *strBMT = NULL, *strBT = NULL;
12479
12480 xmlSchemaPCustomErrExt(ctxt,
12481 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
12482 NULL, type, NULL,
12483 "The member type %s is not validly derived from its "
12484 "corresponding member type %s of the base type %s",
12485 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1),
12486 xmlSchemaFormatItemForReport(&strBMT, NULL, baseMember->type, NULL, 1),
12487 xmlSchemaFormatItemForReport(&strBT, NULL, type->baseType, NULL, 1));
12488 FREE_AND_NULL(str)
12489 FREE_AND_NULL(strBMT)
12490 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012491 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
12492 }
12493 member = member->next;
12494 baseMember = baseMember->next;
12495 }
12496 }
12497 }
12498 /*
12499 * 3.3.2.4 Only pattern and enumeration facet components are
12500 * allowed among the {facets}.
12501 */
12502 if (type->facets != NULL) {
12503 xmlSchemaFacetPtr facet;
12504 int ok = 1;
12505
12506 facet = type->facets;
12507 do {
12508 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
12509 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012510 xmlSchemaPIllegalFacetListUnionErr(ctxt,
12511 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
12512 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012513 ok = 0;
12514 }
12515 facet = facet->next;
12516 } while (facet != NULL);
12517 if (ok == 0)
12518 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
12519
12520 }
12521 /*
12522 * TODO: 3.3.2.5 (facet derivation)
12523 */
12524 }
12525 }
12526
12527 return (0);
12528}
12529
12530/**
12531 * xmlSchemaCheckSRCSimpleType:
12532 * @ctxt: the schema parser context
12533 * @type: the simple type definition
12534 *
12535 * Checks crc-simple-type constraints.
12536 *
12537 * Returns 0 if the constraints are satisfied,
12538 * if not a positive error code and -1 on internal
12539 * errors.
12540 */
12541static int
12542xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
12543 xmlSchemaTypePtr type)
12544{
12545 /*
12546 * NOTE: src-simple-type 2-4 are redundant, since the checks
12547 * were are done for the corresponding <restriction>, <list> and <union>
12548 * elements, but W3C wants a <simpleType> error as well, so it gets one.
12549 * Maby this can be skipped in the future, if we get sure it's not needed.
12550 */
12551 if (type->subtypes == NULL) {
12552 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012553 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012554 "Internal error: xmlSchemaCheckSRCSimpleType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012555 "no subtype on simple type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012556 type->name, NULL);
12557 return (-1);
12558 }
12559 /*
12560 * src-simple-type.1 The corresponding simple type definition, if any,
12561 * must satisfy the conditions set out in Constraints on Simple Type
12562 * Definition Schema Components (§3.14.6).
12563 */
12564 if ((xmlSchemaCheckSTPropsCorrect(ctxt, type) != 0) ||
12565 (xmlSchemaCheckCOSSTRestricts(ctxt, type) != 0)) {
12566 /*
12567 * TODO: Removed this, since it got annoying to get an
12568 * extra error report, if anything failed until now.
12569 * Enable this if needed.
12570 */
12571 /*
12572 xmlSchemaPErr(ctxt, type->node,
12573 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012574 "Simple type '%s' does not satisfy the constraints "
Daniel Veillard01fa6152004-06-29 17:04:39 +000012575 "on simple type definitions.\n",
12576 type->name, NULL);
12577 */
12578 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_1);
12579 }
12580
12581 if (type->subtypes->type == XML_SCHEMA_TYPE_RESTRICTION) {
12582 /*
12583 * src-simple-type.2 If the <restriction> alternative is chosen,
12584 * either it must have a base [attribute] or a <simpleType> among its
12585 * [children], but not both.
12586 */
William M. Brack2f2a6632004-08-20 23:09:47 +000012587 /*
12588 * XML_SCHEMAP_SRC_SIMPLE_TYPE_2
12589 * NOTE: This was removed, since this will be already handled
12590 * in the parse function for <restriction>.
12591 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012592 } else if (type->subtypes->type == XML_SCHEMA_TYPE_LIST) {
12593 /* src-simple-type.3 If the <list> alternative is chosen, either it must have
12594 * an itemType [attribute] or a <simpleType> among its [children],
12595 * but not both.
12596 * NOTE: baseType is set to the local simple type definiton,
12597 * if existent, at parse time. This is a hack and not nice.
12598 */
William M. Brack2f2a6632004-08-20 23:09:47 +000012599 /*
12600 * TODO: Remove this, and add the check to the parse function of <list>.
12601 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012602 if (((type->subtypes->base == NULL) &&
12603 (type->baseType == NULL)) ||
12604 ((type->subtypes->base != NULL) &&
12605 (type->subtypes->baseType != NULL))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012606 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012607 XML_SCHEMAP_SRC_SIMPLE_TYPE_3,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012608 NULL, type, NULL,
12609 "Either the attribute 'itemType' or the <simpleType> child "
12610 "must be present on the <list> child ", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012611 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_3);
12612 }
12613
12614
12615 } else if (type->subtypes->type == XML_SCHEMA_TYPE_UNION) {
12616 xmlSchemaTypeLinkPtr member;
12617 xmlSchemaTypePtr ancestor, anySimpleType;
12618
12619 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
12620
12621 /* src-simple-type.4 Circular union type definition is disallowed. That is, if
12622 * the <union> alternative is chosen, there must not be any entries
12623 * in the memberTypes [attribute] at any depth which resolve to the
12624 * component corresponding to the <simpleType>.
12625 */
12626 member = type->memberTypes;
12627 while (member != NULL) {
12628 ancestor = member->type;
12629 while ((ancestor != NULL) && (ancestor->type != XML_SCHEMA_TYPE_BASIC)) {
12630 if (ancestor->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
12631 xmlSchemaTypeFixup(ancestor, ctxt, NULL);
12632 if (ancestor == anySimpleType)
12633 break;
12634 else if (ancestor == type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012635 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012636 XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012637 NULL, type, NULL,
12638 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012639 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
12640 } else if (ancestor->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
12641 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000012642 * TODO, FIXME: Although a list simple type must not have a union ST
Daniel Veillard01fa6152004-06-29 17:04:39 +000012643 * type as item type, which in turn has a list ST as member
12644 * type, we will assume this here as well, since this check
12645 * was not yet performed.
12646 */
12647
12648 }
12649 ancestor = ancestor->baseType;
12650 }
12651 member = member->next;
12652 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012653 }
12654
12655 return (0);
12656}
12657
William M. Brack2f2a6632004-08-20 23:09:47 +000012658#if 0 /* Not yet used code for CT schema validation */
12659static int
12660xmlSchemaCheckCVCSimpleType(xmlSchemaValidCtxtPtr ctxt,
12661 const xmlChar * value,
12662 xmlSchemaTypePtr type,
12663 int fireErrors)
12664{
12665 int ret;
12666 /*
12667 * 3.14.4 Simple Type Definition Validation Rules
12668 * Validation Rule: String Valid
12669 */
12670 /*
12671 * 1 It is schema-valid with respect to that definition as defined
12672 * by Datatype Valid in [XML Schemas: Datatypes].
12673 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012674 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type, value,
12675 fireErrors, 1, 1, 1);
William M. Brack2f2a6632004-08-20 23:09:47 +000012676 return (ret);
12677 /*
12678 * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
12679 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6), then
12680 * the string must be a ·declared entity name·.
12681 */
12682 /*
12683 * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
12684 * given the empty set, as defined in Type Derivation OK (Simple) (§3.14.6),
12685 * then every whitespace-delimited substring of the string must be a ·declared
12686 * entity name·.
12687 */
12688 /*
12689 * 2.3 otherwise no further condition applies.
12690 */
12691
12692 return (0);
12693}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012694#endif
12695
William M. Brack2f2a6632004-08-20 23:09:47 +000012696
12697static int
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012698xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
12699{
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000012700 if (vctxt->pctxt == NULL) {
12701 if (vctxt->schema != NULL)
12702 vctxt->pctxt = xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
12703 else
12704 vctxt->pctxt = xmlSchemaNewParserCtxt("*");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012705 if (vctxt->pctxt == NULL) {
12706 xmlSchemaVErr(vctxt, NULL,
12707 XML_SCHEMAV_INTERNAL,
12708 "Internal error: xmlSchemaCreatePCtxtOnVCtxt, "
12709 "failed to create a temp. parser context.\n",
William M. Brack2f2a6632004-08-20 23:09:47 +000012710 NULL, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012711 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012712 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012713 /* TODO: Pass user data. */
12714 xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error, vctxt->warning, NULL);
12715 }
12716 return (0);
12717}
12718
12719static int
12720xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
12721{
12722 if (ctxt->vctxt == NULL) {
12723 ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
12724 if (ctxt->vctxt == NULL) {
12725 xmlSchemaPErr(ctxt, NULL,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012726 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012727 "Internal error: xmlSchemaCreatePCtxtOnVCtxt, "
12728 "failed to create a temp. validation context.\n",
12729 NULL, NULL);
12730 return (-1);
12731 }
12732 /* TODO: Pass user data. */
12733 xmlSchemaSetValidErrors(ctxt->vctxt, ctxt->error, ctxt->warning, NULL);
12734 }
12735 return (0);
12736}
12737
12738/**
12739 * xmlSchemaCheckCOSValidDefault:
12740 * @ctxt: the schema parser context
12741 * @type: the simple type definition
12742 * @value: the default value
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000012743 * @val: the precomputed value to be returned
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012744 * @node: an optional node (the holder of the value)
12745 *
12746 * Checks the "cos-valid-default" constraints.
12747 *
12748 * Returns 0 if the constraints are satisfied,
12749 * if not, a positive error code and -1 on internal
12750 * errors.
12751 */
12752static int
12753xmlSchemaCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
12754 xmlSchemaValidCtxtPtr vctxt,
12755 xmlSchemaTypePtr type,
12756 const xmlChar *value,
12757 xmlNodePtr node)
12758{
12759 int ret = 0;
12760
12761 /*
12762 * cos-valid-default:
12763 * Schema Component Constraint: Element Default Valid (Immediate)
12764 * For a string to be a valid default with respect to a type
12765 * definition the appropriate case among the following must be true:
12766 */
12767 /*
12768 * NOTE: This has to work without a given node (the holder of the
12769 * value), since it should work on the component, i.e. an underlying
12770 * DOM must not be mandatory.
12771 */
12772 if ((pctxt == NULL) || (vctxt == NULL)) {
12773 xmlSchemaPErr(pctxt, node,
12774 XML_SCHEMAP_INTERNAL,
12775 "Internal error: xmlSchemaCheckCOSValidDefault, "
12776 "bad arguments: the parser and/or validation context is "
12777 "missing.\n",
12778 NULL, NULL);
12779 return (-1);
12780 }
12781 if IS_COMPLEX_TYPE(type) {
William M. Brack2f2a6632004-08-20 23:09:47 +000012782 /*
12783 * Complex type.
12784 *
12785 * 2.1 its {content type} must be a simple type definition or mixed.
12786 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012787 /*
12788 * TODO: Adjust this when the content type will be computed
12789 * correctly.
12790 */
12791 if ((type->contentType != XML_SCHEMA_CONTENT_SIMPLE) &&
12792 (type->contentType != XML_SCHEMA_CONTENT_BASIC) &&
12793 (type->contentType != XML_SCHEMA_CONTENT_MIXED)) {
12794 xmlSchemaPSimpleTypeErr(pctxt,
12795 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
12796 NULL, NULL, node,
12797 type, NULL, NULL,
12798 "If the type of a constraint value is complex, its content "
12799 "type must be mixed or a simple type",
12800 NULL, NULL);
12801 return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
12802 }
12803 if (type->contentType == XML_SCHEMA_CONTENT_MIXED) {
William M. Brack2f2a6632004-08-20 23:09:47 +000012804 /*
12805 * 2.2.2 If the {content type} is mixed, then the {content type}'s
12806 * particle must be ·emptiable· as defined by Particle Emptiable
12807 * (§3.9.6).
12808 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012809
William M. Brack2f2a6632004-08-20 23:09:47 +000012810 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012811 * URGENT TODO: Implement this.
William M. Brack2f2a6632004-08-20 23:09:47 +000012812 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012813 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000012814 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012815 }
12816 /*
12817 * 1 If the type definition is a simple type definition, then the string
12818 * must be ·valid· with respect to that definition as defined by String
12819 * Valid (§3.14.4).
12820 *
12821 * AND
12822 *
12823 * 2.2.1 If the {content type} is a simple type definition, then the
12824 * string must be ·valid· with respect to that simple type definition
12825 * as defined by String Valid (§3.14.4).
12826 */
12827 vctxt->node = node;
12828 vctxt->cur = NULL;
12829 ret = xmlSchemaValidateSimpleTypeValue(vctxt, type, value, 1, 1, 1, 0);
12830 /* ret = xmlSchemaCheckCVCSimpleType(vctxt, elemDecl->value, typeDef, 0); */
12831 if (ret < 0) {
12832 xmlSchemaPErr(pctxt, node,
12833 /* NOTNICE: error code: This function will be used during
12834 * schema construction and xsi:type validation.
12835 */
12836 XML_SCHEMAP_INTERNAL,
12837 "Internal error: xmlSchemaCheckCOSValidDefault, "
12838 "while validating a value constaint value.\n",
12839 NULL, NULL);
12840
12841 }
12842 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +000012843}
12844
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012845#if 0 /* Not yet used code for CT schema validation */
William M. Brack2f2a6632004-08-20 23:09:47 +000012846/**
12847 * xmlSchemaGetSTContentOfCT:
12848 * @ctxt: the schema parser context
12849 * @type: the complex type definition
12850 *
12851 *
12852 * Returns the corresponding simple type for the content of
12853 * the complex type.
12854 */
12855static xmlSchemaTypePtr
12856xmlSchemaGetSTContentOfCT(xmlSchemaParserCtxtPtr ctxt,
12857 xmlSchemaTypePtr type)
12858{
12859 xmlSchemaTypePtr orig = type, anyType;
12860
12861 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
12862 while ((type != NULL) && (type != anyType) &&
12863 (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
12864 if (type->type == XML_SCHEMA_TYPE_SIMPLE)
12865 return(type);
12866 type = type->baseType;
12867 }
12868 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012869 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000012870 NULL, orig, NULL,
12871 "Internal error: xmlSchemaGetSTContentTypeOfCT, "
12872 "no simple type for the content of complex type '%s' could be "
12873 "computed", orig->name);
12874 return (NULL);
12875}
12876
12877
William M. Brack2f2a6632004-08-20 23:09:47 +000012878
William M. Brack2f2a6632004-08-20 23:09:47 +000012879
12880/**
12881 * xmlSchemaCheckCOSCTExtends:
12882 * @ctxt: the schema parser context
12883 * @type: the complex type definition
12884 *
12885 * Schema Component Constraint: Derivation Valid (Extension)
12886 *
12887 * Returns 0 if the constraints are satisfied, a positive
12888 * error code if not and -1 if an internal error occured.
12889 */
12890static int
12891xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
12892 xmlSchemaTypePtr type)
12893{
12894 xmlSchemaTypePtr base;
12895 /*
12896 * 1 If the {base type definition} is a complex type definition,
12897 * then all of the following must be true:
12898 */
12899 base = type->baseType;
12900 if (base == NULL) {
12901 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012902 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000012903 NULL, type, NULL,
12904 "Internal error: xmlSchemaCheckCOSCTExtends, "
12905 "the complex type '%s' has no base type", type->name);
12906 return (-1);
12907 }
12908 if (base->type == XML_SCHEMA_TYPE_COMPLEX) {
12909 /*
12910 * 1.1 The {final} of the {base type definition} must not
12911 * contain extension.
12912 */
12913 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
12914 xmlSchemaPCustomErr(ctxt,
12915 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
12916 NULL, type, NULL,
12917 "The 'final' of the base type definition "
12918 "contains extension", NULL);
12919 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
12920 }
12921 /*
12922 * 1.2 Its {attribute uses} must be a subset of the {attribute uses}
12923 * of the complex type definition itself, that is, for every attribute
12924 * use in the {attribute uses} of the {base type definition}, there
12925 * must be an attribute use in the {attribute uses} of the complex
12926 * type definition itself whose {attribute declaration} has the same
12927 * {name}, {target namespace} and {type definition} as its attribute
12928 * declaration
12929 *
12930 * NOTE: This will be already satisfied by the way the attribute uses
12931 * are extended in xmlSchemaBuildAttributeValidation; thus this check
12932 * is not needed.
12933 */
12934
12935 /*
12936 * 1.3 If it has an {attribute wildcard}, the complex type definition
12937 * must also have one, and the base type definition's {attribute
12938 * wildcard}'s {namespace constraint} must be a subset of the complex
12939 * type definition's {attribute wildcard}'s {namespace constraint},
12940 * as defined by Wildcard Subset (§3.10.6).
12941 *
12942 * This is already checked in xmlSchemaBuildAttributeValidation; thus
12943 * this check is not needed.
12944 */
12945
12946 /*
12947 * 1.4 One of the following must be true:
12948 *
12949 * 1.4.1 The {content type} of the {base type definition} and the
12950 * {content type} of the complex type definition itself must be the same
12951 * simple type definition
12952 */
12953
12954
12955
12956 } else {
12957 /*
12958 * 2 If the {base type definition} is a simple type definition,
12959 * then all of the following must be true:
12960 */
12961 /*
12962 * 2.1 The {content type} must be the same simple type definition.
12963 */
12964 /*
12965 * 2.2 The {final} of the {base type definition} must not contain
12966 * extension
12967 */
12968 }
12969
12970}
12971
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012972static int
12973xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
12974 xmlSchemaTypePtr type)
12975{
12976 xmlSchemaTypePtr base, content;
12977 int OK = 0;
12978
12979 /*
12980 * TODO: Adjust the error codes here, as I used
12981 * XML_SCHEMAP_SRC_CT_1 only yet.
12982 */
12983 /*
12984 * Schema Representation Constraint:
12985 * Complex Type Definition Representation OK
12986 */
12987 base = type->baseType;
12988 if (base == NULL) {
12989 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL, NULL, type, NULL,
12990 "Internal error: xmlSchemaCheckSRCCT, '%s', no base type",
12991 type->name);
12992 return (-1);
12993 }
12994
12995 if (type->subtypes != NULL) {
12996 if (type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
12997 if IS_COMPLEX_TYPE(base) {
12998 /*
12999 * 1 If the <complexContent> alternative is chosen, the type definition
13000 * ·resolved· to by the ·actual value· of the base [attribute]
13001 * must be a complex type definition;
13002 */
13003 xmlSchemaPCustomErr(ctxt,
13004 XML_SCHEMAP_SRC_CT_1,
13005 NULL, type, NULL,
13006 "The base type is not a complex type", NULL);
13007 return (XML_SCHEMAP_SRC_CT_1);
13008 }
13009 } else if (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
13010
13011 if IS_SIMPLE_TYPE(base) {
13012 if (type->flags &
13013 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
13014 /*
13015 * 2.1.3 only if the <extension> alternative is also
13016 * chosen, a simple type definition.
13017 */
13018 /* TODO: Change error code to ..._SRC_CT_2_1_3. */
13019 xmlSchemaPCustomErr(ctxt,
13020 XML_SCHEMAP_SRC_CT_1,
13021 NULL, type, NULL,
13022 "A complex type (simple content) cannot restrict "
13023 "an other simple type",
13024 NULL);
13025 return (XML_SCHEMAP_SRC_CT_1);
13026 }
13027 OK = 1;
13028
13029 } else { /* if IS_SIMPLE_TYPE(base) */
13030 if (base->contentType = XML_SCHEMA_CONTENT_MIXED) {
13031 /*
13032 * 2.1.2 only if the <restriction> alternative is also
13033 * chosen, a complex type definition whose {content type}
13034 * is mixed and a particle emptyable.
13035 */
13036 /*
13037 * FIXME TODO: Check for *empiable particle* is missing.
13038 */
13039 if ((type->flags &
13040 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) == 0) {
13041 xmlSchemaPCustomErr(ctxt,
13042 XML_SCHEMAP_SRC_CT_1,
13043 NULL, type, NULL,
13044 "A complex type (simple content) cannot "
13045 "extend an other complex type which has a "
13046 "content type of: 'mixed' and emptiable particle",
13047 NULL);
13048 return (XML_SCHEMAP_SRC_CT_1);
13049 }
13050 /*
13051 * NOTE: This will be fired as well, if the base type
13052 * is *'anyType'*.
13053 * NOTE: type->subtypes->subtypes will be the
13054 * <restriction> item.
13055 */
13056 if (type->subtypes->subtypes == NULL) {
13057 /* Yes, this is paranoid programming. */
13058 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
13059 NULL, type, NULL,
13060 "Internal error: xmlSchemaCheckSRCCT, "
13061 "'%s', <simpleContent> has no <restriction>",
13062 type->name);
13063 return (-1);
13064 }
13065 /*
13066 * 2.2 If clause 2.1.2 above is satisfied, then there
13067 * must be a <simpleType> among the [children] of
13068 * <restriction>.
13069 */
13070 if (type->subtypes->subtypes->type !=
13071 XML_SCHEMA_TYPE_SIMPLE) {
13072 /* TODO: Change error code to ..._SRC_CT_2_2. */
13073 xmlSchemaPCustomErr(ctxt,
13074 XML_SCHEMAP_SRC_CT_1,
13075 NULL, type, NULL,
13076 "A <simpleType> is expected among the children "
13077 "of <restriction>", NULL);
13078 return (XML_SCHEMAP_SRC_CT_1);
13079 }
13080 OK = 1;
13081 } else { /* if (base->contentType = XML_SCHEMA_CONTENT_MIXED)*/
13082 /*
13083 * 2.1.1 a complex type definition whose {content type} is a
13084 * simple type definition;
13085 */
13086 if (base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) {
13087 xmlSchemaPCustomErr(ctxt,
13088 XML_SCHEMAP_SRC_CT_1,
13089 NULL, type, NULL,
13090 "A complex type (simple content) cannot "
13091 "be derived from the complex type '%s'",
13092 base->name);
13093 return (XML_SCHEMAP_SRC_CT_1);
13094 }
13095 content = base->contentTypeDef;
13096 if (content == NULL) {
13097 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
13098 NULL, type, NULL,
13099 "Internal error: xmlSchemaCheckSRCCT, "
13100 "'%s', base type has no content type",
13101 type->name);
13102 return (-1);
13103 }
13104 if (content->type != XML_SCHEMA_TYPE_SIMPLE) {
13105 xmlSchemaPCustomErr(ctxt,
13106 XML_SCHEMAP_SRC_CT_1,
13107 NULL, type, NULL,
13108 "A complex type (simple content) cannot "
13109 "be derived from the complex type '%s'",
13110 base->name);
13111 return (XML_SCHEMAP_SRC_CT_1);
13112 }
13113 }
13114 }
13115 }
13116 }
13117 /*
13118 * TODO: 3 The corresponding complex type definition component must
13119 * satisfy the conditions set out in Constraints on Complex Type
13120 * Definition Schema Components (§3.4.6);
13121 *
13122 * TODO: 4 If clause 2.2.1 or clause 2.2.2 in the correspondence specification
13123 * above for {attribute wildcard} is satisfied, the intensional
13124 * intersection must be expressible, as defined in Attribute Wildcard
13125 * Intersection (§3.10.6).
13126 */
13127
13128}
William M. Brack2f2a6632004-08-20 23:09:47 +000013129#endif
13130
Daniel Veillard01fa6152004-06-29 17:04:39 +000013131/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013132 * xmlSchemaGroupDefFixup:
13133 * @typeDecl: the schema model group definition
13134 * @ctxt: the schema parser context
13135 *
13136 * Fixes model group definitions.
13137 */
13138static void
13139xmlSchemaGroupDefFixup(xmlSchemaTypePtr group,
13140 xmlSchemaParserCtxtPtr ctxt,
13141 const xmlChar * name ATTRIBUTE_UNUSED)
13142{
13143 group->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
13144 if ((group->ref != NULL) && (group->subtypes == NULL)) {
13145 xmlSchemaTypePtr groupDef;
13146 /*
13147 * Resolve the reference.
13148 */
13149 groupDef = xmlSchemaGetGroup(ctxt->schema, group->ref,
13150 group->refNs);
13151 if (groupDef == NULL) {
13152 xmlSchemaPResCompAttrErr(ctxt,
13153 XML_SCHEMAP_SRC_RESOLVE,
13154 NULL, group, NULL,
13155 "ref", group->ref, group->refNs,
13156 XML_SCHEMA_TYPE_GROUP, NULL);
13157 return;
13158 }
13159 group->subtypes = groupDef;
13160 }
13161}
13162
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013163#if 0 /* Enable when the content type will be computed. */
13164static int
13165xmlSchemaComputeContentType(xmlSchemaParserCtxtPtr ctxt,
13166 xmlSchemaTypePtr type)
13167{
13168 xmlSchemaTypePtr base, res = NULL;
13169
13170 base = type->baseType;
13171 if (base == NULL) {
13172 xmlSchemaPCustomErr(ctxt,
13173 XML_SCHEMAP_INTERNAL,
13174 NULL, type, NULL,
13175 "Internal error: xmlSchemaGetContentType, "
13176 "the complex type '%s' has no base type", type->name);
13177 return (-1);
13178 }
13179 if (IS_ANYTYPE(base) || (type->subtypes->type ==
13180 XML_SCHEMA_TYPE_COMPLEX_CONTENT)) {
13181 xmlSchemaTypePtr start;
13182 /*
13183 * Effective 'mixed'.
13184 */
13185 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
13186 type->contentType = XML_SCHEMA_CONTENT_MIXED;
13187 /*
13188 * Effective content.
13189 */
13190 if (IS_ANYTYPE(base))
13191 start = type;
13192 else
13193 start = type->subtypes;
13194
13195 } else { /* if XML_SCHEMA_TYPE_COMPLEX_CONTENT */
13196 xmlSchemaTypePtr baseContentItem;
13197
13198 /*
13199 * Complex type with simple content.
13200 */
13201 if IS_COMPLEX_TYPE(base) {
13202 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
13203 /*
13204 * Summary: a complex type (simple content) can *restrict*
13205 * a complex type with the following content type:
13206 * 1. 'mixed' and an emptiable particle
13207 * 2. simple type
13208 */
13209 if (base->contentType == XML_SCHEMA_CONTENT_MIXED) {
13210 /*
13211 * 2 if the {content type} of the base type is mixed and a
13212 * particle which is ·emptiable·,
13213 * [...]
13214 * then starting from the simple type definition
13215 * corresponding to the <simpleType> among the [children]
13216 * of <restriction> (**which must be present**)
13217 *
13218 * FIXME TODO: Handle "emptiable particle".
13219 */
13220 res = type->subtypes->subtypes;
13221 if (res == NULL) {
13222 xmlSchemaPCustomErr(ctxt,
13223 XML_SCHEMAP_INTERNAL,
13224 NULL, type, NULL,
13225 "Internal error: xmlSchemaGetContentType, "
13226 "CT '%s' (restricting): <simpleContent> has no "
13227 "<restriction>",
13228 type->name);
13229 return (-1);
13230 }
13231
13232 res->subtypes;
13233 if (res == NULL) {
13234 xmlSchemaPCustomErr(ctxt,
13235 XML_SCHEMAP_INTERNAL,
13236 NULL, type, NULL,
13237 "Internal error: xmlSchemaGetContentType, "
13238 "CT '%s' (restricting): <restriction> has no "
13239 "mandatory <simpleType>",
13240 type->name);
13241 return (-1);
13242 }
13243 } else {
13244 baseContentItem = base->contentTypeDef;
13245 if (baseContentItem == NULL) {
13246 xmlSchemaPCustomErr(ctxt,
13247 XML_SCHEMAP_INTERNAL,
13248 NULL, type, NULL,
13249 "Internal error: xmlSchemaGetContentType, "
13250 "CT '%s' (restricting), the base type has no "
13251 "content type", type->name);
13252 return (-1);
13253 }
13254 if IS_SIMPLE_TYPE(baseContentItem) {
13255 /*
13256 * 1 If the base type is a complex type whose own
13257 * {content type} is a simple type and the <restriction>
13258 * alternative is chosen
13259 */
13260 /* type->subtypes->subtypes will be the restriction item.*/
13261 res = type->subtypes->subtypes;
13262 if (res == NULL) {
13263 xmlSchemaPCustomErr(ctxt,
13264 XML_SCHEMAP_INTERNAL,
13265 NULL, type, NULL,
13266 "Internal error: xmlSchemaGetContentType, "
13267 "CT '%s' (restricting): <simpleType> has no "
13268 "<restriction>", type->name);
13269 return (-1);
13270 }
13271 /*
13272 * 1.1 the simple type definition corresponding to the
13273 * <simpleType> among the [children] of <restriction>if
13274 * there is one;
13275 */
13276 res = res->subtypes;
13277 if (res == NULL) {
13278 /*
13279 * 1.2 otherwise the {content type}
13280 * of the base type .
13281 */
13282 res = baseContentItem;
13283 }
13284 }
13285 }
13286 /*
13287 * SPECIAL TODO: If *restricting* the spec wants us to
13288 * create an *additional* simple type which restricts the
13289 * located simple type; we won't do this yet, and look how
13290 * far we get with it.
13291 */
13292 } else { /* if XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION */
13293 /*
13294 * Summary: a complex type (simple content) can *extend*
13295 * only a complex base with a simple type as content.
13296 */
13297 /*
13298 * 3 If the type definition ·resolved· to by the ·actual
13299 * value· of the base [attribute] is a complex type
13300 * definition (whose own {content type} *must be* a simple
13301 * type definition, see below) and the *<extension>*
13302 * alternative is chosen, then the {content type} of that
13303 * complex type definition;
13304 */
13305 res = base->contentTypeDef;
13306 if (res == NULL) {
13307 xmlSchemaPCustomErr(ctxt,
13308 XML_SCHEMAP_INTERNAL,
13309 NULL, type, NULL,
13310 "Internal error: xmlSchemaGetContentType, "
13311 "CT '%s' (extending), the base type has no content "
13312 "type", type->name);
13313 return (-1);
13314 }
13315 if (! IS_SIMPLE_TYPE(res)) {
13316 xmlSchemaPCustomErr(ctxt,
13317 XML_SCHEMAP_INTERNAL,
13318 NULL, type, NULL,
13319 "Internal error: xmlSchemaGetContentType, "
13320 "CT '%s' (extending), the content type of the "
13321 "base is not a simple type", type->name);
13322 return (-1);
13323 }
13324 }
13325 } else /* if IS_COMPLEX_TYPE(base) */
13326 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
13327 /*
13328 * 4 otherwise (the type definition ·resolved· to by the
13329 * ·actual value· of the base [attribute] is a simple type
13330 * definition and the <extension> alternative is chosen),
13331 * then that simple type definition.
13332 */
13333 res = base;
13334 }
13335 type->contentTypeDef = res;
13336 if (res == NULL) {
13337 xmlSchemaPCustomErr(ctxt,
13338 XML_SCHEMAP_INTERNAL,
13339 NULL, type, NULL,
13340 "Internal error: xmlSchemaGetContentType, "
13341 "'%s', the content type could not be determined",
13342 type->name);
13343 return (-1);
13344 }
13345
13346 }
13347
13348}
13349#endif
13350
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013351/**
Daniel Veillard4255d502002-04-16 15:50:10 +000013352 * xmlSchemaTypeFixup:
13353 * @typeDecl: the schema type definition
13354 * @ctxt: the schema parser context
13355 *
13356 * Fixes the content model of the type.
13357 */
13358static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013359xmlSchemaTypeFixup(xmlSchemaTypePtr item,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013360 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000013361{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013362 xmlSchemaTypePtr ctxtType;
13363
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013364 if (item == NULL)
Daniel Veillard82bbbd42003-05-11 20:16:09 +000013365 return;
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013366 /*
13367 * Do not allow the following types to be typefixed, prior to
13368 * the corresponding simple/complex types.
13369 */
13370 if (ctxt->ctxtType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013371 switch (item->type) {
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013372 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
13373 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
13374 case XML_SCHEMA_TYPE_UNION:
13375 case XML_SCHEMA_TYPE_RESTRICTION:
13376 case XML_SCHEMA_TYPE_EXTENSION:
13377 return;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013378 default:
13379 break;
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013380 }
13381 }
Daniel Veillard4255d502002-04-16 15:50:10 +000013382 if (name == NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013383 name = item->name;
13384 if (item->contentType == XML_SCHEMA_CONTENT_UNKNOWN) {
13385 switch (item->type) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013386 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013387 if (item->subtypes != NULL) {
13388 if (item->subtypes->contentType ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013389 XML_SCHEMA_CONTENT_UNKNOWN) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013390 xmlSchemaTypeFixup(item->subtypes, ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013391 NULL);
13392 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013393 item->contentType =
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013394 XML_SCHEMA_CONTENT_SIMPLE;
13395 /* item->subtypes->contentType; */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013396 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013397 break;
13398 }
13399 case XML_SCHEMA_TYPE_RESTRICTION:{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013400 xmlSchemaTypePtr base = NULL;
13401
13402 ctxt->ctxtType->flags |=
13403 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013404 if (item->baseType != NULL)
13405 base = item->baseType;
13406 else if (item->base != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013407 base =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013408 xmlSchemaGetType(ctxt->schema, item->base,
13409 item->baseNs);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013410 if (base == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013411 xmlSchemaPResCompAttrErr(ctxt,
13412 XML_SCHEMAP_SRC_RESOLVE,
William M. Brack2f2a6632004-08-20 23:09:47 +000013413 NULL, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013414 (xmlNodePtr) xmlSchemaGetPropNode(item->node, "base"),
13415 "base", item->base, item->baseNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013416 XML_SCHEMA_TYPE_BASIC, "type definition");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013417 } else if (base->contentType ==
Daniel Veillard3646d642004-06-02 19:19:14 +000013418 XML_SCHEMA_CONTENT_UNKNOWN) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013419 xmlSchemaTypeFixup(base, ctxt, NULL);
13420 }
William M. Brack2f2a6632004-08-20 23:09:47 +000013421 }
13422 ctxt->ctxtType->baseType = base;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013423 if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX) {
13424 /*
13425 * ComplexType restriction.
William M. Brack2f2a6632004-08-20 23:09:47 +000013426 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013427 /*
13428 * Content type.
13429 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013430 if (item->subtypes == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013431 /* 1.1.1 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013432 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
13433 else if ((item->subtypes->subtypes == NULL) &&
13434 ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013435 XML_SCHEMA_TYPE_ALL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013436 || (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013437 XML_SCHEMA_TYPE_SEQUENCE)))
13438 /* 1.1.2 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013439 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
13440 else if ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013441 XML_SCHEMA_TYPE_CHOICE)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013442 && (item->subtypes->subtypes == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +000013443 /* 1.1.3 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013444 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013445 else {
13446 /* 1.2 and 2.X are applied at the other layer */
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 } else {
13451 /*
13452 * SimpleType restriction.
13453 */
William M. Brack2f2a6632004-08-20 23:09:47 +000013454 /* TODO: Nothing? */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013455 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013456 break;
13457 }
13458 case XML_SCHEMA_TYPE_EXTENSION:{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013459 xmlSchemaTypePtr base = NULL;
13460 xmlSchemaContentType explicitContentType;
13461
13462 /*
13463 * An extension does exist on a complexType only.
13464 */
13465 ctxt->ctxtType->flags |=
13466 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013467 if (item->recurse) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013468 /* TODO: The word "recursive" should be changed to "circular" here. */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013469 xmlSchemaPCustomErr(ctxt,
13470 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013471 NULL, item, item->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013472 "This item is circular", NULL);
Daniel Veillard2582a332004-04-18 19:49:46 +000013473 return;
13474 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013475 if (item->base != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013476 base =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013477 xmlSchemaGetType(ctxt->schema, item->base,
13478 item->baseNs);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013479 if (base == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013480 xmlSchemaPResCompAttrErr(ctxt,
13481 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013482 NULL, item, item->node,
13483 "base", item->base, item->baseNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013484 XML_SCHEMA_TYPE_BASIC, "type definition");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013485 } else if (base->contentType ==
13486 XML_SCHEMA_CONTENT_UNKNOWN) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013487 item->recurse = 1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013488 xmlSchemaTypeFixup(base, ctxt, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013489 item->recurse = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013490 }
13491 /*
13492 * The type definition ·resolved· to by the ·actual
13493 * value· of the base [attribute]
13494 */
13495 ctxt->ctxtType->baseType = base;
13496 /*
13497 * TODO: This one is still needed for computation of
13498 * the content model by xmlSchemaBuildAContentModel.
13499 * Try to get rid of it.
13500 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013501 item->baseType = base;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013502 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013503 if ((item->subtypes != NULL) &&
13504 (item->subtypes->contentType == XML_SCHEMA_CONTENT_UNKNOWN))
13505 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013506
13507 explicitContentType = XML_SCHEMA_CONTENT_ELEMENTS;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013508 if (item->subtypes == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013509 /* 1.1.1 */
13510 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013511 else if ((item->subtypes->subtypes == NULL) &&
13512 ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013513 XML_SCHEMA_TYPE_ALL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013514 || (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013515 XML_SCHEMA_TYPE_SEQUENCE)))
13516 /* 1.1.2 */
13517 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013518 else if ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013519 XML_SCHEMA_TYPE_CHOICE)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013520 && (item->subtypes->subtypes == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +000013521 /* 1.1.3 */
13522 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
13523 if (base != NULL) {
13524 /* It will be reported later, if the base is missing. */
13525 if (explicitContentType == XML_SCHEMA_CONTENT_EMPTY) {
13526 /* 2.1 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013527 item->contentType = base->contentType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013528 } else if (base->contentType ==
13529 XML_SCHEMA_CONTENT_EMPTY) {
13530 /* 2.2 imbitable ! */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013531 item->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000013532 XML_SCHEMA_CONTENT_ELEMENTS;
13533 } else {
13534 /* 2.3 imbitable pareil ! */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013535 item->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000013536 XML_SCHEMA_CONTENT_ELEMENTS;
13537 }
13538 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013539 break;
13540 }
13541 case XML_SCHEMA_TYPE_COMPLEX:{
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013542 ctxtType = ctxt->ctxtType;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013543 ctxt->ctxtType = item;
13544 /*
13545 * Start with an empty content-type type.
13546 */
13547 if (item->subtypes == NULL)
13548 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
13549
13550 if ((item->subtypes == NULL) ||
13551 ((item->subtypes->type !=
Daniel Veillard01fa6152004-06-29 17:04:39 +000013552 XML_SCHEMA_TYPE_SIMPLE_CONTENT) &&
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013553 (item->subtypes->type !=
Daniel Veillard01fa6152004-06-29 17:04:39 +000013554 XML_SCHEMA_TYPE_COMPLEX_CONTENT))) {
13555 /*
13556 * This case is understood as shorthand for complex
13557 * content restricting the ur-type definition, and
13558 * the details of the mappings should be modified as
13559 * necessary.
13560 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013561 item->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
13562 item->flags |=
Daniel Veillard01fa6152004-06-29 17:04:39 +000013563 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013564 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013565 * Assume that we inherit the content-type type
13566 * from 'anyType', which is 'mixed' and a particle
13567 * emptiable.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013568 */
13569 item->contentType = item->baseType->contentType;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013570 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013571 /*
13572 * Fixup the sub components.
13573 */
13574 if ((item->subtypes != NULL) &&
13575 (item->subtypes->contentType ==
13576 XML_SCHEMA_CONTENT_UNKNOWN)) {
13577 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013578 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013579 if (item->flags & XML_SCHEMAS_TYPE_MIXED) {
13580 item->contentType = XML_SCHEMA_CONTENT_MIXED;
13581 } else if (item->subtypes != NULL) {
13582 /*
13583 * Use the content-type type of the model groups
13584 * defined, if 'mixed' is not set. If 'mixed' is set
13585 * it will expand the content-type by allowing character
13586 * content to appear.
13587 */
13588 item->contentType =
13589 item->subtypes->contentType;
13590 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013591
13592 /*
13593 * Some optimization for validation:
13594 * If there are no facets beside the "whitespace" facet,
13595 * then a value needs not to checked against against a
13596 * facet, thus no computed value is needed.
13597 * TODO URGENT: This is just a workaround, we need to
13598 * introduce the correct usage of contentType to store the
13599 * facets in!
13600 */
Daniel Veillardd3210bc2005-01-28 17:56:39 +000013601 if ((item->baseType != NULL) &&
13602 (item->baseType->flags &
13603 XML_SCHEMAS_TYPE_FACETSNEEDVALUE))
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013604 item->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
13605 else {
13606 xmlSchemaFacetLinkPtr cur;
13607
13608 for (cur = item->facetSet; cur != NULL;
13609 cur = cur->next) {
13610 if (cur->facet->type != XML_SCHEMA_FACET_WHITESPACE) {
13611 item->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
13612 break;
13613 }
13614 }
13615 }
13616
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013617 xmlSchemaBuildAttributeValidation(ctxt, item);
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000013618 xmlSchemaCheckDefaults(item, ctxt, item->name);
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013619 ctxt->ctxtType = ctxtType;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013620 break;
13621 }
13622 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013623 if (item->subtypes == NULL) {
13624 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
13625 if (item->flags & XML_SCHEMAS_TYPE_MIXED)
13626 item->contentType =
Daniel Veillard1aefc862004-03-04 11:40:48 +000013627 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013628 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013629 if (item->flags & XML_SCHEMAS_TYPE_MIXED) {
13630 item->contentType =
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013631 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillard3646d642004-06-02 19:19:14 +000013632 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013633 xmlSchemaTypeFixup(item->subtypes, ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013634 NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013635 if (item->subtypes != NULL)
13636 item->contentType =
13637 item->subtypes->contentType;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013638 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013639 /*
13640 * Removed due to implementation of the build of attribute uses.
13641 */
13642 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013643 if (item->attributes == NULL)
13644 item->attributes =
13645 item->subtypes->attributes;
Daniel Veillard3646d642004-06-02 19:19:14 +000013646 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013647 }
13648 break;
13649 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013650 case XML_SCHEMA_TYPE_SIMPLE:
13651 /*
13652 * Simple Type Definition Schema Component
13653 *
13654 */
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013655 ctxtType = ctxt->ctxtType;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013656 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
13657 if (item->subtypes->contentType ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013658 XML_SCHEMA_CONTENT_UNKNOWN) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013659 ctxt->ctxtType = item;
13660 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013661 }
13662 /* Fixup base type */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013663 if ((item->baseType != NULL) &&
13664 (item->baseType->contentType ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013665 XML_SCHEMA_CONTENT_UNKNOWN)) {
13666 /* OPTIMIZE: Actually this one will never by hit, since
13667 * the base type is already type-fixed in <restriction>.
13668 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013669 ctxt->ctxtType = item;
13670 xmlSchemaTypeFixup(item->baseType, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013671 }
13672 /* Base type:
13673 * 2 If the <list> or <union> alternative is chosen,
13674 * then the ·simple ur-type definition·.
13675 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013676 if (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013677 XML_SCHEMA_TYPE_LIST) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013678 item->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
13679 item->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
13680 } else if (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013681 XML_SCHEMA_TYPE_UNION) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013682 item->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
13683 item->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
13684 } else if (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013685 XML_SCHEMA_TYPE_RESTRICTION) {
13686 xmlSchemaFacetLinkPtr facet, cur, last = NULL;
13687
13688 /*
13689 * Variety
13690 * If the <restriction> alternative is chosen, then the
13691 * {variety} of the {base type definition}.
13692 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013693 if (item->baseType != NULL) {
13694 if (item->baseType->flags &
Daniel Veillard01fa6152004-06-29 17:04:39 +000013695 XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013696 item->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
13697 else if (item->baseType->flags &
Daniel Veillard01fa6152004-06-29 17:04:39 +000013698 XML_SCHEMAS_TYPE_VARIETY_LIST)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013699 item->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
13700 else if (item->baseType->flags &
Daniel Veillard01fa6152004-06-29 17:04:39 +000013701 XML_SCHEMAS_TYPE_VARIETY_UNION)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013702 item->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013703 /*
13704 * Schema Component Constraint: Simple Type Restriction
13705 * (Facets)
13706 * NOTE: Satisfaction of 1 and 2 arise from the fixup
13707 * applied beforehand.
13708 *
13709 * 3 The {facets} of R are the union of S and the {facets}
13710 * of B, eliminating duplicates. To eliminate duplicates,
13711 * when a facet of the same kind occurs in both S and the
13712 * {facets} of B, the one in the {facets} of B is not
13713 * included, with the exception of enumeration and pattern
13714 * facets, for which multiple occurrences with distinct values
13715 * are allowed.
13716 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013717 if (item->baseType->facetSet != NULL) {
13718 last = item->facetSet;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013719 if (last != NULL)
13720 while (last->next != NULL)
13721 last = last->next;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013722 cur = item->baseType->facetSet;
13723 for (; cur != NULL; cur = cur->next) {
13724 /*
13725 * Base patterns won't be add here:
13726 * they are ORed in a type and
13727 * ANDed in derived types. This will
13728 * happed at validation level by
13729 * walking the base axis of the type.
13730 */
13731 if (cur->facet->type ==
13732 XML_SCHEMA_FACET_PATTERN)
13733 continue;
13734 facet = NULL;
13735 if ((item->facetSet != NULL) &&
13736 /* REMOVED: a check for
13737 * XML_SCHEMA_FACET_PATTERN was already
13738 * performed above.
13739
13740 * (cur->facet->type !=
13741 * XML_SCHEMA_FACET_PATTERN) &&
Daniel Veillard01fa6152004-06-29 17:04:39 +000013742 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013743 (cur->facet->type !=
13744 XML_SCHEMA_FACET_ENUMERATION)) {
13745 facet = item->facetSet;
13746 do {
13747 if (cur->facet->type ==
13748 facet->facet->type)
13749 break;
13750 facet = facet->next;
13751 } while (facet != NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013752 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013753 if (facet == NULL) {
13754 facet = (xmlSchemaFacetLinkPtr)
13755 xmlMalloc(sizeof(xmlSchemaFacetLink));
13756 if (facet == NULL) {
13757 xmlSchemaPErrMemory(ctxt,
13758 "fixing simpleType", NULL);
13759 return;
13760 }
13761 /*
13762 * The facets are not copied but referenced
13763 * via the facet link.
13764 */
13765 facet->facet = cur->facet;
13766 facet->next = NULL;
13767 if (last == NULL)
13768 item->facetSet = facet;
13769 else
13770 last->next = facet;
13771 last = facet;
13772 }
13773 }
13774 }
13775 /*
13776 * Some optimization for validation:
13777 * If there are no facets beside the "whitespace" facet,
13778 * then a value needs not to checked against against a
13779 * facet, thus no computed value is needed.
13780 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000013781 if (item->baseType->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013782 item->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
13783 else {
13784 for (cur = item->facetSet; cur != NULL;
13785 cur = cur->next) {
13786 if (cur->facet->type != XML_SCHEMA_FACET_WHITESPACE) {
13787 item->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
13788 break;
13789 }
13790 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013791 }
13792 }
13793 }
13794 /*
13795 * Check constraints.
13796 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013797 xmlSchemaCheckSRCSimpleType(ctxt, item);
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000013798 xmlSchemaCheckDefaults(item, ctxt, item->name);
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013799 ctxt->ctxtType = ctxtType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013800 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013801 case XML_SCHEMA_TYPE_SEQUENCE:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013802 case XML_SCHEMA_TYPE_ALL:
13803 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013804 item->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013805 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013806 case XML_SCHEMA_TYPE_GROUP:
13807 /*
13808 * TODO: Handling was moved to xmlSchemaGroupDefFixup.
13809 */
13810 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013811 case XML_SCHEMA_TYPE_LIST:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013812 xmlSchemaParseListRefFixup(item, ctxt);
13813 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013814 break;
13815 case XML_SCHEMA_TYPE_UNION:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013816 xmlSchemaParseUnionRefCheck(item, ctxt);
13817 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013818 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013819 case XML_SCHEMA_TYPE_BASIC:
13820 case XML_SCHEMA_TYPE_ANY:
13821 case XML_SCHEMA_TYPE_FACET:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013822 case XML_SCHEMA_TYPE_UR:
13823 case XML_SCHEMA_TYPE_ELEMENT:
13824 case XML_SCHEMA_TYPE_ATTRIBUTE:
13825 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
William M. Brack29aa7722004-05-12 00:27:56 +000013826 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013827 case XML_SCHEMA_TYPE_NOTATION:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013828 case XML_SCHEMA_FACET_MININCLUSIVE:
13829 case XML_SCHEMA_FACET_MINEXCLUSIVE:
13830 case XML_SCHEMA_FACET_MAXINCLUSIVE:
13831 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
13832 case XML_SCHEMA_FACET_TOTALDIGITS:
13833 case XML_SCHEMA_FACET_FRACTIONDIGITS:
13834 case XML_SCHEMA_FACET_PATTERN:
13835 case XML_SCHEMA_FACET_ENUMERATION:
13836 case XML_SCHEMA_FACET_WHITESPACE:
13837 case XML_SCHEMA_FACET_LENGTH:
13838 case XML_SCHEMA_FACET_MAXLENGTH:
13839 case XML_SCHEMA_FACET_MINLENGTH:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013840 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
13841 if (item->subtypes != NULL)
13842 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013843 break;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000013844 case XML_SCHEMA_TYPE_IDC_UNIQUE:
13845 case XML_SCHEMA_TYPE_IDC_KEY:
13846 case XML_SCHEMA_TYPE_IDC_KEYREF:
13847 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013848 }
13849 }
Daniel Veillard8651f532002-04-17 09:06:27 +000013850#ifdef DEBUG_TYPE
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013851 if (item->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013852 xmlGenericError(xmlGenericErrorContext,
13853 "Type of %s : %s:%d :", name,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013854 item->node->doc->URL,
13855 xmlGetLineNo(item->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +000013856 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013857 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000013858 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013859 switch (item->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013860 case XML_SCHEMA_CONTENT_SIMPLE:
13861 xmlGenericError(xmlGenericErrorContext, "simple\n");
13862 break;
13863 case XML_SCHEMA_CONTENT_ELEMENTS:
13864 xmlGenericError(xmlGenericErrorContext, "elements\n");
13865 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000013866 case XML_SCHEMA_CONTENT_UNKNOWN:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013867 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
13868 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000013869 case XML_SCHEMA_CONTENT_EMPTY:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013870 xmlGenericError(xmlGenericErrorContext, "empty\n");
13871 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000013872 case XML_SCHEMA_CONTENT_MIXED:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013873 xmlGenericError(xmlGenericErrorContext, "mixed\n");
13874 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013875 /* Removed, since not used. */
13876 /*
Daniel Veillard8651f532002-04-17 09:06:27 +000013877 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013878 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
13879 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013880 */
Daniel Veillard8651f532002-04-17 09:06:27 +000013881 case XML_SCHEMA_CONTENT_BASIC:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013882 xmlGenericError(xmlGenericErrorContext, "basic\n");
13883 break;
13884 default:
13885 xmlGenericError(xmlGenericErrorContext,
13886 "not registered !!!\n");
13887 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000013888 }
13889#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000013890}
13891
13892/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000013893 * xmlSchemaCheckFacet:
13894 * @facet: the facet
13895 * @typeDecl: the schema type definition
13896 * @ctxt: the schema parser context or NULL
13897 * @name: name of the type
13898 *
13899 * Checks the default values types, especially for facets
13900 *
13901 * Returns 0 if okay or -1 in cae of error
13902 */
13903int
13904xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013905 xmlSchemaTypePtr typeDecl,
13906 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000013907{
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +000013908 xmlSchemaTypePtr nonNegativeIntegerType = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013909 int ret = 0, reuseValCtxt = 0;
13910
Daniel Veillardce682bc2004-11-05 17:22:25 +000013911 if ((facet == NULL) || (typeDecl == NULL))
13912 return(-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013913 /*
13914 * TODO: will the parser context be given if used from
13915 * the relaxNG module?
13916 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000013917
13918 if (nonNegativeIntegerType == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013919 nonNegativeIntegerType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000013920 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000013921 }
13922 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013923 case XML_SCHEMA_FACET_MININCLUSIVE:
13924 case XML_SCHEMA_FACET_MINEXCLUSIVE:
13925 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013926 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
13927 case XML_SCHEMA_FACET_ENUMERATION: {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013928 /*
13929 * Okay we need to validate the value
13930 * at that point.
13931 */
13932 xmlSchemaValidCtxtPtr vctxt;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013933 xmlSchemaTypePtr base;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013934
13935 /* 4.3.5.5 Constraints on enumeration Schema Components
13936 * Schema Component Constraint: enumeration valid restriction
13937 * It is an ·error· if any member of {value} is not in the
13938 * ·value space· of {base type definition}.
13939 *
13940 * minInclusive, maxInclusive, minExclusive, maxExclusive:
13941 * The value ·must· be in the
13942 * ·value space· of the ·base type·.
13943 */
13944 /*
13945 * This function is intended to deliver a compiled value
13946 * on the facet. In XML Schemas the type holding a facet,
13947 * cannot be a built-in type. Thus to ensure that other API
13948 * calls (relaxng) do work, if the given type is a built-in
13949 * type, we will assume that the given built-in type *is
13950 * already* the base type.
13951 */
13952 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
13953 base = typeDecl->baseType;
13954 if (base == NULL) {
13955 xmlSchemaPErr(ctxt, typeDecl->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013956 XML_SCHEMAP_INTERNAL,
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013957 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013958 "the type '%s' has no base type.\n",
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013959 typeDecl->name, NULL);
13960 return (-1);
13961 }
13962 } else
13963 base = typeDecl;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013964 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013965 * This avoids perseverative creation of the
13966 * validation context if a parser context is
13967 * used.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013968 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013969 if (ctxt != NULL) {
13970 reuseValCtxt = 1;
13971 if (ctxt->vctxt == NULL) {
13972 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
13973 return (-1);
13974 }
13975 vctxt = ctxt->vctxt;
13976 } else {
13977 vctxt = xmlSchemaNewValidCtxt(NULL);
13978 if (vctxt == NULL) {
13979 xmlSchemaPErr(ctxt, typeDecl->node,
13980 XML_SCHEMAP_INTERNAL,
13981 "Internal error: xmlSchemaCheckFacet, "
13982 "creating a new validation context.\n",
13983 NULL, NULL);
13984 return (-1);
13985 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013986 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013987
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013988 vctxt->node = facet->node;
13989 vctxt->cur = NULL;
13990 /*
13991 * NOTE: This call does not check the content nodes,
13992 * since they are not available:
13993 * facet->node is just the node holding the facet
13994 * definition, *not* the attribute holding the *value*
13995 * of the facet.
13996 */
13997 ret = xmlSchemaValidateSimpleTypeValue(vctxt, base,
13998 facet->value, 0, 1, 1, 0);
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013999 facet->val = vctxt->value;
14000 vctxt->value = NULL;
14001 if (ret > 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014002 /* error code */
14003 if (ctxt != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014004 xmlSchemaPErrExt(ctxt, facet->node,
14005 XML_SCHEMAP_INVALID_FACET,
14006 NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014007 "Type definition '%s': The value '%s' of the "
14008 "facet '%s' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000014009 name, facet->value,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014010 xmlSchemaFacetTypeToString(facet->type),
Daniel Veillard01fa6152004-06-29 17:04:39 +000014011 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014012 }
14013 ret = -1;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000014014 } else if (ret < 0) {
14015 xmlSchemaPErrExt(ctxt, facet->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014016 XML_SCHEMAP_INTERNAL,
Daniel Veillardf4b05d02004-07-05 13:10:37 +000014017 NULL, NULL, NULL,
14018 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000014019 "failed to validate the value '%s' name of the "
14020 "facet '%s' against the base type '%s'.\n",
Daniel Veillardf4b05d02004-07-05 13:10:37 +000014021 facet->value,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014022 xmlSchemaFacetTypeToString(facet->type),
Daniel Veillardf4b05d02004-07-05 13:10:37 +000014023 base->name, NULL, NULL);
14024 ret = -1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014025 }
14026 if (reuseValCtxt == 0)
14027 xmlSchemaFreeValidCtxt(vctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014028 break;
14029 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014030 case XML_SCHEMA_FACET_PATTERN:
14031 facet->regexp = xmlRegexpCompile(facet->value);
14032 if (facet->regexp == NULL) {
14033 xmlSchemaPErr(ctxt, typeDecl->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014034 XML_SCHEMAP_REGEXP_INVALID,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014035 "Type definition '%s': The value '%s' of the "
14036 "facet 'pattern' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000014037 name, facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014038 ret = -1;
14039 }
14040 break;
14041 case XML_SCHEMA_FACET_TOTALDIGITS:
14042 case XML_SCHEMA_FACET_FRACTIONDIGITS:
14043 case XML_SCHEMA_FACET_LENGTH:
14044 case XML_SCHEMA_FACET_MAXLENGTH:
14045 case XML_SCHEMA_FACET_MINLENGTH:{
14046 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000014047
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014048 tmp =
14049 xmlSchemaValidatePredefinedType(nonNegativeIntegerType,
14050 facet->value,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +000014051 &(facet->val));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014052 if (tmp != 0) {
14053 /* error code */
14054 if (ctxt != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014055 xmlSchemaPErrExt(ctxt, facet->node,
14056 XML_SCHEMAP_INVALID_FACET_VALUE,
14057 NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014058 "Type definition '%s': The value '%s' of the "
14059 "facet '%s' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000014060 name, facet->value,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014061 xmlSchemaFacetTypeToString(facet->type),
Daniel Veillard01fa6152004-06-29 17:04:39 +000014062 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014063 }
14064 ret = -1;
14065 }
14066 break;
14067 }
14068 case XML_SCHEMA_FACET_WHITESPACE:{
14069 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
14070 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
14071 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
14072 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
14073 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
14074 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
14075 } else {
14076 if (ctxt != NULL) {
14077 xmlSchemaPErr(ctxt, facet->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014078 XML_SCHEMAP_INVALID_WHITE_SPACE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014079 "Type definition '%s': The value '%s' of the "
14080 "facet 'whiteSpace' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000014081 name, facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014082 }
14083 ret = -1;
14084 }
14085 }
14086 default:
14087 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000014088 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014089 return (ret);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000014090}
14091
14092/**
Daniel Veillard4255d502002-04-16 15:50:10 +000014093 * xmlSchemaCheckDefaults:
14094 * @typeDecl: the schema type definition
14095 * @ctxt: the schema parser context
14096 *
14097 * Checks the default values types, especially for facets
14098 */
14099static void
14100xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014101 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000014102{
Daniel Veillard4255d502002-04-16 15:50:10 +000014103 if (name == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014104 name = typeDecl->name;
14105 /*
14106 * NOTE: It is intended to use the facets list, instead
14107 * of facetSet.
14108 */
14109 if (typeDecl->facets != NULL) {
14110 xmlSchemaFacetPtr facet = typeDecl->facets;
14111
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014112 /*
14113 * Temporarily assign the "schema" to the validation context
14114 * of the parser context. This is needed for NOTATION validation.
14115 */
14116 if (ctxt->vctxt == NULL) {
14117 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
14118 return;
14119 }
14120 ctxt->vctxt->schema = ctxt->schema;
14121
Daniel Veillard01fa6152004-06-29 17:04:39 +000014122 while (facet != NULL) {
14123 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
14124 facet = facet->next;
14125 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014126
14127 ctxt->vctxt->schema = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014128 }
Daniel Veillard4255d502002-04-16 15:50:10 +000014129}
14130
14131/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014132 * xmlSchemaGetCircModelGrDefRef:
14133 * @ctxtGr: the searched model group
14134 * @list: the list of model groups to be processed
14135 *
14136 * This one is intended to be used by
14137 * xmlSchemaCheckGroupDefCircular only.
14138 *
14139 * Returns the circular model group definition reference, otherwise NULL.
14140 */
14141static xmlSchemaTypePtr
14142xmlSchemaGetCircModelGrDefRef(xmlSchemaTypePtr ctxtGrDef,
14143 xmlSchemaTypePtr gr)
14144{
14145 xmlSchemaTypePtr circ = NULL;
14146 int marked;
14147 /*
14148 * We will search for an model group reference which
14149 * references the context model group definition.
14150 */
14151 while (gr != NULL) {
14152 if (((gr->type == XML_SCHEMA_TYPE_GROUP) ||
14153 (gr->type == XML_SCHEMA_TYPE_ALL) ||
14154 (gr->type == XML_SCHEMA_TYPE_SEQUENCE) ||
14155 (gr->type == XML_SCHEMA_TYPE_CHOICE)) &&
14156 (gr->subtypes != NULL)) {
14157 marked = 0;
14158 if ((gr->type == XML_SCHEMA_TYPE_GROUP) &&
14159 (gr->ref != NULL)) {
14160 if (gr->subtypes == ctxtGrDef)
14161 return (gr);
14162 else if (gr->subtypes->flags &
14163 XML_SCHEMAS_TYPE_MARKED) {
14164 gr = gr->next;
14165 continue;
14166 } else {
14167 /*
14168 * Mark to avoid infinite recursion on
14169 * circular references not yet examined.
14170 */
14171 gr->subtypes->flags |= XML_SCHEMAS_TYPE_MARKED;
14172 marked = 1;
14173 }
14174 if (gr->subtypes->subtypes != NULL)
14175 circ = xmlSchemaGetCircModelGrDefRef(ctxtGrDef,
14176 gr->subtypes->subtypes);
14177 /*
14178 * Unmark the visited model group definition.
14179 */
14180 if (marked)
14181 gr->subtypes->flags ^= XML_SCHEMAS_TYPE_MARKED;
14182 if (circ != NULL)
14183 return (circ);
14184 } else {
14185 circ = xmlSchemaGetCircModelGrDefRef(ctxtGrDef,
14186 (xmlSchemaTypePtr) gr->subtypes);
14187 if (circ != NULL)
14188 return (circ);
14189 }
14190
14191 }
14192 gr = gr->next;
14193 }
14194 return (NULL);
14195}
14196
14197/**
14198 * xmlSchemaCheckGroupDefCircular:
14199 * attrGr: the model group definition
14200 * @ctxt: the parser context
14201 * @name: the name
14202 *
14203 * Checks for circular references to model group definitions.
14204 */
14205static void
14206xmlSchemaCheckGroupDefCircular(xmlSchemaTypePtr modelGrDef,
14207 xmlSchemaParserCtxtPtr ctxt,
14208 const xmlChar * name ATTRIBUTE_UNUSED)
14209{
14210 /*
14211 * Schema Component Constraint: Model Group Correct
14212 * 2 Circular groups are disallowed. That is, within the {particles}
14213 * of a group there must not be at any depth a particle whose {term}
14214 * is the group itself.
14215 */
14216 /*
14217 * NOTE: "gr->subtypes" holds the referenced group.
14218 */
14219 if ((modelGrDef->type != XML_SCHEMA_TYPE_GROUP) ||
14220 ((modelGrDef->flags & XML_SCHEMAS_TYPE_GLOBAL) == 0) ||
14221 (modelGrDef->subtypes == NULL))
14222 return;
14223 else {
14224 xmlSchemaTypePtr circ;
14225
14226 circ = xmlSchemaGetCircModelGrDefRef(modelGrDef, modelGrDef->subtypes);
14227 if (circ != NULL) {
14228 /*
14229 * TODO: Report the referenced attr group as QName.
14230 */
14231 xmlSchemaPCustomErr(ctxt,
14232 XML_SCHEMAP_MG_PROPS_CORRECT_2,
14233 NULL, NULL, circ->node,
14234 "Circular reference to the model group definition '%s' "
14235 "defined", modelGrDef->name);
14236 /*
14237 * NOTE: We will cut the reference to avoid further
14238 * confusion of the processor.
14239 * TODO: SPEC: Does the spec define how to process here?
14240 */
14241 circ->subtypes = NULL;
14242 }
14243 }
14244}
14245
14246
14247/**
14248 * xmlSchemaGetCircAttrGrRef:
14249 * @ctxtGr: the searched attribute group
14250 * @attr: the current attribute list to be processed
14251 *
14252 * This one is intended to be used by
14253 * xmlSchemaCheckSRCAttributeGroupCircular only.
14254 *
14255 * Returns the circular attribute grou reference, otherwise NULL.
14256 */
14257static xmlSchemaAttributeGroupPtr
14258xmlSchemaGetCircAttrGrRef(xmlSchemaAttributeGroupPtr ctxtGr,
14259 xmlSchemaAttributePtr attr)
14260{
14261 xmlSchemaAttributeGroupPtr circ = NULL, gr;
14262 int marked;
14263 /*
14264 * We will search for an attribute group reference which
14265 * references the context attribute group.
14266 */
14267 while (attr != NULL) {
14268 marked = 0;
14269 if (attr->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
14270 gr = (xmlSchemaAttributeGroupPtr) attr;
14271 if (gr->refItem != NULL) {
14272 if (gr->refItem == ctxtGr)
14273 return (gr);
14274 else if (gr->refItem->flags &
14275 XML_SCHEMAS_ATTRGROUP_MARKED) {
14276 attr = attr->next;
14277 continue;
14278 } else {
14279 /*
14280 * Mark as visited to avoid infinite recursion on
14281 * circular references not yet examined.
14282 */
14283 gr->refItem->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
14284 marked = 1;
14285 }
14286 }
14287 if (gr->attributes != NULL)
14288 circ = xmlSchemaGetCircAttrGrRef(ctxtGr, gr->attributes);
14289 /*
14290 * Unmark the visited group's attributes.
14291 */
14292 if (marked)
14293 gr->refItem->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
14294 if (circ != NULL)
14295 return (circ);
14296 }
14297 attr = attr->next;
14298 }
14299 return (NULL);
14300}
14301
14302/**
14303 * xmlSchemaCheckSRCAttributeGroupCircular:
14304 * attrGr: the attribute group definition
14305 * @ctxt: the parser context
14306 * @name: the name
14307 *
14308 * Checks for circular references of attribute groups.
14309 */
14310static void
14311xmlSchemaCheckAttributeGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
14312 xmlSchemaParserCtxtPtr ctxt,
14313 const xmlChar * name ATTRIBUTE_UNUSED)
14314{
14315 /*
14316 * Schema Representation Constraint:
14317 * Attribute Group Definition Representation OK
14318 * 3 Circular group reference is disallowed outside <redefine>.
14319 * That is, unless this element information item's parent is
14320 * <redefine>, then among the [children], if any, there must
14321 * not be an <attributeGroup> with ref [attribute] which resolves
14322 * to the component corresponding to this <attributeGroup>. Indirect
14323 * circularity is also ruled out. That is, when QName resolution
14324 * (Schema Document) (§3.15.3) is applied to a ·QName· arising from
14325 * any <attributeGroup>s with a ref [attribute] among the [children],
14326 * it must not be the case that a ·QName· is encountered at any depth
14327 * which resolves to the component corresponding to this <attributeGroup>.
14328 */
14329 /*
14330 * Only global components can be referenced.
14331 */
14332 if (((attrGr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) == 0) ||
14333 (attrGr->attributes == NULL))
14334 return;
14335 else {
14336 xmlSchemaAttributeGroupPtr circ;
14337
14338 circ = xmlSchemaGetCircAttrGrRef(attrGr, attrGr->attributes);
14339 if (circ != NULL) {
14340 /*
14341 * TODO: Report the referenced attr group as QName.
14342 */
14343 xmlSchemaPCustomErr(ctxt,
14344 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
14345 NULL, NULL, circ->node,
14346 "Circular reference to the attribute group '%s' "
14347 "defined", attrGr->name);
14348 /*
14349 * NOTE: We will cut the reference to avoid further
14350 * confusion of the processor.
14351 * BADSPEC: The spec should define how to process in this case.
14352 */
14353 circ->attributes = NULL;
14354 circ->refItem = NULL;
14355 }
14356 }
14357}
14358
14359/**
Daniel Veillard13e04c62002-04-23 17:51:29 +000014360 * xmlSchemaAttrGrpFixup:
14361 * @attrgrpDecl: the schema attribute definition
14362 * @ctxt: the schema parser context
14363 * @name: the attribute name
14364 *
14365 * Fixes finish doing the computations on the attributes definitions
14366 */
14367static void
Daniel Veillard3646d642004-06-02 19:19:14 +000014368xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014369 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +000014370{
14371 if (name == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000014372 name = attrgrp->name;
14373 if (attrgrp->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014374 return;
Daniel Veillard3646d642004-06-02 19:19:14 +000014375 if (attrgrp->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014376 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +000014377
Daniel Veillardc0826a72004-08-10 14:17:33 +000014378 ref = xmlSchemaGetAttributeGroup(ctxt->schema, attrgrp->ref,
14379 attrgrp->refNs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014380 if (ref == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014381 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014382 XML_SCHEMAP_SRC_RESOLVE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014383 NULL, (xmlSchemaTypePtr) attrgrp, attrgrp->node,
14384 "ref", attrgrp->ref, attrgrp->refNs,
14385 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014386 return;
14387 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014388 attrgrp->refItem = ref;
14389 /*
14390 * Check for self reference!
14391 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014392 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000014393 attrgrp->attributes = ref->attributes;
14394 attrgrp->attributeWildcard = ref->attributeWildcard;
14395 }
Daniel Veillard13e04c62002-04-23 17:51:29 +000014396}
14397
14398/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014399 * xmlSchemaAttrCheckValConstr:
14400 * @item: an schema attribute declaration/use
14401 * @ctxt: a schema parser context
14402 * @name: the name of the attribute
14403 *
14404 * Validates the value constraints of an attribute declaration/use.
Daniel Veillard4255d502002-04-16 15:50:10 +000014405 *
14406 * Fixes finish doing the computations on the attributes definitions
14407 */
14408static void
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014409xmlSchemaCheckAttrValConstr(xmlSchemaAttributePtr item,
14410 xmlSchemaParserCtxtPtr ctxt,
14411 const xmlChar * name ATTRIBUTE_UNUSED)
14412{
14413
14414 /*
14415 * a-props-correct
14416 * Schema Component Constraint: Attribute Declaration Properties Correct
14417 *
14418 * 2 if there is a {value constraint}, the canonical lexical
14419 * representation of its value must be ·valid· with respect
14420 * to the {type definition} as defined in String Valid (§3.14.4).
14421 */
14422
14423 if (item->defValue != NULL) {
14424 int ret;
14425 xmlNodePtr node;
14426 xmlSchemaTypePtr type;
14427
14428 if (item->subtypes == NULL) {
14429 xmlSchemaPErr(ctxt, item->node,
14430 XML_SCHEMAP_INTERNAL,
14431 "Internal error: xmlSchemaCheckAttrValConstr, "
14432 "type is missing... skipping validation of "
14433 "value constraint", NULL, NULL);
14434 return;
14435 }
14436
14437 /*
14438 * TODO: Try to avoid creating a new context.
14439 * TODO: This all is not very performant.
14440 */
14441 type = item->subtypes;
14442 /*
14443 * Ensure there's validation context.
14444 */
14445 if (ctxt->vctxt == NULL) {
14446 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1) {
14447 xmlSchemaPErr(ctxt, item->node,
14448 XML_SCHEMAP_INTERNAL,
14449 "Internal error: xmlSchemaCheckAttrValConstr, "
14450 "creating a new validation context.\n",
14451 NULL, NULL);
14452 return;
14453 }
14454 }
14455
14456 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
14457 node = (xmlNodePtr) xmlHasProp(item->node, BAD_CAST "fixed");
14458 else
14459 node = (xmlNodePtr) xmlHasProp(item->node, BAD_CAST "default");
14460 ctxt->vctxt->node = node;
14461 ctxt->vctxt->cur = NULL;
14462 /*
14463 * NOTE: This call does not check the content nodes,
14464 * since they are not available:
14465 * facet->node is just the node holding the facet
14466 * definition, *not* the attribute holding the *value*
14467 * of the facet.
14468 */
14469 ret = xmlSchemaValidateSimpleTypeValue(ctxt->vctxt, type,
14470 item->defValue, 0, 1, 1, 0);
14471 if (ret == 0) {
14472 /*
14473 * Store the computed value.
14474 */
14475 item->defVal = ctxt->vctxt->value;
14476 ctxt->vctxt->value = NULL;
14477 } else if (ret > 0) {
14478 if (ctxt != NULL) {
14479 xmlSchemaPSimpleTypeErr(ctxt,
14480 XML_SCHEMAP_A_PROPS_CORRECT_2,
14481 NULL, NULL, node,
14482 type, NULL, item->defValue,
14483 NULL, NULL, NULL);
14484 }
14485 } else if (ret < 0) {
14486 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
14487 NULL, NULL, node,
14488 "Internal error: xmlSchemaAttrCheckValConstr, "
14489 "failed to validate the value constraint of the "
14490 "attribute decl/use against the type '%s'",
14491 type->name);
14492 }
14493 }
14494}
14495
14496#if 0 /* Not used yet. */
14497static int
14498xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
14499 xmlSchemaElementPtr edecl)
14500{
14501 /*
14502 * TODO: 1 The values of the properties of an element declaration must be as
14503 * described in the property tableau in The Element Declaration Schema
14504 * Component (§3.3.1), modulo the impact of Missing Sub-components (§5.3).
14505 */
14506 /*
14507 * 2 If there is a {value constraint}, the canonical lexical
14508 * representation of its value must be ·valid· with respect to the {type
14509 * definition} as defined in Element Default Valid (Immediate) (§3.3.6).
14510 *
14511 * NOTE: This is done in xmlSchemaCheckElemValConstr.
14512 */
14513 /*
14514 * 3 If there is a non-·absent· {substitution group affiliation},
14515 * then {scope} must be global.
14516 *
14517 * NOTE: This is done in xmlSchemaParseElement.
14518 * TODO: Move it to this layer here.
14519 */
14520 /*
14521 * TODO: 4 If there is a {substitution group affiliation}, the {type definition}
14522 * of the element declaration must be validly derived from the {type
14523 * definition} of the {substitution group affiliation}, given the value
14524 * of the {substitution group exclusions} of the {substitution group
14525 * affiliation}, as defined in Type Derivation OK (Complex) (§3.4.6)
14526 * (if the {type definition} is complex) or as defined in
14527 * Type Derivation OK (Simple) (§3.14.6) (if the {type definition} is
14528 * simple).
14529 */
14530 /*
14531 * TODO: 5 If the {type definition} or {type definition}'s {content type}
14532 * is or is derived from ID then there must not be a {value constraint}.
14533 * Note: The use of ID as a type definition for elements goes beyond
14534 * XML 1.0, and should be avoided if backwards compatibility is desired
14535 */
14536 /*
14537 * TODO: 6 Circular substitution groups are disallowed. That is, it must not
14538 * be possible to return to an element declaration by repeatedly following
14539 * the {substitution group affiliation} property.
14540 */
14541}
14542#endif
14543
14544/**
14545 * xmlSchemaCheckElemValConstr:
14546 * @item: an schema element declaration/particle
14547 * @ctxt: a schema parser context
14548 * @name: the name of the attribute
14549 *
14550 * Validates the value constraints of an element declaration.
14551 *
14552 * Fixes finish doing the computations on the element declarations.
14553 */
14554static void
14555xmlSchemaCheckElemValConstr(xmlSchemaElementPtr decl,
14556 xmlSchemaParserCtxtPtr ctxt,
14557 const xmlChar * name ATTRIBUTE_UNUSED)
14558{
14559 if (decl->value != NULL) {
14560 int ret;
14561 xmlNodePtr node = NULL;
14562 xmlSchemaTypePtr type;
14563
14564 /*
14565 * 2 If there is a {value constraint}, the canonical lexical
14566 * representation of its value must be ·valid· with respect to the {type
14567 * definition} as defined in Element Default Valid (Immediate) (§3.3.6).
14568 */
14569 if (decl->subtypes == NULL) {
14570 xmlSchemaPErr(ctxt, decl->node,
14571 XML_SCHEMAP_INTERNAL,
14572 "Internal error: xmlSchemaCheckElemValConstr, "
14573 "type is missing... skipping validation of "
14574 "the value constraint", NULL, NULL);
14575 return;
14576 }
14577 /*
14578 * Ensure there's a validation context.
14579 */
14580 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
14581 return;
14582
14583 type = decl->subtypes;
14584
14585 if (decl->node != NULL) {
14586 if (decl->flags & XML_SCHEMAS_ELEM_FIXED)
14587 node = (xmlNodePtr) xmlHasProp(decl->node, BAD_CAST "fixed");
14588 else
14589 node = (xmlNodePtr) xmlHasProp(decl->node, BAD_CAST "default");
14590 }
14591 ctxt->vctxt->node = node;
14592 ctxt->vctxt->cur = NULL;
14593 ret = xmlSchemaCheckCOSValidDefault(ctxt, ctxt->vctxt, type, decl->value,
14594 node);
14595 if (ret == 0) {
14596 /*
14597 * Consume the computed value.
14598 */
14599 decl->defVal = ctxt->vctxt->value;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000014600 ctxt->vctxt->value = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014601 } else if (ret < 0) {
14602 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
14603 NULL, NULL, node,
14604 "Internal error: xmlSchemaElemCheckValConstr, "
14605 "failed to validate the value constraint of the "
14606 "element declaration '%s'",
14607 decl->name);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000014608 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014609 }
14610}
14611
14612/**
14613 * xmlSchemaAttrFixup:
14614 * @item: an schema attribute declaration/use.
14615 * @ctxt: a schema parser context
14616 * @name: the name of the attribute
14617 *
14618 * Fixes finish doing the computations on attribute declarations/uses.
14619 */
14620static void
14621xmlSchemaAttrFixup(xmlSchemaAttributePtr item,
14622 xmlSchemaParserCtxtPtr ctxt,
14623 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000014624{
Daniel Veillardc0826a72004-08-10 14:17:33 +000014625 /*
14626 * TODO: If including this is done twice (!) for every attribute.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014627 * -> Hmm, check if this is still done.
Daniel Veillardc0826a72004-08-10 14:17:33 +000014628 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014629 /*
14630 * The simple type definition corresponding to the <simpleType> element
14631 * information item in the [children], if present, otherwise the simple
14632 * type definition ·resolved· to by the ·actual value· of the type
14633 * [attribute], if present, otherwise the ·simple ur-type definition·.
14634 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014635 if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
Daniel Veillardc0826a72004-08-10 14:17:33 +000014636 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014637 item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
14638 if (item->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014639 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014640 if (item->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014641 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000014642
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014643 type = xmlSchemaGetType(ctxt->schema, item->typeName,
14644 item->typeNs);
14645 if ((type == NULL) || (! IS_SIMPLE_TYPE(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014646 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014647 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014648 NULL, (xmlSchemaTypePtr) item, item->node,
14649 "type", item->typeName, item->typeNs,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014650 XML_SCHEMA_TYPE_SIMPLE, NULL);
14651 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014652 item->subtypes = type;
14653
14654 } else if (item->ref != NULL) {
14655 xmlSchemaAttributePtr decl;
Daniel Veillard4255d502002-04-16 15:50:10 +000014656
Daniel Veillardc0826a72004-08-10 14:17:33 +000014657 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014658 * We have an attribute use here; assign the referenced
14659 * attribute declaration.
14660 */
14661 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000014662 * TODO: Evaluate, what errors could occur if the declaration is not
14663 * found. It might be possible that the "typefixup" might crash if
14664 * no ref declaration was found.
14665 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014666 decl = xmlSchemaGetAttribute(ctxt->schema, item->ref, item->refNs);
14667 if (decl == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014668 xmlSchemaPResCompAttrErr(ctxt,
14669 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014670 NULL, (xmlSchemaTypePtr) item, item->node,
14671 "ref", item->ref, item->refNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014672 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014673 return;
14674 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014675 item->refDecl = decl;
14676 xmlSchemaAttrFixup(decl, ctxt, NULL);
14677
14678 item->subtypes = decl->subtypes;
14679 /*
14680 * Attribute Use Correct
14681 * au-props-correct.2: If the {attribute declaration} has a fixed
14682 * {value constraint}, then if the attribute use itself has a
14683 * {value constraint}, it must also be fixed and its value must match
14684 * that of the {attribute declaration}'s {value constraint}.
14685 */
14686 if ((decl->flags & XML_SCHEMAS_ATTR_FIXED) &&
14687 (item->defValue != NULL)) {
14688 if (((item->flags & XML_SCHEMAS_ATTR_FIXED) == 0) ||
14689 (!xmlStrEqual(item->defValue, decl->defValue))) {
14690 xmlSchemaPCustomErr(ctxt,
14691 XML_SCHEMAP_AU_PROPS_CORRECT_2,
14692 NULL, NULL, item->node,
14693 "The value constraint must be fixed "
14694 "and match the referenced attribute "
14695 "declarations's value constraint '%s'",
14696 decl->defValue);
14697 }
14698 /*
14699 * FUTURE: One should change the values of the attr. use
14700 * if ever validation should be attempted even if the
14701 * schema itself was not fully valid.
14702 */
14703 }
Daniel Veillard3646d642004-06-02 19:19:14 +000014704 } else {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014705 item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
14706 }
Daniel Veillard4255d502002-04-16 15:50:10 +000014707}
14708
14709/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000014710 * xmlSchemaResolveIDCKeyRef:
14711 * @idc: the identity-constraint definition
14712 * @ctxt: the schema parser context
14713 * @name: the attribute name
14714 *
14715 * Resolve keyRef references to key/unique IDCs.
14716 */
14717static void
14718xmlSchemaResolveIDCKeyRef(xmlSchemaIDCPtr idc,
14719 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000014720 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000014721{
14722 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
14723 return;
14724 if (idc->ref->name != NULL) {
14725 idc->ref->item = (xmlSchemaBasicItemPtr) xmlHashLookup2(
14726 ctxt->schema->idcDef,
14727 idc->ref->name,
14728 idc->ref->targetNamespace);
14729 if (idc->ref->item == NULL) {
14730 /*
14731 * TODO: It is actually not an error to fail to resolve.
14732 */
14733 xmlSchemaPResCompAttrErr(ctxt,
14734 XML_SCHEMAP_SRC_RESOLVE,
14735 NULL, (xmlSchemaTypePtr) idc, idc->node,
14736 "refer", idc->ref->name,
14737 idc->ref->targetNamespace,
14738 XML_SCHEMA_TYPE_IDC_KEYREF, NULL);
14739 return;
14740 }
14741 }
14742}
14743
14744/**
Daniel Veillard4255d502002-04-16 15:50:10 +000014745 * xmlSchemaParse:
14746 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000014747 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000014748 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +000014749 * XML Shema struture which can be used to validate instances.
14750 * *WARNING* this interface is highly subject to change
14751 *
14752 * Returns the internal XML Schema structure built from the resource or
14753 * NULL in case of error
14754 */
14755xmlSchemaPtr
14756xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
14757{
14758 xmlSchemaPtr ret = NULL;
14759 xmlDocPtr doc;
Daniel Veillardbd2904b2003-11-25 15:38:59 +000014760 xmlNodePtr root;
Daniel Veillarddda22c12004-01-24 08:31:30 +000014761 int preserve = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000014762
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014763 /*
14764 * This one is used if the schema to be parsed was specified via
14765 * the API; i.e. not automatically by the validated instance document.
14766 */
14767
Daniel Veillard4255d502002-04-16 15:50:10 +000014768 xmlSchemaInitTypes();
14769
Daniel Veillard6045c902002-10-09 21:13:59 +000014770 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +000014771 return (NULL);
14772
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000014773 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000014774 ctxt->counter = 0;
14775 ctxt->container = NULL;
14776
14777 /*
14778 * First step is to parse the input document into an DOM/Infoset
14779 */
Daniel Veillard6045c902002-10-09 21:13:59 +000014780 if (ctxt->URL != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000014781 doc = xmlReadFile((const char *) ctxt->URL, NULL,
14782 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014783 if (doc == NULL) {
14784 xmlSchemaPErr(ctxt, NULL,
14785 XML_SCHEMAP_FAILED_LOAD,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014786 "xmlSchemaParse: could not load '%s'.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014787 ctxt->URL, NULL);
14788 return (NULL);
14789 }
Daniel Veillard6045c902002-10-09 21:13:59 +000014790 } else if (ctxt->buffer != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000014791 doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
14792 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014793 if (doc == NULL) {
14794 xmlSchemaPErr(ctxt, NULL,
14795 XML_SCHEMAP_FAILED_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014796 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014797 NULL, NULL);
14798 return (NULL);
14799 }
14800 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard65765282004-01-08 16:59:30 +000014801 ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
Daniel Veillard9d751502003-10-29 13:21:47 +000014802 } else if (ctxt->doc != NULL) {
14803 doc = ctxt->doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000014804 preserve = 1;
Daniel Veillard6045c902002-10-09 21:13:59 +000014805 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014806 xmlSchemaPErr(ctxt, NULL,
14807 XML_SCHEMAP_NOTHING_TO_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014808 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014809 NULL, NULL);
14810 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000014811 }
14812
14813 /*
14814 * Then extract the root and Schema parse it
14815 */
14816 root = xmlDocGetRootElement(doc);
14817 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014818 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
14819 XML_SCHEMAP_NOROOT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014820 "The schema has no document element.\n", NULL, NULL);
Daniel Veillarddda22c12004-01-24 08:31:30 +000014821 if (!preserve) {
14822 xmlFreeDoc(doc);
14823 }
Daniel Veillard4255d502002-04-16 15:50:10 +000014824 return (NULL);
14825 }
14826
14827 /*
14828 * Remove all the blank text nodes
14829 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +000014830 xmlSchemaCleanupDoc(ctxt, root);
Daniel Veillard4255d502002-04-16 15:50:10 +000014831
14832 /*
14833 * Then do the parsing for good
14834 */
14835 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillard1d913862003-11-21 00:28:39 +000014836 if (ret == NULL) {
Daniel Veillarddda22c12004-01-24 08:31:30 +000014837 if (!preserve) {
14838 xmlFreeDoc(doc);
14839 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014840 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +000014841 }
Daniel Veillard4255d502002-04-16 15:50:10 +000014842 ret->doc = doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000014843 ret->preserve = preserve;
Daniel Veillard4255d502002-04-16 15:50:10 +000014844 ctxt->schema = ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014845 ctxt->ctxtType = NULL;
14846 ctxt->parentItem = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000014847 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +000014848 * Then fixup all attributes declarations
14849 */
14850 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
14851
14852 /*
14853 * Then fixup all attributes group declarations
14854 */
14855 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
14856 ctxt);
14857
14858 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000014859 * Resolve identity-constraint keyRefs.
14860 */
14861 xmlHashScan(ret->idcDef, (xmlHashScanner) xmlSchemaResolveIDCKeyRef, ctxt);
14862
14863 /*
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014864 * Check attribute groups for circular references.
14865 */
14866 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner)
14867 xmlSchemaCheckAttributeGroupCircular, ctxt);
14868
14869 /*
14870 * Then fixup all model group definitions.
14871 */
14872 xmlHashScan(ret->groupDecl, (xmlHashScanner) xmlSchemaGroupDefFixup, ctxt);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014873
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014874 /*
Daniel Veillard4255d502002-04-16 15:50:10 +000014875 * Then fixup all types properties
Daniel Veillardc0826a72004-08-10 14:17:33 +000014876 */
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014877 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014878
14879 /*
14880 * Then fix references of element declaration; apply constraints.
14881 */
14882 xmlHashScanFull(ret->elemDecl,
14883 (xmlHashScannerFull) xmlSchemaRefFixupCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000014884
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014885 /*
14886 * Check model groups defnitions for circular references.
14887 */
14888 xmlHashScan(ret->groupDecl, (xmlHashScanner)
14889 xmlSchemaCheckGroupDefCircular, ctxt);
14890
Daniel Veillard4255d502002-04-16 15:50:10 +000014891 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014892 * Then build the content model for all complex types
Daniel Veillard4255d502002-04-16 15:50:10 +000014893 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014894 xmlHashScan(ret->typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014895 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000014896
14897 /*
14898 * Then check the defaults part of the type like facets values
14899 */
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000014900 /* OLD: xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaCheckDefaults, ctxt); */
Daniel Veillard4255d502002-04-16 15:50:10 +000014901
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014902 /*
14903 * Validate the value constraint of attribute declarations/uses.
14904 */
14905 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaCheckAttrValConstr, ctxt);
14906
14907 /*
14908 * Validate the value constraint of element declarations.
14909 */
14910 xmlHashScan(ret->elemDecl, (xmlHashScanner) xmlSchemaCheckElemValConstr, ctxt);
14911
Daniel Veillardc0826a72004-08-10 14:17:33 +000014912
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000014913 if (ctxt->nberrors != 0) {
14914 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014915 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000014916 }
Daniel Veillard4255d502002-04-16 15:50:10 +000014917 return (ret);
14918}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014919
Daniel Veillard4255d502002-04-16 15:50:10 +000014920/**
Daniel Veillard01c13b52002-12-10 15:19:08 +000014921 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +000014922 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +000014923 * @err: the error callback
14924 * @warn: the warning callback
14925 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +000014926 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000014927 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000014928 */
14929void
14930xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014931 xmlSchemaValidityErrorFunc err,
14932 xmlSchemaValidityWarningFunc warn, void *ctx)
14933{
Daniel Veillard4255d502002-04-16 15:50:10 +000014934 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014935 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000014936 ctxt->error = err;
14937 ctxt->warning = warn;
14938 ctxt->userData = ctx;
14939}
14940
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014941/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000014942 * xmlSchemaGetParserErrors:
14943 * @ctxt: a XMl-Schema parser context
14944 * @err: the error callback result
14945 * @warn: the warning callback result
14946 * @ctx: contextual data for the callbacks result
14947 *
14948 * Get the callback information used to handle errors for a parser context
14949 *
14950 * Returns -1 in case of failure, 0 otherwise
14951 */
14952int
14953xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
14954 xmlSchemaValidityErrorFunc * err,
14955 xmlSchemaValidityWarningFunc * warn, void **ctx)
14956{
14957 if (ctxt == NULL)
14958 return(-1);
14959 if (err != NULL)
14960 *err = ctxt->error;
14961 if (warn != NULL)
14962 *warn = ctxt->warning;
14963 if (ctx != NULL)
14964 *ctx = ctxt->userData;
14965 return(0);
14966}
14967
14968/**
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014969 * xmlSchemaFacetTypeToString:
14970 * @type: the facet type
14971 *
14972 * Convert the xmlSchemaTypeType to a char string.
14973 *
14974 * Returns the char string representation of the facet type if the
14975 * type is a facet and an "Internal Error" string otherwise.
14976 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014977static const xmlChar *
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014978xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
14979{
14980 switch (type) {
14981 case XML_SCHEMA_FACET_PATTERN:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014982 return (BAD_CAST "pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014983 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014984 return (BAD_CAST "maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014985 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014986 return (BAD_CAST "maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014987 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014988 return (BAD_CAST "minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014989 case XML_SCHEMA_FACET_MININCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014990 return (BAD_CAST "minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014991 case XML_SCHEMA_FACET_WHITESPACE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014992 return (BAD_CAST "whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014993 case XML_SCHEMA_FACET_ENUMERATION:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014994 return (BAD_CAST "enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014995 case XML_SCHEMA_FACET_LENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014996 return (BAD_CAST "length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014997 case XML_SCHEMA_FACET_MAXLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014998 return (BAD_CAST "maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014999 case XML_SCHEMA_FACET_MINLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000015000 return (BAD_CAST "minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015001 case XML_SCHEMA_FACET_TOTALDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000015002 return (BAD_CAST "totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015003 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000015004 return (BAD_CAST "fractionDigits");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000015005 default:
15006 break;
15007 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000015008 return (BAD_CAST "Internal Error");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000015009}
15010
Daniel Veillardc0826a72004-08-10 14:17:33 +000015011static int
15012xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
15013{
15014 xmlSchemaTypePtr anc;
15015
15016 /*
15017 * The normalization type can be changed only for types which are derived
15018 * from xsd:string.
15019 */
15020 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000015021 if (type->builtInType == XML_SCHEMAS_STRING)
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000015022 return(XML_SCHEMAS_FACET_PRESERVE);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000015023 else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000015024 return(XML_SCHEMAS_FACET_REPLACE);
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000015025 else if (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)
15026 /*
15027 * Note that we assume a whitespace of preserve for anySimpleType.
15028 */
15029 return(XML_SCHEMAS_FACET_PRESERVE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015030 else {
15031 /*
15032 * For all ·atomic· datatypes other than string (and types ·derived·
15033 * by ·restriction· from it) the value of whiteSpace is fixed to
15034 * collapse
15035 */
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000015036 return(XML_SCHEMAS_FACET_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015037 }
15038 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
15039 /*
15040 * For list types the facet "whiteSpace" is fixed to "collapse".
15041 */
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000015042 return (XML_SCHEMAS_FACET_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015043 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000015044 return (XML_SCHEMAS_FACET_UNKNOWN);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015045 } else if (type->facetSet != NULL) {
15046 xmlSchemaTypePtr anyST;
15047 xmlSchemaFacetLinkPtr lin;
15048
15049 /*
15050 * Atomic types.
15051 */
15052 anyST = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
15053 anc = type->baseType;
15054 do {
15055 /*
15056 * For all ·atomic· datatypes other than string (and types ·derived·
15057 * by ·restriction· from it) the value of whiteSpace is fixed to
15058 * collapse
15059 */
15060 if ((anc->type == XML_SCHEMA_TYPE_BASIC) &&
15061 (anc->builtInType == XML_SCHEMAS_STRING)) {
15062
15063 lin = type->facetSet;
15064 do {
15065 if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000015066 return(lin->facet->whitespace);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015067 break;
15068 }
15069 lin = lin->next;
15070 } while (lin != NULL);
15071 break;
15072 }
15073 anc = anc->baseType;
15074 } while (anc != anyST);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000015075 return (XML_SCHEMAS_FACET_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015076 }
15077 return (-1);
15078}
15079
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000015080/**
Daniel Veillard377e1a92004-04-16 16:30:05 +000015081 * xmlSchemaValidateFacetsInternal:
15082 * @ctxt: a schema validation context
Daniel Veillardc0826a72004-08-10 14:17:33 +000015083 * @type: the type holding the facets
Daniel Veillard377e1a92004-04-16 16:30:05 +000015084 * @facets: the list of facets to check
15085 * @value: the lexical repr of the value to validate
15086 * @val: the precomputed value
William M. Bracke7091952004-05-11 15:09:58 +000015087 * @fireErrors: if 0, only internal errors will be fired;
15088 * otherwise all errors will be fired.
Daniel Veillard377e1a92004-04-16 16:30:05 +000015089 *
15090 * Check a value against all facet conditions
15091 *
15092 * Returns 0 if the element is schemas valid, a positive error code
15093 * number otherwise and -1 in case of internal or API error.
15094 */
15095static int
15096xmlSchemaValidateFacetsInternal(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015097 xmlSchemaTypePtr type,
15098 const xmlChar * value,
15099 unsigned long length,
15100 int fireErrors)
Daniel Veillard377e1a92004-04-16 16:30:05 +000015101{
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000015102 int ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015103 xmlNodePtr node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015104 xmlSchemaTypePtr biType; /* The build-in type. */
15105 xmlSchemaTypePtr tmpType;
15106 xmlSchemaFacetLinkPtr facetLink;
Daniel Veillardc7e3cc42004-09-28 12:33:52 +000015107 int retFacet;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015108 xmlSchemaFacetPtr facet;
15109 unsigned long len = 0;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000015110
Daniel Veillardc0826a72004-08-10 14:17:33 +000015111#ifdef DEBUG_UNION_VALIDATION
15112 printf("Facets of type: '%s'\n", (const char *) type->name);
15113 printf(" fireErrors: %d\n", fireErrors);
15114#endif
15115
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015116 node = ctxt->node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015117 /*
15118 * NOTE: Do not jump away, if the facetSet of the given type is
15119 * empty: until now, "pattern" facets of the *base types* need to
15120 * be checked as well.
15121 */
15122 biType = type->baseType;
15123 while ((biType != NULL) && (biType->type != XML_SCHEMA_TYPE_BASIC))
15124 biType = biType->baseType;
15125 if (biType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015126 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015127 "Internal error: xmlSchemaValidateFacetsInternal, "
15128 "the base type axis of the given type '%s' does not resolve to "
15129 "a built-in type.\n",
15130 type->name, NULL);
15131 return (-1);
15132 }
15133
15134 if (type->facetSet != NULL) {
15135 facetLink = type->facetSet;
15136 while (facetLink != NULL) {
15137 facet = facetLink->facet;
15138 /*
15139 * Skip the pattern "whiteSpace": it is used to
15140 * format the character content beforehand.
15141 */
15142 switch (facet->type) {
15143 case XML_SCHEMA_FACET_WHITESPACE:
15144 case XML_SCHEMA_FACET_PATTERN:
15145 case XML_SCHEMA_FACET_ENUMERATION:
15146 break;
15147 case XML_SCHEMA_FACET_LENGTH:
15148 case XML_SCHEMA_FACET_MINLENGTH:
15149 case XML_SCHEMA_FACET_MAXLENGTH:
15150 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
15151 ret = xmlSchemaValidateListSimpleTypeFacet(facet,
15152 value, length, 0);
15153 len = length;
15154 } else
15155 ret = xmlSchemaValidateLengthFacet(biType, facet,
15156 value, ctxt->value, &len);
15157 break;
15158 default:
15159 ret = xmlSchemaValidateFacet(biType, facet, value,
15160 ctxt->value);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015161 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000015162 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015163 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015164 "Internal error: xmlSchemaValidateFacetsInternal, "
15165 "validating facet of type '%s'.\n",
15166 type->name, NULL);
15167 break;
15168 } else if ((ret > 0) && (fireErrors)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015169 xmlSchemaVFacetErr(ctxt, ret, node, value, len,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015170 type, facet, NULL, NULL, NULL, NULL);
15171 }
15172
15173 facetLink = facetLink->next;
15174 }
15175 if (ret >= 0) {
15176 /*
15177 * Process enumerations.
15178 */
15179 retFacet = 0;
15180 facetLink = type->facetSet;
15181 while (facetLink != NULL) {
15182 if (facetLink->facet->type == XML_SCHEMA_FACET_ENUMERATION) {
15183 retFacet = xmlSchemaValidateFacet(biType, facetLink->facet,
15184 value, ctxt->value);
15185 if (retFacet <= 0)
15186 break;
15187 }
15188 facetLink = facetLink->next;
15189 }
15190 if (retFacet > 0) {
15191 ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
15192 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015193 xmlSchemaVFacetErr(ctxt, ret, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015194 value, 0, type, NULL, NULL, NULL, NULL, NULL);
15195 } else if (retFacet < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015196 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015197 "Internal error: xmlSchemaValidateFacetsInternal, "
15198 "validating facet of type '%s'.\n",
15199 BAD_CAST "enumeration", NULL);
15200 ret = -1;
15201 }
15202 }
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000015203 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000015204 if (ret >= 0) {
15205 /*
15206 * Process patters. Pattern facets are ORed at type level
15207 * and ANDed if derived. Walk the base type axis.
15208 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000015209 tmpType = type;
15210 facet = NULL;
15211 do {
15212 retFacet = 0;
15213 for (facetLink = tmpType->facetSet; facetLink != NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015214 facetLink = facetLink->next) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015215 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
15216 continue;
15217 retFacet = xmlSchemaValidateFacet(biType, facetLink->facet,
15218 value, ctxt->value);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015219 if (retFacet == 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +000015220 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015221 else if (retFacet < 0) {
15222 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
15223 "Internal error: xmlSchemaValidateFacetsInternal, "
15224 "validating 'pattern' facet '%s' of type '%s'.\n",
15225 facetLink->facet->value, tmpType->name);
15226 ret = -1;
15227 break;
15228 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +000015229 /* Save the last non-validating facet. */
15230 facet = facetLink->facet;
15231 }
15232 if (retFacet != 0)
15233 break;
15234 tmpType = tmpType->baseType;
15235 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015236 if (retFacet > 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015237 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
15238 if (fireErrors) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015239 xmlSchemaVFacetErr(ctxt, ret, node, value, 0, type, facet,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015240 NULL, NULL, NULL, NULL);
15241 }
15242 }
15243 }
15244
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000015245 return (ret);
15246}
15247
Daniel Veillard4255d502002-04-16 15:50:10 +000015248/************************************************************************
15249 * *
15250 * Simple type validation *
15251 * *
15252 ************************************************************************/
Daniel Veillard377e1a92004-04-16 16:30:05 +000015253
Daniel Veillard4255d502002-04-16 15:50:10 +000015254
15255/************************************************************************
15256 * *
15257 * DOM Validation code *
15258 * *
15259 ************************************************************************/
15260
Daniel Veillard4255d502002-04-16 15:50:10 +000015261static int xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015262 xmlNodePtr elem,
Daniel Veillard3646d642004-06-02 19:19:14 +000015263 xmlSchemaTypePtr type);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015264static int xmlSchemaValidateElementByType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015265 xmlSchemaTypePtr type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000015266 int isNil,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015267 int valSimpleContent);
Daniel Veillard4255d502002-04-16 15:50:10 +000015268
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015269static void xmlSchemaBeginElement(xmlSchemaValidCtxtPtr vctxt);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000015270static int xmlSchemaEndElement(xmlSchemaValidCtxtPtr vctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015271
15272#ifdef ELEM_INFO_ENABLED
15273/**
15274 * xmlSchemaGetFreshElemInfo:
15275 * @vctxt: the schema validation context
15276 *
15277 * Creates/reuses and initializes the element info item for
15278 * the currect tree depth.
15279 *
15280 * Returns the element info item or NULL on API or internal errors.
15281 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000015282static xmlSchemaNodeInfoPtr
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000015283xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt,
15284 int depth)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015285{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000015286 xmlSchemaNodeInfoPtr info = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015287
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000015288 if (depth > vctxt->sizeElemInfos) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015289 xmlSchemaVErr(vctxt, NULL, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000015290 "Internal error: xmlSchemaGetFreshElemInfo, "
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015291 "an inconsistent depth encountered.\n",
15292 NULL, NULL);
15293 return (NULL);
15294 }
15295 if (vctxt->elemInfos == NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000015296 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
15297 xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015298 if (vctxt->elemInfos == NULL) {
15299 xmlSchemaVErrMemory(vctxt,
15300 "allocating the element info array", NULL);
15301 return (NULL);
15302 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000015303 memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015304 vctxt->sizeElemInfos = 10;
15305 } else if (vctxt->sizeElemInfos == vctxt->depth) {
15306 int i = vctxt->sizeElemInfos;
15307
15308 vctxt->sizeElemInfos *= 2;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000015309 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015310 xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000015311 sizeof(xmlSchemaNodeInfoPtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015312 if (vctxt->elemInfos == NULL) {
15313 xmlSchemaVErrMemory(vctxt,
15314 "re-allocating the element info array", NULL);
15315 return (NULL);
15316 }
15317 /*
15318 * We need the new memory to be NULLed.
15319 * TODO: Use memset instead?
15320 */
15321 for (; i < vctxt->sizeElemInfos; i++)
15322 vctxt->elemInfos[i] = NULL;
15323 } else
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000015324 info = vctxt->elemInfos[depth];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015325
15326 if (info == NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000015327 info = (xmlSchemaNodeInfoPtr)
15328 xmlMalloc(sizeof(xmlSchemaNodeInfo));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015329 if (info == NULL) {
15330 xmlSchemaVErrMemory(vctxt,
15331 "allocating an element info", NULL);
15332 return (NULL);
15333 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000015334 vctxt->elemInfos[depth] = info;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015335 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000015336 memset(info, 0, sizeof(xmlSchemaNodeInfo));
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000015337 info->depth = depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015338
15339 return (info);
15340}
15341#endif /* ELEM_INFO_ENABLED */
15342
Daniel Veillard3646d642004-06-02 19:19:14 +000015343
15344/**
15345 * xmlSchemaFreeAttrStates:
15346 * @state: a list of attribute states
15347 *
15348 * Free the given list of attribute states
15349 *
15350 */
15351static void
15352xmlSchemaFreeAttributeStates(xmlSchemaAttrStatePtr state)
15353{
15354 xmlSchemaAttrStatePtr tmp;
15355 while (state != NULL) {
15356 tmp = state;
15357 state = state->next;
15358 xmlFree(tmp);
15359 }
15360}
15361
Daniel Veillard4255d502002-04-16 15:50:10 +000015362/**
15363 * xmlSchemaRegisterAttributes:
15364 * @ctxt: a schema validation context
15365 * @attrs: a list of attributes
15366 *
15367 * Register the list of attributes as the set to be validated on that element
15368 *
15369 * Returns -1 in case of error, 0 otherwise
15370 */
15371static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015372xmlSchemaRegisterAttributes(xmlSchemaValidCtxtPtr ctxt, xmlAttrPtr attrs)
15373{
Daniel Veillard3646d642004-06-02 19:19:14 +000015374 xmlSchemaAttrStatePtr tmp;
15375
15376 ctxt->attr = NULL;
15377 ctxt->attrTop = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000015378 while (attrs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015379 if ((attrs->ns != NULL) &&
15380 (xmlStrEqual(attrs->ns->href, xmlSchemaInstanceNs))) {
15381 attrs = attrs->next;
15382 continue;
15383 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000015384 tmp = (xmlSchemaAttrStatePtr)
15385 xmlMalloc(sizeof(xmlSchemaAttrState));
15386 if (tmp == NULL) {
15387 xmlSchemaVErrMemory(ctxt, "registering attributes", NULL);
15388 return (-1);
15389 }
Daniel Veillard3646d642004-06-02 19:19:14 +000015390 tmp->attr = attrs;
15391 tmp->state = XML_SCHEMAS_ATTR_UNKNOWN;
15392 tmp->next = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015393 tmp->decl = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000015394 if (ctxt->attr == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015395 ctxt->attr = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000015396 else
15397 ctxt->attrTop->next = tmp;
15398 ctxt->attrTop = tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015399 attrs = attrs->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000015400 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015401 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000015402}
15403
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015404#if 0 /* Currently not used */
Daniel Veillard4255d502002-04-16 15:50:10 +000015405/**
Daniel Veillard4255d502002-04-16 15:50:10 +000015406 * xmlSchemaValidateCheckNodeList
15407 * @nodelist: the list of nodes
15408 *
15409 * Check the node list is only made of text nodes and entities pointing
15410 * to text nodes
15411 *
15412 * Returns 1 if true, 0 if false and -1 in case of error
15413 */
15414static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015415xmlSchemaValidateCheckNodeList(xmlNodePtr nodelist)
15416{
Daniel Veillard4255d502002-04-16 15:50:10 +000015417 while (nodelist != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015418 if (nodelist->type == XML_ENTITY_REF_NODE) {
15419 TODO /* implement recursion in the entity content */
15420 }
15421 if ((nodelist->type != XML_TEXT_NODE) &&
15422 (nodelist->type != XML_COMMENT_NODE) &&
15423 (nodelist->type != XML_PI_NODE) &&
William M. Bracke7091952004-05-11 15:09:58 +000015424 (nodelist->type != XML_CDATA_SECTION_NODE)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015425 return (0);
15426 }
15427 nodelist = nodelist->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000015428 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015429 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +000015430}
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015431#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000015432
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015433static void
15434xmlSchemaPostSchemaAssembleFixup(xmlSchemaParserCtxtPtr ctxt)
15435{
15436 int i, nbItems;
15437 xmlSchemaTypePtr item, *items;
15438
15439
15440 /*
15441 * During the Assemble of the schema ctxt->curItems has
15442 * been filled with the relevant new items. Fix those up.
15443 */
15444 nbItems = ctxt->assemble->nbItems;
15445 items = (xmlSchemaTypePtr *) ctxt->assemble->items;
15446
15447 for (i = 0; i < nbItems; i++) {
15448 item = items[i];
15449 switch (item->type) {
15450 case XML_SCHEMA_TYPE_ATTRIBUTE:
15451 xmlSchemaAttrFixup((xmlSchemaAttributePtr) item, ctxt, NULL);
15452 break;
15453 case XML_SCHEMA_TYPE_ELEMENT:
15454 xmlSchemaRefFixupCallback((xmlSchemaElementPtr) item, ctxt,
15455 NULL, NULL, NULL);
15456 break;
15457 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
15458 xmlSchemaAttrGrpFixup((xmlSchemaAttributeGroupPtr) item,
15459 ctxt, NULL);
15460 break;
15461 case XML_SCHEMA_TYPE_GROUP:
15462 xmlSchemaGroupDefFixup(item, ctxt, NULL);
15463 default:
15464 break;
15465 }
15466 }
15467 /*
15468 * Circularity checks.
15469 */
15470 for (i = 0; i < nbItems; i++) {
15471 item = items[i];
15472 switch (item->type) {
15473 case XML_SCHEMA_TYPE_GROUP:
15474 xmlSchemaCheckGroupDefCircular(item, ctxt, NULL);
15475 break;
15476 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
15477 xmlSchemaCheckAttributeGroupCircular(
15478 (xmlSchemaAttributeGroupPtr) item, ctxt, NULL);
15479 break;
15480 default:
15481 break;
15482 }
15483 }
15484 /*
15485 * Fixup for all other item.
15486 * TODO: Hmm, not sure if starting from complex/simple types,
15487 * all subsequent items will be reached.
15488 */
15489 for (i = 0; i < nbItems; i++) {
15490 item = items[i];
15491 switch (item->type) {
15492 case XML_SCHEMA_TYPE_SIMPLE:
15493 case XML_SCHEMA_TYPE_COMPLEX:
15494 xmlSchemaTypeFixup(item, ctxt, NULL);
15495 break;
15496 default:
15497 break;
15498 }
15499 }
15500 /*
15501 * Check facet values. Note that facets are
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000015502 * hold by simple type components only (and
15503 * by complex types in the current implementation).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015504 */
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000015505 /* OLD:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015506 for (i = 0; i < nbItems; i++) {
15507 item = items[i];
15508 switch (item->type) {
15509 case XML_SCHEMA_TYPE_SIMPLE:
15510 case XML_SCHEMA_TYPE_COMPLEX:
15511 xmlSchemaCheckDefaults(item, ctxt, NULL);
15512 break;
15513 default:
15514 break;
15515 }
15516 }
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000015517 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015518 /*
15519 * Build the content model for complex types.
15520 */
15521 for (i = 0; i < nbItems; i++) {
15522 item = items[i];
15523 switch (item->type) {
15524 case XML_SCHEMA_TYPE_COMPLEX:
15525 xmlSchemaBuildContentModel(item, ctxt, NULL);
15526 break;
15527 default:
15528 break;
15529 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015530 }
15531 /*
15532 * Validate value contraint values.
15533 */
15534 for (i = 0; i < nbItems; i++) {
15535 item = items[i];
15536 switch (item->type) {
15537 case XML_SCHEMA_TYPE_ATTRIBUTE:
15538 xmlSchemaCheckAttrValConstr((xmlSchemaAttributePtr) item, ctxt, NULL);
15539 break;
15540 case XML_SCHEMA_TYPE_ELEMENT:
15541 xmlSchemaCheckElemValConstr((xmlSchemaElementPtr) item, ctxt, NULL);
15542 break;
15543 default:
15544 break;
15545 }
15546 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015547}
15548
15549/**
15550 * xmlSchemaAssembleByLocation:
15551 * @pctxt: a schema parser context
15552 * @vctxt: a schema validation context
15553 * @schema: the existing schema
15554 * @node: the node that fired the assembling
15555 * @nsName: the namespace name of the new schema
15556 * @location: the location of the schema
15557 *
15558 * Expands an existing schema by an additional schema.
15559 *
15560 * Returns 0 if the new schema is correct, a positive error code
15561 * number otherwise and -1 in case of an internal or API error.
15562 */
15563static int
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015564xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
15565 xmlSchemaPtr schema,
15566 xmlNodePtr node,
15567 const xmlChar *nsName,
15568 const xmlChar *location)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015569{
15570 const xmlChar *targetNs, *oldtns;
15571 xmlDocPtr doc, olddoc;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015572 int oldflags, ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015573 xmlNodePtr docElem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015574 xmlSchemaParserCtxtPtr pctxt;
15575
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015576 /*
15577 * This should be used:
15578 * 1. on <import>(s)
15579 * 2. if requested by the validated instance
15580 * 3. if requested via the API
15581 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015582 if ((vctxt == NULL) || (schema == NULL))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015583 return (-1);
15584 /*
15585 * Create a temporary parser context.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015586 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015587 if ((vctxt->pctxt == NULL) &&
15588 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1)) {
15589 xmlSchemaVErr(vctxt, node,
15590 XML_SCHEMAV_INTERNAL,
15591 "Internal error: xmlSchemaAssembleByLocation, "
15592 "failed to create a temp. parser context.\n",
15593 NULL, NULL);
15594 return (-1);
15595 }
15596 pctxt = vctxt->pctxt;
15597 /*
15598 * Set the counter to produce unique names for anonymous items.
15599 */
15600 pctxt->counter = schema->counter;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015601 /*
15602 * Acquire the schema document.
15603 */
15604 ret = xmlSchemaAcquireSchemaDoc(pctxt, schema, node,
15605 nsName, location, &doc, &targetNs, 0);
15606 if (ret != 0) {
15607 if (doc != NULL)
15608 xmlFreeDoc(doc);
15609 } else if (doc != NULL) {
15610 docElem = xmlDocGetRootElement(doc);
15611 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015612 * Create new assemble info.
15613 */
15614 if (pctxt->assemble == NULL) {
15615 pctxt->assemble = xmlSchemaNewAssemble();
15616 if (pctxt->assemble == NULL) {
15617 xmlSchemaVErrMemory(vctxt,
15618 "Memory error: xmlSchemaAssembleByLocation, "
15619 "allocating assemble info", NULL);
15620 xmlFreeDoc(doc);
15621 return (-1);
15622 }
15623 }
15624 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015625 * Save and reset the context & schema.
15626 */
15627 oldflags = schema->flags;
15628 oldtns = schema->targetNamespace;
15629 olddoc = schema->doc;
15630
15631 xmlSchemaClearSchemaDefaults(schema);
15632 schema->targetNamespace = targetNs;
15633 /* schema->nbCurItems = 0; */
15634 pctxt->schema = schema;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015635 pctxt->ctxtType = NULL;
15636 pctxt->parentItem = NULL;
15637
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015638 xmlSchemaParseSchemaDefaults(pctxt, schema, docElem);
15639 xmlSchemaParseSchemaTopLevel(pctxt, schema, docElem->children);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015640 xmlSchemaPostSchemaAssembleFixup(pctxt);
15641 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015642 * Set the counter of items.
15643 */
15644 schema->counter = pctxt->counter;
15645 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015646 * Free the list of assembled components.
15647 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015648 pctxt->assemble->nbItems = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015649 /*
15650 * Restore the context & schema.
15651 */
15652 schema->flags = oldflags;
15653 schema->targetNamespace = oldtns;
15654 schema->doc = olddoc;
15655 ret = pctxt->err;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015656 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015657 return (ret);
15658}
15659
15660/**
15661 * xmlSchemaAssembleByXSIAttr:
15662 * @vctxt: a schema validation context
15663 * @xsiAttr: an xsi attribute
15664 * @noNamespace: whether a schema with no target namespace is exptected
15665 *
15666 * Expands an existing schema by an additional schema using
15667 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
15668 * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
15669 * must be set to 1.
15670 *
15671 * Returns 0 if the new schema is correct, a positive error code
15672 * number otherwise and -1 in case of an internal or API error.
15673 */
15674static int
15675xmlSchemaAssembleByXSIAttr(xmlSchemaValidCtxtPtr vctxt,
15676 xmlAttrPtr xsiAttr,
15677 int noNamespace)
15678{
15679 xmlChar *value;
15680 const xmlChar *cur, *end;
15681 const xmlChar *nsname = NULL, *location;
15682 int count = 0;
15683 int ret = 0;
15684
15685 if (xsiAttr == NULL) {
15686 xmlSchemaVCustomErr(vctxt, XML_SCHEMAV_INTERNAL,
15687 NULL, NULL,
15688 "Internal error: xmlSchemaAssembleByXSIAttr, "
15689 "bad arguments", NULL);
15690 return (-1);
15691 }
15692 /*
15693 * Parse the value; we will assume an even number of values
15694 * to be given (this is how Xerces and XSV work).
15695 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015696 value = xmlNodeGetContent((xmlNodePtr) xsiAttr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015697 cur = value;
15698 do {
15699 if (noNamespace != 1) {
15700 /*
15701 * Get the namespace name.
15702 */
15703 while (IS_BLANK_CH(*cur))
15704 cur++;
15705 end = cur;
15706 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
15707 end++;
15708 if (end == cur)
15709 break;
15710 count++;
15711 nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
15712 cur = end;
15713 }
15714 /*
15715 * Get the URI.
15716 */
15717 while (IS_BLANK_CH(*cur))
15718 cur++;
15719 end = cur;
15720 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
15721 end++;
15722 if (end == cur)
15723 break;
15724 count++;
15725 location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015726 cur = end;
15727 ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015728 xsiAttr->parent, nsname, location);
15729 if (ret == -1) {
15730 xmlSchemaVCustomErr(vctxt,
15731 XML_SCHEMAV_INTERNAL,
15732 (xmlNodePtr) xsiAttr, NULL,
15733 "Internal error: xmlSchemaAssembleByXSIAttr, "
15734 "assembling schemata", NULL);
15735 if (value != NULL)
15736 xmlFree(value);
15737 return (-1);
15738 }
15739 } while (*cur != 0);
15740 if (value != NULL)
15741 xmlFree(value);
15742 return (ret);
15743}
15744
15745/**
15746 * xmlSchemaAssembleByXSIElem:
15747 * @vctxt: a schema validation context
15748 * @elem: an element node possibly holding xsi attributes
15749 * @noNamespace: whether a schema with no target namespace is exptected
15750 *
15751 * Assembles an existing schema by an additional schema using
15752 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attributes
15753 * of the given @elem.
15754 *
15755 * Returns 0 if the new schema is correct, a positive error code
15756 * number otherwise and -1 in case of an internal or API error.
15757 */
15758static int
15759xmlSchemaAssembleByXSIElem(xmlSchemaValidCtxtPtr vctxt,
15760 xmlNodePtr elem)
15761{
15762 int ret = 0, retNs = 0;
15763 xmlAttrPtr attr;
15764
15765 attr = xmlHasNsProp(elem, BAD_CAST "schemaLocation", xmlSchemaInstanceNs);
15766 if (attr != NULL) {
15767 retNs = xmlSchemaAssembleByXSIAttr(vctxt, attr, 0);
15768 if (retNs == -1)
15769 return (-1);
15770 }
15771 attr = xmlHasNsProp(elem, BAD_CAST "noNamespaceSchemaLocation", xmlSchemaInstanceNs);
15772 if (attr != NULL) {
15773 ret = xmlSchemaAssembleByXSIAttr(vctxt, attr, 1);
15774 if (ret == -1)
15775 return (-1);
15776 }
15777 if (retNs != 0)
15778 return (retNs);
15779 else
15780 return (ret);
15781}
15782
Daniel Veillard4255d502002-04-16 15:50:10 +000015783/**
Daniel Veillard4255d502002-04-16 15:50:10 +000015784 * xmlSchemaValidateCallback:
15785 * @ctxt: a schema validation context
15786 * @name: the name of the element detected (might be NULL)
15787 * @type: the type
15788 *
15789 * A transition has been made in the automata associated to an element
15790 * content model
15791 */
15792static void
15793xmlSchemaValidateCallback(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015794 const xmlChar * name ATTRIBUTE_UNUSED,
15795 xmlSchemaTypePtr type, xmlNodePtr node)
15796{
Daniel Veillard4255d502002-04-16 15:50:10 +000015797 xmlSchemaTypePtr oldtype = ctxt->type;
15798 xmlNodePtr oldnode = ctxt->node;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015799
Daniel Veillard4255d502002-04-16 15:50:10 +000015800#ifdef DEBUG_CONTENT
Daniel Veillard8651f532002-04-17 09:06:27 +000015801 xmlGenericError(xmlGenericErrorContext,
15802 "xmlSchemaValidateCallback: %s, %s, %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015803 name, type->name, node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +000015804#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015805 /*
15806 * @type->type will be XML_SCHEMA_TYPE_ANY or XML_SCHEMA_TYPE_ELEMENT.
15807 */
Daniel Veillard4255d502002-04-16 15:50:10 +000015808 ctxt->type = type;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015809 ctxt->node = node;
15810 ctxt->cur = node->children;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015811
15812#ifdef ELEM_INFO_ENABLED
15813 xmlSchemaBeginElement(ctxt);
15814#endif
15815
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015816 /*
15817 * Assemble new schemata using xsi.
15818 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015819 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015820 int ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015821
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015822 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
15823 if (ret == -1) {
15824 xmlSchemaVCustomErr(ctxt,
15825 XML_SCHEMAV_INTERNAL,
15826 ctxt->node, NULL,
15827 "Internal error: xmlSchemaValidateElement, "
15828 "assembling schema by xsi", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015829 goto leave;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015830 }
15831 /*
15832 * NOTE: We won't react on schema parser errors here.
15833 * TODO: But a warning would be nice.
15834 */
15835 }
15836 switch (type->type) {
15837 case XML_SCHEMA_TYPE_ELEMENT: {
15838 /*
15839 * NOTE: The build of the content model
15840 * (xmlSchemaBuildAContentModel) ensures that the element
15841 * declaration (and not a reference to it) will be given.
15842 */
15843 if (((xmlSchemaElementPtr) ctxt->type)->ref != NULL) {
15844 /*
15845 * This is paranoid coding ;-)... it should not
15846 * happen here any more.
15847 */
15848 xmlSchemaVCustomErr(ctxt,
15849 XML_SCHEMAV_INTERNAL,
15850 node, NULL,
15851 "Internal error: xmlSchemaValidateCallback, "
15852 "element declaration 'reference' encountered, "
15853 "but an element declaration was expected",
15854 NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015855 goto leave;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015856 }
15857 xmlSchemaValidateElementByDeclaration(ctxt,
15858 (xmlSchemaElementPtr) type);
15859 break;
15860 }
15861 case XML_SCHEMA_TYPE_ANY:
15862 xmlSchemaValidateElementByWildcard(ctxt, type);
15863 break;
15864 default:
15865 break;
15866 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015867leave:
15868
15869#ifdef ELEM_INFO_ENABLED
15870 xmlSchemaEndElement(ctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015871#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000015872 ctxt->type = oldtype;
15873 ctxt->node = oldnode;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015874}
Daniel Veillard4255d502002-04-16 15:50:10 +000015875
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000015876static int
15877xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
15878 const xmlChar *value,
15879 xmlSchemaValPtr *val,
15880 xmlNodePtr node)
15881{
15882 int ret;
15883
15884 ret = xmlValidateQName(value, 1);
15885 if (ret != 0)
15886 return (ret);
15887
15888 {
15889 xmlChar *uri = NULL;
15890 xmlChar *local = NULL;
15891 xmlChar *prefix;
15892
15893 local = xmlSplitQName2(value, &prefix);
15894 if (prefix != NULL) {
15895 xmlNsPtr ns;
15896
15897 /*
15898 * TODO: Make this streamable.
15899 */
15900 if ((node == NULL) || (node->doc == NULL)) {
15901 xmlFree(prefix);
15902 xmlFree(local);
15903 return (3);
15904 }
15905
15906 ns = xmlSearchNs(node->doc, node, prefix);
15907 if (ns == NULL) {
15908 xmlFree(prefix);
15909 xmlFree(local);
15910 return (1);
15911 }
15912 }
15913 if (prefix != NULL) {
15914 if (xmlHashLookup2(vctxt->schema->notaDecl, local, uri) == NULL)
15915 ret = 1;
15916 } else if (xmlHashLookup2(vctxt->schema->notaDecl, value,
15917 NULL) == NULL)
15918 ret = 1;
15919
15920 if ((ret == 0) && (val != NULL)) {
15921 if (prefix != NULL) {
15922 (*val) = xmlSchemaNewNOTATIONValue(BAD_CAST local,
15923 BAD_CAST xmlStrdup(uri));
15924 local = NULL;
15925 } else
15926 (*val) = xmlSchemaNewNOTATIONValue(BAD_CAST xmlStrdup(value),
15927 NULL);
15928 if (*val == NULL)
15929 ret = -1;
15930 }
15931 if (local != NULL)
15932 xmlFree(local);
15933 }
15934
15935 return (ret);
15936}
15937
Daniel Veillard01fa6152004-06-29 17:04:39 +000015938/**
15939 * xmlSchemaValidateSimpleTypeValue:
15940 * @ctxt: a schema validation context
15941 * @value: the value to be validated
15942 * @fireErrors: shall errors be reported?
15943 * @applyFacets: shall facets be applied?
Daniel Veillardc0826a72004-08-10 14:17:33 +000015944 * @normalize: shall the value be normalized?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015945 * @checkNodes: shall the content nodes be checked?
Daniel Veillard01fa6152004-06-29 17:04:39 +000015946 *
15947 * Validates a value by the given type (user derived or built-in).
15948 *
15949 * Returns 0 if the value is valid, a positive error code
15950 * number otherwise and -1 in case of an internal or API error.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015951 */
15952static int
15953xmlSchemaValidateSimpleTypeValue(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015954 xmlSchemaTypePtr type,
15955 const xmlChar *value,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015956 int fireErrors,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015957 int applyFacets,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015958 int normalize,
15959 int checkNodes)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015960{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015961 xmlNodePtr node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015962 int ret = 0;
15963 xmlChar *normValue = NULL;
15964 int wtsp;
15965
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015966 node = ctxt->node;
15967 /* Save the current whitespace normalization type. */
Daniel Veillardc0826a72004-08-10 14:17:33 +000015968 wtsp = ctxt->valueWS;
15969 /*
15970 * Normalize the value.
15971 */
15972 if (normalize &&
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000015973 (ctxt->valueWS != XML_SCHEMAS_FACET_COLLAPSE)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015974 int norm = xmlSchemaGetWhiteSpaceFacetValue(type);
15975
15976 if ((norm != -1) && (norm > ctxt->valueWS)) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000015977 if (norm == XML_SCHEMAS_FACET_COLLAPSE)
Daniel Veillardc0826a72004-08-10 14:17:33 +000015978 normValue = xmlSchemaCollapseString(value);
15979 else
15980 normValue = xmlSchemaWhiteSpaceReplace(value);
15981 ctxt->valueWS = norm;
15982 if (normValue != NULL)
15983 value = (const xmlChar *) normValue;
15984 }
15985 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015986 /*
15987 * The nodes of a content must be checked only once,
15988 * this is not working since list types will fire this
15989 * multiple times.
15990 */
15991 if ((checkNodes == 1) && (ctxt->cur != NULL)) {
15992 xmlNodePtr cur = ctxt->cur;
15993
15994 do {
15995 switch (cur->type) {
15996 case XML_TEXT_NODE:
15997 case XML_CDATA_SECTION_NODE:
15998 case XML_PI_NODE:
15999 case XML_COMMENT_NODE:
16000 case XML_XINCLUDE_START:
16001 case XML_XINCLUDE_END:
16002 break;
16003 case XML_ENTITY_REF_NODE:
16004 case XML_ENTITY_NODE:
16005 /* TODO: Scour the entities for illegal nodes. */
16006 TODO break;
16007 case XML_ELEMENT_NODE: {
16008 /* NOTE: Changed to an internal error, since the
16009 * existence of an element node will be already checked in
16010 * xmlSchemaValidateElementBySimpleType and in
16011 * xmlSchemaValidateElementByComplexType.
16012 */
16013 xmlSchemaVCustomErr(ctxt,
16014 XML_SCHEMAV_INTERNAL,
16015 /* XML_SCHEMAS_ERR_INVALIDELEM, */
16016 node, type,
16017 "Element '%s' found in simple type content",
16018 cur->name);
16019 return (XML_SCHEMAV_INTERNAL);
16020 }
16021 case XML_ATTRIBUTE_NODE:
16022 case XML_DOCUMENT_NODE:
16023 case XML_DOCUMENT_TYPE_NODE:
16024 case XML_DOCUMENT_FRAG_NODE:
16025 case XML_NOTATION_NODE:
16026 case XML_HTML_DOCUMENT_NODE:
16027 case XML_DTD_NODE:
16028 case XML_ELEMENT_DECL:
16029 case XML_ATTRIBUTE_DECL:
16030 case XML_ENTITY_DECL:
16031 case XML_NAMESPACE_DECL:
16032#ifdef LIBXML_DOCB_ENABLED
16033 case XML_DOCB_DOCUMENT_NODE:
16034#endif
16035 xmlSchemaVCustomErr(ctxt,
16036 XML_SCHEMAV_INTERNAL,
16037 /* XML_SCHEMAS_ERR_INVALIDELEM, */
16038 node, NULL,
16039 "Node of unexpected type found in simple type content",
16040 NULL);
16041 return (XML_SCHEMAV_INTERNAL);
16042 }
16043 cur = cur->next;
16044 } while (cur != NULL);
16045 }
16046
William M. Brack2f2a6632004-08-20 23:09:47 +000016047 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
16048 xmlSchemaTypePtr base, anyType;
16049
16050 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
16051
16052 base = type->baseType;
16053 while ((base != NULL) &&
16054 (base->type != XML_SCHEMA_TYPE_SIMPLE) &&
16055 (base->type != XML_SCHEMA_TYPE_BASIC) &&
16056 (base != anyType)) {
16057 base = base->baseType;
16058 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016059 ret = xmlSchemaValidateSimpleTypeValue(ctxt, base, value, 1, 0, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000016060 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016061 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000016062 "Internal error: xmlSchemaValidateSimpleTypeValue, "
16063 "validating complex type '%s'\n",
16064 type->name, NULL);
16065 } else if ((ret == 0) && (applyFacets) && (type->facetSet != NULL)) {
16066 /*
16067 * Check facets.
16068 */
16069 /*
16070 * This is somehow not nice, since if an error occurs
16071 * the reported type will be the complex type; the spec
16072 * wants a simple type to be created on the complex type
16073 * if it has a simple content. For now we have to live with
16074 * it.
16075 */
16076 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
16077 value, 0, fireErrors);
16078 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016079 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000016080 "Internal error: xmlSchemaValidateSimpleTypeValue, "
16081 "validating facets of complex type '%s'\n",
16082 type->name, NULL);
16083 } else if (ret > 0) {
16084 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
William M. Brack2f2a6632004-08-20 23:09:47 +000016085 if (fireErrors)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016086 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
William M. Brack2f2a6632004-08-20 23:09:47 +000016087 }
16088 }
16089 } else if (type->type == XML_SCHEMA_TYPE_BASIC) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016090
16091 if (ctxt->value != NULL) {
16092 xmlSchemaFreeValue(ctxt->value);
16093 ctxt->value = NULL;
16094 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016095 /*
16096 * STREAM-READ-CHILDREN.
16097 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016098 if ((type->builtInType == XML_SCHEMAS_NOTATION) &&
16099 (ctxt->schema != NULL)) {
16100 /*
16101 * NOTATIONs need to be processed here, since they need
16102 * to lookup in the hashtable of NOTATION declarations.
16103 */
16104 ret = xmlSchemaValidateNotation(ctxt, value, &(ctxt->value), node);
16105 } else
16106 ret = xmlSchemaValPredefTypeNodeNoNorm(type, value, &(ctxt->value), node);
Daniel Veillardc0826a72004-08-10 14:17:33 +000016107 if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016108 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
16109 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
16110 else
16111 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
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 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016115 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016116 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000016117 "validating built-in type '%s'\n", type->name, NULL);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000016118 } else if ((ctxt->value == NULL) &&
16119 (type->builtInType == XML_SCHEMAS_STRING) &&
16120 (ctxt->nodeInfo != NULL) &&
16121 (ctxt->nodeInfo->flags & XML_SCHEMA_ELEM_INFO_VALUE_NEEDED)) {
16122#ifdef IDC_VALUE_SUPPORT
16123 xmlChar *valdup;
16124 /*
16125 * Create a precomputed string value for "string" as well if
16126 * requested.
16127 */
16128 valdup = xmlStrdup(value);
16129 ctxt->value = xmlSchemaNewStringValue(XML_SCHEMAS_STRING,
16130 BAD_CAST valdup);
16131 if ((valdup != NULL) && (ctxt->value == NULL))
16132 xmlFree(valdup);
16133#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +000016134 }
16135 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
16136 /* 1.2.1 if {variety} is ·atomic· then the string must ·match·
16137 * a literal in the ·lexical space· of {base type definition}
16138 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016139 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type->baseType, value, 0, 0, 0, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016140 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016141 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016142 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000016143 "validating atomic simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000016144 type->name, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000016145 } else if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016146 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000016147 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016148 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillardc0826a72004-08-10 14:17:33 +000016149 } else if ((applyFacets) && (type->facetSet != NULL)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016150 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000016151 * Check facets.
Daniel Veillard01fa6152004-06-29 17:04:39 +000016152 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000016153 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
16154 value, 0, fireErrors);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016155 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016156 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016157 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000016158 "validating facets of atomic simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000016159 type->name, NULL);
16160 } else if (ret > 0) {
16161 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000016162 /*
16163 Disabled, since the facet validation already reports errors.
16164 if (fireErrors)
16165 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
16166 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000016167 }
16168 }
16169 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
16170
16171 xmlSchemaTypePtr tmpType;
16172 const xmlChar *cur, *end;
16173 xmlChar *tmp;
Daniel Veillardc0826a72004-08-10 14:17:33 +000016174 unsigned long len = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016175
16176 /* 1.2.2 if {variety} is ·list· then the string must be a sequence
16177 * of white space separated tokens, each of which ·match·es a literal
16178 * in the ·lexical space· of {item type definition}
16179 */
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +000016180
Kasimier T. Buchcikde938cd2005-01-13 12:25:57 +000016181 if (value == NULL)
16182 value = BAD_CAST "";
Daniel Veillardc0826a72004-08-10 14:17:33 +000016183 tmpType = xmlSchemaGetListSimpleTypeItemType(type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016184 cur = value;
16185 do {
16186 while (IS_BLANK_CH(*cur))
16187 cur++;
16188 end = cur;
16189 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
16190 end++;
16191 if (end == cur)
16192 break;
16193 tmp = xmlStrndup(cur, end - cur);
16194 len++;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016195 ret = xmlSchemaValidateSimpleTypeValue(ctxt, tmpType, tmp, 0, 1, 0, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016196 xmlFree(tmp);
Daniel Veillardc0826a72004-08-10 14:17:33 +000016197 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016198 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016199 "Internal error: xmlSchemaValidateSimpleTypeValue, "
16200 "validating an item of list simple type '%s'\n",
16201 type->name, NULL);
16202 break;
16203 } else if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016204 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
Daniel Veillardc0826a72004-08-10 14:17:33 +000016205 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016206 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016207 break;
Daniel Veillardc0826a72004-08-10 14:17:33 +000016208 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000016209 cur = end;
16210 } while (*cur != 0);
16211 /*
16212 * Check facets.
16213 */
16214 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016215 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016216 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000016217 "validating list simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000016218 type->name, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000016219 } else if ((ret == 0) && (applyFacets)) {
16220 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
16221 value, len, fireErrors);
16222 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016223 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016224 "Internal error: xmlSchemaValidateSimpleTypeValue, "
16225 "validating facets of list simple type '%s'\n",
16226 type->name, NULL);
16227 } else if (ret > 0) {
16228 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016229 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000016230 Disabled, since the facet validation already reports errors.
16231 if (fireErrors)
16232 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016233 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000016234 }
16235
Daniel Veillard01fa6152004-06-29 17:04:39 +000016236 }
16237 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
16238 xmlSchemaTypeLinkPtr memberLink;
16239
16240 /*
16241 * TODO: For all datatypes ·derived· by ·union· whiteSpace does
16242 * not apply directly; however, the normalization behavior of ·union·
16243 * types is controlled by the value of whiteSpace on that one of the
16244 * ·memberTypes· against which the ·union· is successfully validated.
16245 *
16246 * This means that the value is normalized by the first validating
16247 * member type, then the facets of the union type are applied. This
16248 * needs changing of the value!
16249 */
16250
16251 /*
16252 * 1.2.3 if {variety} is ·union· then the string must ·match· a
16253 * literal in the ·lexical space· of at least one member of
16254 * {member type definitions}
16255 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000016256#ifdef DEBUG_UNION_VALIDATION
16257 printf("Union ST : '%s'\n", (const char *) type->name);
16258 printf(" fireErrors : %d\n", fireErrors);
16259 printf(" applyFacets: %d\n", applyFacets);
16260#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +000016261 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
16262 if (memberLink == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016263 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016264 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000016265 "union simple type '%s' has no member types\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000016266 type->name, NULL);
16267 ret = -1;
16268 }
16269 if (ret == 0) {
16270 while (memberLink != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016271 ret = xmlSchemaValidateSimpleTypeValue(ctxt, memberLink->type,
16272 value, 0, 1, 1, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016273 if ((ret <= 0) || (ret == 0))
16274 break;
16275 memberLink = memberLink->next;
16276 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000016277 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016278 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016279 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000016280 "validating members of union simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000016281 type->name, NULL);
16282 } else if (ret > 0) {
16283 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
Daniel Veillardc0826a72004-08-10 14:17:33 +000016284 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016285 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillardc0826a72004-08-10 14:17:33 +000016286 }
16287 }
16288 /*
16289 * Apply facets (pattern, enumeration).
16290 */
16291 if ((ret == 0) && (applyFacets) && (type->facetSet != NULL)) {
16292 int mws;
16293 /*
16294 * The normalization behavior of ·union· types is controlled by
16295 * the value of whiteSpace on that one of the ·memberTypes·
16296 * against which the ·union· is successfully validated.
16297 */
16298 if (normValue != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016299 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016300 "Internal error: xmlSchemaValidateSimpleTypeValue, "
16301 "the value was already normalized for the union simple "
16302 "type '%s'.\n", type->name, NULL);
16303 }
16304 mws = xmlSchemaGetWhiteSpaceFacetValue(memberLink->type);
16305 if (mws > ctxt->valueWS) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000016306 if (mws == XML_SCHEMAS_FACET_COLLAPSE)
Daniel Veillardc0826a72004-08-10 14:17:33 +000016307 normValue = xmlSchemaCollapseString(value);
16308 else
16309 normValue = xmlSchemaWhiteSpaceReplace(value);
16310 if (normValue != NULL)
16311 value = (const xmlChar *) normValue;
16312 }
16313
16314 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
16315 value, 0, fireErrors);
16316 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016317 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016318 "Internal error: xmlSchemaValidateSimpleTypeValue, "
16319 "validating facets of union simple type '%s'\n",
16320 type->name, NULL);
16321 } else if (ret > 0) {
16322 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
16323 /*
16324 if (fireErrors)
16325 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
16326 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000016327 }
16328 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000016329 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000016330 ctxt->valueWS = wtsp;
16331 if (normValue != NULL)
16332 xmlFree(normValue);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016333 return (ret);
16334}
16335
16336/**
16337 * xmlSchemaValidateSimpleTypeElement:
16338 * @ctxt: a schema validation context
16339 * @node: the element node to be validated.
16340 *
16341 * Validate the element against a simple type.
16342 *
16343 * Returns 0 if the element is valid, a positive error code
16344 * number otherwise and -1 in case of an internal or API error.
16345 */
16346static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016347xmlSchemaValidateElementBySimpleType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016348 xmlSchemaTypePtr type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000016349 int isNil,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016350 int valSimpleContent)
Daniel Veillard01fa6152004-06-29 17:04:39 +000016351{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016352 xmlSchemaTypePtr oldtype;
16353 xmlNodePtr node;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016354 xmlAttrPtr attr;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016355 xmlNodePtr cur;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016356 int ret = 0, retval = 0;
16357
Daniel Veillard01fa6152004-06-29 17:04:39 +000016358 if ((ctxt == NULL) || (type == NULL)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016359 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_INTERNAL, NULL, NULL,
16360 "Internal error: xmlSchemaValidateElementBySimpleType, "
16361 "bad arguments", NULL);
16362 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016363 }
16364
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016365 oldtype = ctxt->type;
16366 node = ctxt->node;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016367 /*
16368 * cvc-type: 3.1.2 The element information item must have no element
16369 * information item [children].
16370 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016371 /*
16372 * STREAM: Child nodes are processed.
16373 */
16374 cur = node->children;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016375 while (cur != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016376 /*
16377 * TODO: Entities, will they produce elements as well?
16378 */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016379 if (cur->type == XML_ELEMENT_NODE) {
16380 xmlSchemaVCustomErr(ctxt,
16381 XML_SCHEMAV_CVC_TYPE_3_1_2,
16382 node, type,
16383 "No element content allowed", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016384 ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016385 }
16386 cur = cur->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016387 }
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016388
Daniel Veillard01fa6152004-06-29 17:04:39 +000016389 /*
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016390 * cvc-type 3.1.1:
16391 *
16392 * The attributes of must be empty, excepting those whose namespace name
16393 * is identical to http://www.w3.org/2001/XMLSchema-instance and whose local
16394 * name is one of type, nil, schemaLocation or noNamespaceSchemaLocation.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016395 */
16396 /*
16397 * STREAM: Attribute nodes are processed.
16398 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000016399 attr = node->properties;
16400 while (attr != NULL) {
16401 if ((attr->ns == NULL) ||
16402 (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
16403 ((!xmlStrEqual(attr->name, BAD_CAST "type")) &&
16404 (!xmlStrEqual(attr->name, BAD_CAST "nil")) &&
16405 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation")) &&
16406 (!xmlStrEqual
16407 (attr->name, BAD_CAST "noNamespaceSchemaLocation")))) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016408 xmlSchemaVIllegalAttrErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016409 XML_SCHEMAV_CVC_TYPE_3_1_1, attr);
16410 ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016411 }
16412 attr = attr->next;
16413 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016414 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016415 * This will skip validation if the type is 'anySimpleType' and
16416 * if the value was already validated (e.g. default values).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016417 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000016418 if ((! isNil) &&
16419 (valSimpleContent == 1) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016420 ((type->type != XML_SCHEMA_TYPE_BASIC) ||
16421 (type->builtInType != XML_SCHEMAS_ANYSIMPLETYPE))) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016422 xmlChar *value;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016423
16424 value = xmlNodeGetContent(node);
16425 /*
16426 * NOTE: This call will not check the content nodes, since
16427 * this should be checked here already.
16428 */
16429 retval = xmlSchemaValidateSimpleTypeValue(ctxt, type, value,
16430 1, 1, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000016431 if (value != NULL)
16432 xmlFree(value);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016433 if (retval != 0)
16434 ret = retval;
William M. Brack2f2a6632004-08-20 23:09:47 +000016435 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016436 ctxt->type = oldtype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016437 return (ret);
16438}
Daniel Veillard4255d502002-04-16 15:50:10 +000016439
16440/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016441 * xmlSchemaValQNameAcquire:
16442 * @value: the lexical represantation of the QName value
16443 * @node: the node to search for the corresponding namespace declaration
16444 * @nsName: the resulting namespace name if found
16445 *
16446 * Checks that a value conforms to the lexical space of the type QName;
16447 * if valid, the corresponding namespace name is searched and retured
16448 * as a copy in @nsName. The local name is returned in @localName as
16449 * a copy.
16450 *
16451 * Returns 0 if valid, 1 if not valid by type, 2 if no corresponding
16452 * namespace declaration was found in scope; -1 in case of an internal or
16453 * API error.
16454 */
16455static int
16456xmlSchemaValQNameAcquire(const xmlChar *value, xmlNodePtr node,
16457 xmlChar **nsName, xmlChar **localName)
16458{
16459 int ret;
16460 xmlChar *local = NULL;
16461
16462 if ((nsName == NULL) || (localName == NULL) || (node == NULL))
16463 return (-1);
16464 *nsName = NULL;
16465 *localName = NULL;
16466 ret = xmlValidateQName(value, 1);
16467 if (ret == 0) {
16468 xmlChar *prefix;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016469 xmlNsPtr ns;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016470
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016471 /*
16472 * NOTE: xmlSplitQName2 will return a duplicated
16473 * string.
16474 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016475 local = xmlSplitQName2(value, &prefix);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016476 if (local == NULL)
16477 local = xmlStrdup(value);
16478 ns = xmlSearchNs(node->doc, node, prefix);
16479 /*
16480 * A namespace need not to be found if the prefix is NULL.
16481 */
16482 if (ns != NULL) {
16483 /*
16484 * TODO: Is it necessary to duplicate the URI here?
16485 */
16486 *nsName = xmlStrdup(ns->href);
16487 } else if (prefix != NULL) {
16488 xmlFree(prefix);
16489 if (local != NULL)
16490 xmlFree(local);
16491 return (2);
16492 }
16493 *localName = local;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016494 if (prefix != NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016495 xmlFree(prefix);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016496 } else
16497 return (1);
16498 return (ret);
16499}
16500
16501/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016502 * xmlSchemaHasElemContent:
16503 * @node: the node
16504 *
16505 * Scours the content of the given node for element
16506 * nodes.
16507 *
16508 * Returns 1 if an element node is found,
16509 * 0 otherwise.
16510 */
16511static int
16512xmlSchemaHasElemContent(xmlNodePtr node)
16513{
16514 if (node == NULL)
16515 return (0);
16516 node = node->children;
16517 while (node != NULL) {
16518 if (node->type == XML_ELEMENT_NODE)
16519 return (1);
16520 node = node->next;
16521 }
16522 return (0);
16523}
16524/**
16525 * xmlSchemaHasElemOrCharContent:
16526 * @node: the node
16527 *
16528 * Scours the content of the given node for element
16529 * and character nodes.
16530 *
16531 * Returns 1 if an element or character node is found,
16532 * 0 otherwise.
16533 */
16534static int
16535xmlSchemaHasElemOrCharContent(xmlNodePtr node)
16536{
16537 if (node == NULL)
16538 return (0);
16539 node = node->children;
16540 while (node != NULL) {
16541 switch (node->type) {
16542 case XML_ELEMENT_NODE:
16543 /*
16544 * TODO: Ask Daniel if these are all character nodes.
16545 */
16546 case XML_TEXT_NODE:
16547 case XML_CDATA_SECTION_NODE:
16548 /*
16549 * TODO: How XML_ENTITY_NODEs evaluated?
16550 */
16551 case XML_ENTITY_REF_NODE:
16552 case XML_ENTITY_NODE:
16553 return (1);
16554 break;
16555 default:
16556 break;
16557 }
16558 node = node->next;
16559 }
16560 return (0);
16561}
16562
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016563/************************************************************************
16564 * *
16565 * Identity-constraints (IDC) *
16566 * *
16567 ************************************************************************/
16568
16569#ifdef IDC_ENABLED
16570
16571/**
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016572 * xmlSchemaAugmentIDC:
16573 * @idcDef: the IDC definition
16574 *
16575 * Creates an augmented IDC definition item.
16576 *
16577 * Returns the item, or NULL on internal errors.
16578 */
16579static void
16580xmlSchemaAugmentIDC(xmlSchemaIDCPtr idcDef,
16581 xmlSchemaValidCtxtPtr vctxt)
16582{
16583 xmlSchemaIDCAugPtr aidc;
16584
16585 aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
16586 if (aidc == NULL) {
16587 xmlSchemaVErrMemory(vctxt,
16588 "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
16589 NULL);
16590 return;
16591 }
16592 aidc->bubbleDepth = -1;
16593 aidc->def = idcDef;
16594 aidc->next = NULL;
16595 if (vctxt->aidcs == NULL)
16596 vctxt->aidcs = aidc;
16597 else {
16598 aidc->next = vctxt->aidcs;
16599 vctxt->aidcs = aidc;
16600 }
16601}
16602
16603/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016604 * xmlSchemaIDCNewBinding:
16605 * @idcDef: the IDC definition of this binding
16606 *
16607 * Creates a new IDC binding.
16608 *
16609 * Returns the new binding in case of succeeded, NULL on internal errors.
16610 */
16611static xmlSchemaPSVIIDCBindingPtr
16612xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
16613{
16614 xmlSchemaPSVIIDCBindingPtr ret;
16615
16616 ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
16617 sizeof(xmlSchemaPSVIIDCBinding));
16618 if (ret == NULL) {
16619 xmlSchemaVErrMemory(NULL,
16620 "allocating a PSVI IDC binding item", NULL);
16621 return (NULL);
16622 }
16623 memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
16624 ret->definition = idcDef;
16625 return (ret);
16626}
16627
16628/**
16629 * xmlSchemaIDCStoreNodeTableItem:
16630 * @vctxt: the WXS validation context
16631 * @item: the IDC node table item
16632 *
16633 * The validation context is used to store an IDC node table items.
16634 * They are stored to avoid copying them if IDC node-tables are merged
16635 * with corresponding parent IDC node-tables (bubbling).
16636 *
16637 * Returns 0 if succeeded, -1 on internal errors.
16638 */
16639static int
16640xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
16641 xmlSchemaPSVIIDCNodePtr item)
16642{
16643 /*
16644 * Add to gobal list.
16645 */
16646 if (vctxt->idcNodes == NULL) {
16647 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
16648 xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
16649 if (vctxt->idcNodes == NULL) {
16650 xmlSchemaVErrMemory(vctxt,
16651 "allocating the IDC node table item list", NULL);
16652 return (-1);
16653 }
16654 vctxt->sizeIdcNodes = 20;
16655 } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
16656 vctxt->sizeIdcNodes *= 2;
16657 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
16658 xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
16659 sizeof(xmlSchemaPSVIIDCNodePtr));
16660 if (vctxt->idcNodes == NULL) {
16661 xmlSchemaVErrMemory(vctxt,
16662 "re-allocating the IDC node table item list", NULL);
16663 return (-1);
16664 }
16665 }
16666 vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
16667
16668 return (0);
16669}
16670
16671/**
16672 * xmlSchemaIDCStoreKey:
16673 * @vctxt: the WXS validation context
16674 * @item: the IDC key
16675 *
16676 * The validation context is used to store an IDC key.
16677 *
16678 * Returns 0 if succeeded, -1 on internal errors.
16679 */
16680static int
16681xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
16682 xmlSchemaPSVIIDCKeyPtr key)
16683{
16684 /*
16685 * Add to gobal list.
16686 */
16687 if (vctxt->idcKeys == NULL) {
16688 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
16689 xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
16690 if (vctxt->idcKeys == NULL) {
16691 xmlSchemaVErrMemory(vctxt,
16692 "allocating the IDC key storage list", NULL);
16693 return (-1);
16694 }
16695 vctxt->sizeIdcKeys = 40;
16696 } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
16697 vctxt->sizeIdcKeys *= 2;
16698 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
16699 xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
16700 sizeof(xmlSchemaPSVIIDCKeyPtr));
16701 if (vctxt->idcKeys == NULL) {
16702 xmlSchemaVErrMemory(vctxt,
16703 "re-allocating the IDC key storage list", NULL);
16704 return (-1);
16705 }
16706 }
16707 vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
16708
16709 return (0);
16710}
16711
16712/**
16713 * xmlSchemaIDCAppendNodeTableItem:
16714 * @bind: the IDC binding
16715 * @ntItem: the node-table item
16716 *
16717 * Appends the IDC node-table item to the binding.
16718 *
16719 * Returns 0 on success and -1 on internal errors.
16720 */
16721static int
16722xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
16723 xmlSchemaPSVIIDCNodePtr ntItem)
16724{
16725 if (bind->nodeTable == NULL) {
16726 bind->sizeNodes = 10;
16727 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
16728 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
16729 if (bind->nodeTable == NULL) {
16730 xmlSchemaVErrMemory(NULL,
16731 "allocating an array of IDC node-table items", NULL);
16732 return(-1);
16733 }
16734 } else if (bind->sizeNodes <= bind->nbNodes) {
16735 bind->sizeNodes *= 2;
16736 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
16737 xmlRealloc(bind->nodeTable, bind->sizeNodes *
16738 sizeof(xmlSchemaPSVIIDCNodePtr));
16739 if (bind->nodeTable == NULL) {
16740 xmlSchemaVErrMemory(NULL,
16741 "re-allocating an array of IDC node-table items", NULL);
16742 return(-1);
16743 }
16744 }
16745 bind->nodeTable[bind->nbNodes++] = ntItem;
16746 return(0);
16747}
16748
16749/**
16750 * xmlSchemaIDCAquireBinding:
16751 * @vctxt: the WXS validation context
16752 * @matcher: the IDC matcher
16753 *
16754 * Looks up an PSVI IDC binding, for the IDC definition and
16755 * of the given matcher. If none found, a new one is created
16756 * and added to the IDC table.
16757 *
16758 * Returns an IDC binding or NULL on internal errors.
16759 */
16760static xmlSchemaPSVIIDCBindingPtr
16761xmlSchemaIDCAquireBinding(xmlSchemaValidCtxtPtr vctxt,
16762 xmlSchemaIDCMatcherPtr matcher)
16763{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000016764 xmlSchemaNodeInfoPtr info;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016765
16766 info = vctxt->elemInfos[matcher->depth];
16767
16768 if (info->idcTable == NULL) {
16769 info->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
16770 if (info->idcTable == NULL)
16771 return (NULL);
16772 return(info->idcTable);
16773 } else {
16774 xmlSchemaPSVIIDCBindingPtr bind = NULL;
16775
16776 bind = info->idcTable;
16777 do {
16778 if (bind->definition == matcher->aidc->def)
16779 return(bind);
16780 if (bind->next == NULL) {
16781 bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
16782 if (bind->next == NULL)
16783 return (NULL);
16784 return(bind->next);
16785 }
16786 bind = bind->next;
16787 } while (bind != NULL);
16788 }
16789 return (NULL);
16790}
16791
16792/**
16793 * xmlSchemaIDCFreeKey:
16794 * @key: the IDC key
16795 *
16796 * Frees an IDC key together with its compiled value.
16797 */
16798static void
16799xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
16800{
16801 if (key->compValue != NULL)
16802 xmlSchemaFreeValue(key->compValue);
16803 xmlFree(key);
16804}
16805
16806/**
16807 * xmlSchemaIDCFreeBinding:
16808 *
16809 * Frees an IDC binding. Note that the node table-items
16810 * are not freed.
16811 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000016812static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016813xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
16814{
16815 if (bind->nodeTable != NULL) {
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000016816 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
16817 int i;
16818 /*
16819 * Node-table items for keyrefs are not stored globally
16820 * to the validation context, since they are not bubbled.
16821 * We need to free them here.
16822 */
16823 for (i = 0; i < bind->nbNodes; i++) {
16824 xmlFree(bind->nodeTable[i]->keys);
16825 xmlFree(bind->nodeTable[i]);
16826 }
16827 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016828 xmlFree(bind->nodeTable);
16829 }
16830 xmlFree(bind);
16831}
16832
16833/**
16834 * xmlSchemaIDCFreeIDCTable:
16835 * @bind: the first IDC binding in the list
16836 *
16837 * Frees an IDC table, i.e. all the IDC bindings in the list.
16838 */
16839static void
16840xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
16841{
16842 xmlSchemaPSVIIDCBindingPtr prev;
16843
16844 while (bind != NULL) {
16845 prev = bind;
16846 bind = bind->next;
16847 xmlSchemaIDCFreeBinding(prev);
16848 }
16849}
16850
16851/**
16852 * xmlSchemaIDCFreeMatcherList:
16853 * @matcher: the first IDC matcher in the list
16854 *
16855 * Frees a list of IDC matchers.
16856 */
16857static void
16858xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
16859{
16860 xmlSchemaIDCMatcherPtr next;
16861
16862 while (matcher != NULL) {
16863 next = matcher->next;
16864 if (matcher->keySeqs != NULL) {
16865 int i;
16866 for (i = 0; i < matcher->sizeKeySeqs; i++)
16867 if (matcher->keySeqs[i] != NULL)
16868 xmlFree(matcher->keySeqs[i]);
16869 xmlFree(matcher->keySeqs);
16870 }
16871 xmlFree(matcher);
16872 matcher = next;
16873 }
16874}
16875
16876/**
16877 * xmlSchemaAreValuesEqual:
16878 * @ta: the first type
16879 * @a: the first value
16880 * @tb: the second type
16881 * @b: the second value
16882 *
16883 * Compares two values.
16884 *
16885 * Returns 1 if they are equal, 0 if not and -1 on internal errors.
16886 */
16887static int
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000016888xmlSchemaAreValuesEqual(xmlSchemaValidCtxtPtr vctxt,
16889 xmlSchemaTypePtr ta,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016890 xmlSchemaValPtr a,
16891 xmlSchemaTypePtr tb,
16892 xmlSchemaValPtr b)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000016893{
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016894 /* Same user derived/built-in derived/built-in primitive types. */
16895 if (ta == tb)
16896 goto compareValue;
16897
16898 /*
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000016899 * Note that comparison with anySimpleTypes with be supported for
16900 * string based types as well.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016901 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000016902#if 0
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016903 if ((ta->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
16904 (tb->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
16905 return(0);
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000016906#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016907
16908 /*
16909 * 4.2.1 equal (data-types)
16910 *
16911 * the ·value space·s of all ·primitive· datatypes are disjoint
16912 * (they do not share any values)
16913 */
16914 if ((ta->builtInType != 0) && (tb->builtInType != 0) &&
16915 (ta->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE) &&
16916 (tb->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
16917 return(0);
16918
16919 if ((ta->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
16920 (ta->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) ||
16921 (tb->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
16922 (tb->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)) {
16923 TODO
16924 return(0);
16925 }
16926 /*
16927 * (1) if a datatype T' is ·derived· by ·restriction· from an atomic datatype
16928 * T then the ·value space· of T' is a subset of the ·value space· of T.
16929 */
16930 /*
16931 * (2) if datatypes T' and T'' are ·derived· by ·restriction· from a common
16932 * atomic ancestor T then the ·value space·s of T' and T'' may overlap.
16933 */
16934
16935 {
16936 xmlSchemaTypePtr pta = ta, ptb = tb;
16937
16938 /* Note that we will compare the primitives here. */
16939 while ((pta->builtInType == 0) ||
16940 ((pta->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE) == 0))
16941 pta = pta->baseType;
16942 while ((ptb->builtInType == 0) ||
16943 ((ptb->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE) == 0))
16944 ptb = ptb->baseType;
16945 if (pta == ptb)
16946 goto compareValue;
16947 return(0);
16948 }
16949compareValue:
16950 {
16951#ifdef IDC_VALUE_SUPPORT
16952 int ret;
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000016953 int aws, bws;
16954
16955 aws = xmlSchemaGetWhiteSpaceFacetValue(ta);
16956 bws = xmlSchemaGetWhiteSpaceFacetValue(tb);
16957
16958 ret = xmlSchemaCompareValuesWhtsp(
16959 a, (xmlSchemaWhitespaceValueType) aws,
16960 b, (xmlSchemaWhitespaceValueType) bws);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016961 if (ret == 0)
16962 return(1);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000016963 else if (ret == -2) {
16964 xmlSchemaVErr(vctxt, vctxt->node,
16965 XML_SCHEMAV_INTERNAL,
16966 "Internal error: xmlSchemaAreValuesEqual, "
16967 "failed to compare the values.\n",
16968 NULL, NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016969 return(-1);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000016970 } else
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016971 return(0);
16972#else
16973 return (1);
16974#endif
16975 }
16976}
16977
16978/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016979 * xmlSchemaIDCAddStateObject:
16980 * @vctxt: the WXS validation context
16981 * @matcher: the IDC matcher
16982 * @sel: the XPath information
16983 * @parent: the parent "selector" state object if any
16984 * @type: "selector" or "field"
16985 *
16986 * Creates/reuses and activates state objects for the given
16987 * XPath information; if the XPath expression consists of unions,
16988 * multiple state objects are created for every unioned expression.
16989 *
16990 * Returns 0 on success and -1 on internal errors.
16991 */
16992static int
16993xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
16994 xmlSchemaIDCMatcherPtr matcher,
16995 xmlSchemaIDCSelectPtr sel,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016996 int type)
16997{
16998 xmlSchemaIDCStateObjPtr sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016999
17000 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017001 * Reuse the state objects from the pool.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017002 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017003 if (vctxt->xpathStatePool != NULL) {
17004 sto = vctxt->xpathStatePool;
17005 vctxt->xpathStatePool = sto->next;
17006 sto->next = NULL;
17007 } else {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017008 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017009 * Create a new state object.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017010 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017011 sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
17012 if (sto == NULL) {
17013 xmlSchemaVErrMemory(NULL,
17014 "allocating an IDC state object", NULL);
17015 return (-1);
17016 }
17017 memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
17018 }
17019 /*
17020 * Add to global list.
17021 */
17022 if (vctxt->xpathStates != NULL)
17023 sto->next = vctxt->xpathStates;
17024 vctxt->xpathStates = sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017025
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017026 /*
17027 * Free the old xpath validation context.
17028 */
17029 if (sto->xpathCtxt != NULL)
17030 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
17031
17032 /*
17033 * Create a new XPath (pattern) validation context.
17034 */
17035 sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
17036 (xmlPatternPtr) sel->xpathComp);
17037 if (sto->xpathCtxt == NULL) {
17038 xmlSchemaVErr(vctxt, vctxt->node,
17039 XML_SCHEMAV_INTERNAL,
17040 "Internal error: xmlSchemaIDCAddStateObject, "
17041 "failed to create the XPath validation context.\n",
17042 NULL, NULL);
17043 return (-1);
17044 }
17045 sto->type = type;
17046 sto->depth = vctxt->depth;
17047 sto->matcher = matcher;
17048 sto->sel = sel;
17049 sto->nbHistory = 0;
17050
17051#if DEBUG_IDC
17052 xmlGenericError(xmlGenericErrorContext, "IDC: STO push '%s'\n",
17053 sto->sel->xpath);
17054#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017055 return (0);
17056}
17057
17058/**
17059 * xmlSchemaXPathEvaluate:
17060 * @vctxt: the WXS validation context
17061 * @nodeType: the nodeType of the current node
17062 *
17063 * Evaluates all active XPath state objects.
17064 *
17065 * Returns the number of IC "field" state objects which resolved to
17066 * this node, 0 if none resolved and -1 on internal errors.
17067 */
17068static int
17069xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017070 xmlElementType nodeType)
17071{
17072 xmlSchemaIDCStateObjPtr sto, head = NULL, first;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017073 int res, resolved = 0, depth = vctxt->depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017074
17075 if (vctxt->xpathStates == NULL)
17076 return (0);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017077
17078 if (nodeType == XML_ATTRIBUTE_NODE)
17079 depth++;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017080#if DEBUG_IDC
17081 {
17082 xmlChar *str = NULL;
17083 xmlGenericError(xmlGenericErrorContext,
17084 "IDC: EVAL on %s, depth %d, type %d\n",
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017085 xmlSchemaFormatNsUriLocal(&str, vctxt->nodeInfo->namespaceName,
17086 vctxt->nodeInfo->localName), depth, nodeType);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017087 FREE_AND_NULL(str)
17088 }
17089#endif
17090 /*
17091 * Process all active XPath state objects.
17092 */
17093 first = vctxt->xpathStates;
17094 sto = first;
17095 while (sto != head) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017096#if DEBUG_IDC
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017097 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017098 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] selector '%s'\n",
17099 sto->matcher->aidc->def->name, sto->sel->xpath);
17100 else
17101 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] field '%s'\n",
17102 sto->matcher->aidc->def->name, sto->sel->xpath);
17103#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017104
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017105#ifdef IDC_XPATH_SUPPORT
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017106 if (nodeType == XML_ELEMENT_NODE)
17107 res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
17108 vctxt->nodeInfo->localName, vctxt->nodeInfo->namespaceName);
17109 else
17110 res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
17111 vctxt->nodeInfo->localName, vctxt->nodeInfo->namespaceName);
17112
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017113#else
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017114 res = 0;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017115#endif
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017116 if (res == -1) {
17117 xmlSchemaVErr(vctxt, vctxt->node,
17118 XML_SCHEMAV_INTERNAL,
17119 "Internal error: xmlSchemaXPathEvaluate, "
17120 "failed to evaluate a node.\n",
17121 NULL, NULL);
17122 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017123 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017124 if (res == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017125 goto next_sto;
17126 /*
17127 * Full match.
17128 */
17129#if DEBUG_IDC
17130 xmlGenericError(xmlGenericErrorContext, "IDC: "
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017131 "MATCH\n");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017132#endif
17133 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017134 * Register a match in the state object history.
17135 */
17136 if (sto->history == NULL) {
17137 sto->history = (int *) xmlMalloc(5 * sizeof(int));
17138 if (sto->history == NULL) {
17139 xmlSchemaVErrMemory(NULL,
17140 "allocating the state object history", NULL);
17141 return(-1);
17142 }
17143 sto->sizeHistory = 10;
17144 } else if (sto->sizeHistory <= sto->nbHistory) {
17145 sto->sizeHistory *= 2;
17146 sto->history = (int *) xmlRealloc(sto->history,
17147 sto->sizeHistory * sizeof(int));
17148 if (sto->history == NULL) {
17149 xmlSchemaVErrMemory(NULL,
17150 "re-allocating the state object history", NULL);
17151 return(-1);
17152 }
17153 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017154 sto->history[sto->nbHistory++] = depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017155
17156#ifdef DEBUG_IDC
17157 xmlGenericError(xmlGenericErrorContext, "IDC: push match '%d'\n",
17158 vctxt->depth);
17159#endif
17160
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017161 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
17162 xmlSchemaIDCSelectPtr sel;
17163 /*
17164 * Activate state objects for the IDC fields of
17165 * the IDC selector.
17166 */
17167#if DEBUG_IDC
17168 xmlGenericError(xmlGenericErrorContext, "IDC: "
17169 "activating field states\n");
17170#endif
17171 sel = sto->matcher->aidc->def->fields;
17172 while (sel != NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017173 if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
17174 sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
17175 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017176 sel = sel->next;
17177 }
17178 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
17179 /*
17180 * An IDC key node was found.
17181 */
17182#if DEBUG_IDC
17183 xmlGenericError(xmlGenericErrorContext,
17184 "IDC: key found\n");
17185#endif
17186 /*
17187 * Notify that the character value of this node is
17188 * needed.
17189 */
17190 if (resolved == 0)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017191 vctxt->nodeInfo->flags |= XML_SCHEMA_ELEM_INFO_VALUE_NEEDED;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017192 resolved++;
17193 }
17194next_sto:
17195 if (sto->next == NULL) {
17196 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017197 * Evaluate field state objects created on this node as well.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017198 */
17199 head = first;
17200 sto = vctxt->xpathStates;
17201 } else
17202 sto = sto->next;
17203 }
17204 return (resolved);
17205}
17206
17207/**
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017208 * xmlSchemaXPathProcessHistory:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017209 * @vctxt: the WXS validation context
17210 * @type: the simple/complex type of the current node if any at all
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017211 * @compValue: the precompiled value
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017212 *
17213 * Processes and pops the history items of the IDC state objects.
17214 * IDC key-sequences are validated/created on IDC bindings.
17215 *
17216 * Returns 0 on success and -1 on internal errors.
17217 */
17218static int
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017219xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017220 int depth)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017221{
17222 xmlSchemaIDCStateObjPtr sto, nextsto;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017223 int res, matchDepth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017224 xmlSchemaPSVIIDCKeyPtr key = NULL;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017225 xmlSchemaTypePtr type = vctxt->nodeInfo->typeDef;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017226
17227 if (vctxt->xpathStates == NULL)
17228 return (0);
17229 sto = vctxt->xpathStates;
17230
17231#if DEBUG_IDC
17232 {
17233 xmlChar *str = NULL;
17234 xmlGenericError(xmlGenericErrorContext,
17235 "IDC: BACK on %s, depth %d\n",
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017236 xmlSchemaFormatNsUriLocal(&str, vctxt->nodeInfo->namespaceName,
17237 vctxt->nodeInfo->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017238 FREE_AND_NULL(str)
17239 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017240#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017241 /*
17242 * Evaluate the state objects.
17243 */
17244 while (sto != NULL) {
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017245#ifdef IDC_XPATH_SUPPORT
17246 xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
17247 #if DEBUG_IDC
17248 xmlGenericError(xmlGenericErrorContext, "IDC: stream pop '%s'\n",
17249 sto->sel->xpath);
17250 #endif
17251#endif
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017252 if (sto->nbHistory == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017253 goto deregister_check;
17254
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017255 matchDepth = sto->history[sto->nbHistory -1];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017256
17257 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017258 * Only matches at the current depth are of interest.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017259 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017260 if (matchDepth != depth) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017261 sto = sto->next;
17262 continue;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017263 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017264 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
17265 if (! IS_SIMPLE_TYPE(type)) {
17266 /*
17267 * Not qualified if the field resolves to a node of non
17268 * simple type.
17269 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017270 xmlSchemaStreamVCustomErr(vctxt,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017271 XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017272 vctxt->nodeInfo,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017273 (xmlSchemaTypePtr) sto->matcher->aidc->def,
17274 "The field '%s' does evaluate to a node of "
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017275 "non-simple type", sto->sel->xpath, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017276
17277 sto->nbHistory--;
17278 goto deregister_check;
17279 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017280 if ((key == NULL) && (vctxt->nodeInfo->value == NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017281 /*
17282 * Failed to provide the normalized value; maby
17283 * the value was invalid.
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017284 */
17285 xmlSchemaStreamVCustomErr(vctxt,
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000017286 XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017287 vctxt->nodeInfo,
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000017288 (xmlSchemaTypePtr) sto->matcher->aidc->def,
17289 "Warning: No precomputed value available, the value "
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017290 "was either invalid or something strange happend",
17291 NULL, NULL);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000017292 /*
17293 xmlSchemaVErr(vctxt, vctxt->nodeInfo->node,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017294 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017295 "Internal error: xmlSchemaXPathProcessHistory, "
17296 "computed value not available.\n",
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017297 NULL, NULL);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000017298 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017299 sto->nbHistory--;
17300 goto deregister_check;
17301 } else {
17302 xmlSchemaIDCMatcherPtr matcher = sto->matcher;
17303 xmlSchemaPSVIIDCKeyPtr *keySeq;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017304 int pos, idx;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017305
17306 /*
17307 * The key will be anchored on the matcher's list of
17308 * key-sequences. The position in this list is determined
17309 * by the target node's depth relative to the matcher's
17310 * depth of creation (i.e. the depth of the scope element).
17311 */
17312 pos = sto->depth - matcher->depth;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017313 idx = sto->sel->index;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017314
17315 /*
17316 * Create/grow the array of key-sequences.
17317 */
17318 if (matcher->keySeqs == NULL) {
17319 if (pos > 9)
17320 matcher->sizeKeySeqs = pos * 2;
17321 else
17322 matcher->sizeKeySeqs = 10;
17323 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
17324 xmlMalloc(matcher->sizeKeySeqs *
17325 sizeof(xmlSchemaPSVIIDCKeyPtr *));
17326 if (matcher->keySeqs == NULL) {
17327 xmlSchemaVErrMemory(NULL,
17328 "allocating an array of key-sequences",
17329 NULL);
17330 return(-1);
17331 }
17332 memset(matcher->keySeqs, 0,
17333 matcher->sizeKeySeqs *
17334 sizeof(xmlSchemaPSVIIDCKeyPtr *));
17335 } else if (pos >= matcher->sizeKeySeqs) {
17336 int i = matcher->sizeKeySeqs;
17337
17338 matcher->sizeKeySeqs *= 2;
17339 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
17340 xmlRealloc(matcher->keySeqs,
17341 matcher->sizeKeySeqs *
17342 sizeof(xmlSchemaPSVIIDCKeyPtr *));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017343 if (matcher->keySeqs == NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017344 xmlSchemaVErrMemory(NULL,
17345 "reallocating an array of key-sequences",
17346 NULL);
17347 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017348 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017349 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017350 * The array needs to be NULLed.
17351 * TODO: Use memset?
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017352 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017353 for (; i < matcher->sizeKeySeqs; i++)
17354 matcher->keySeqs[i] = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017355 }
17356
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017357 /*
17358 * Get/create the key-sequence.
17359 */
17360 keySeq = matcher->keySeqs[pos];
17361 if (keySeq == NULL) {
17362 goto create_sequence;
17363 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017364 if (keySeq[idx] != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017365 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017366 * cvc-identity-constraint:
17367 * 3 For each node in the ·target node set· all
17368 * of the {fields}, with that node as the context
17369 * node, evaluate to either an empty node-set or
17370 * a node-set with exactly one member, which must
17371 * have a simple type.
17372 *
17373 * The key was already set; report an error.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017374 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017375 xmlSchemaStreamVCustomErr(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017376 XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017377 vctxt->nodeInfo,
17378 (xmlSchemaTypePtr) matcher->aidc->def,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017379 "The field '%s' evaluates to a node-set "
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017380 "with more than one member",
17381 sto->sel->xpath, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017382 sto->nbHistory--;
17383 goto deregister_check;
17384 } else {
17385 goto create_key;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017386 }
17387 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017388
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017389create_sequence:
17390 /*
17391 * Create a key-sequence.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017392 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017393 keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
17394 matcher->aidc->def->nbFields *
17395 sizeof(xmlSchemaPSVIIDCKeyPtr));
17396 if (keySeq == NULL) {
17397 xmlSchemaVErrMemory(NULL,
17398 "allocating an IDC key-sequence", NULL);
17399 return(-1);
17400 }
17401 memset(keySeq, 0, matcher->aidc->def->nbFields *
17402 sizeof(xmlSchemaPSVIIDCKeyPtr));
17403 matcher->keySeqs[pos] = keySeq;
17404create_key:
17405 /*
17406 * Created a key once per node only.
17407 */
17408 if (key == NULL) {
17409 key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
17410 sizeof(xmlSchemaPSVIIDCKey));
17411 if (key == NULL) {
17412 xmlSchemaVErrMemory(NULL,
17413 "allocating a IDC key", NULL);
17414 xmlFree(keySeq);
17415 matcher->keySeqs[pos] = NULL;
17416 return(-1);
17417 }
17418 /*
17419 * Consume the compiled value.
17420 */
17421 key->type = type;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017422 key->compValue = vctxt->nodeInfo->value;
17423 vctxt->nodeInfo->value = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017424 /*
17425 * Store the key in a global list.
17426 */
17427 if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
17428 xmlSchemaIDCFreeKey(key);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017429 return (-1);
17430 }
17431 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017432 keySeq[idx] = key;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017433 }
17434 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017435
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017436 xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
17437 xmlSchemaPSVIIDCBindingPtr bind;
17438 xmlSchemaPSVIIDCNodePtr ntItem;
17439 xmlSchemaIDCMatcherPtr matcher;
17440 xmlSchemaIDCPtr idc;
17441 int pos, i, j, nbKeys;
17442 /*
17443 * Here we have the following scenario:
17444 * An IDC 'selector' state object resolved to a target node,
17445 * during the time this target node was in the
17446 * ancestor-or-self axis, the 'field' state object(s) looked
17447 * out for matching nodes to create a key-sequence for this
17448 * target node. Now we are back to this target node and need
17449 * to put the key-sequence, together with the target node
17450 * itself, into the node-table of the corresponding IDC
17451 * binding.
17452 */
17453 matcher = sto->matcher;
17454 idc = matcher->aidc->def;
17455 nbKeys = idc->nbFields;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017456 pos = depth - matcher->depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017457 /*
17458 * Check if the matcher has any key-sequences at all, plus
17459 * if it has a key-sequence for the current target node.
17460 */
17461 if ((matcher->keySeqs == NULL) ||
17462 (matcher->sizeKeySeqs <= pos)) {
17463 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
17464 goto selector_key_error;
17465 else
17466 goto selector_leave;
17467 }
17468
17469 keySeq = &(matcher->keySeqs[pos]);
17470 if (*keySeq == NULL) {
17471 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
17472 goto selector_key_error;
17473 else
17474 goto selector_leave;
17475 }
17476
17477 for (i = 0; i < nbKeys; i++) {
17478 if ((*keySeq)[i] == NULL) {
17479 /*
17480 * Not qualified, if not all fields did resolve.
17481 */
17482 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
17483 /*
17484 * All fields of a "key" IDC must resolve.
17485 */
17486 goto selector_key_error;
17487 }
17488 goto selector_leave;
17489 }
17490 }
17491 /*
17492 * All fields did resolve.
17493 */
17494
17495 /*
17496 * 4.1 If the {identity-constraint category} is unique(/key),
17497 * then no two members of the ·qualified node set· have
17498 * ·key-sequences· whose members are pairwise equal, as
17499 * defined by Equal in [XML Schemas: Datatypes].
17500 *
17501 * Get the IDC binding from the matcher and check for
17502 * duplicate key-sequences.
17503 */
17504 bind = xmlSchemaIDCAquireBinding(vctxt, matcher);
17505 if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
17506 (bind->nbNodes != 0)) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017507 xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017508
17509 i = 0;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017510 res = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017511 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017512 * Compare the key-sequences, key by key.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017513 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017514 do {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017515 bkeySeq = bind->nodeTable[i]->keys;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017516 for (j = 0; j < nbKeys; j++) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017517 ckey = (*keySeq)[j];
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017518 bkey = bkeySeq[j];
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017519 res = xmlSchemaAreValuesEqual(vctxt, ckey->type,
17520 ckey->compValue, bkey->type, bkey->compValue);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017521 if (res == -1) {
17522 return (-1);
17523 } else if (res == 0)
17524 break;
17525 }
17526 if (res == 1) {
17527 /*
17528 * Duplicate found.
17529 */
17530 break;
17531 }
17532 i++;
17533 } while (i < bind->nbNodes);
17534 if (i != bind->nbNodes) {
17535 /*
17536 * TODO: Try to report the key-sequence.
17537 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017538 xmlSchemaStreamVCustomErr(vctxt,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017539 XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017540 vctxt->nodeInfo,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017541 (xmlSchemaTypePtr) idc,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017542 "Duplicate key-sequence found", NULL, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017543
17544 goto selector_leave;
17545 }
17546 }
17547 /*
17548 * Add a node-table item to the IDC binding.
17549 */
17550 ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
17551 sizeof(xmlSchemaPSVIIDCNode));
17552 if (ntItem == NULL) {
17553 xmlSchemaVErrMemory(NULL,
17554 "allocating an IDC node-table item", NULL);
17555 xmlFree(*keySeq);
17556 *keySeq = NULL;
17557 return(-1);
17558 }
17559 memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
17560
17561 /*
17562 * Store the node-table item on global list.
17563 */
17564 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
17565 if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
17566 xmlFree(ntItem);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017567 xmlFree(*keySeq);
17568 *keySeq = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017569 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017570 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017571 }
17572 /*
17573 * Init the node-table item. Consume the key-sequence.
17574 */
17575 ntItem->node = vctxt->node;
17576 ntItem->keys = *keySeq;
17577 *keySeq = NULL;
17578 if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1) {
17579 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
17580 /*
17581 * Free the item, since keyref items won't be
17582 * put on a global list.
17583 */
17584 xmlFree(ntItem->keys);
17585 xmlFree(ntItem);
17586 }
17587 return (-1);
17588 }
17589
17590 goto selector_leave;
17591selector_key_error:
17592 /*
17593 * 4.2.1 (KEY) The ·target node set· and the
17594 * ·qualified node set· are equal, that is, every
17595 * member of the ·target node set· is also a member
17596 * of the ·qualified node set· and vice versa.
17597 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017598 xmlSchemaStreamVCustomErr(vctxt,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017599 XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017600 vctxt->nodeInfo,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017601 (xmlSchemaTypePtr) idc,
17602 "All 'key' fields must evaluate to a node",
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017603 NULL, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017604selector_leave:
17605 /*
17606 * Free the key-sequence if not added to the IDC table.
17607 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017608 if ((keySeq != NULL) && (*keySeq != NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017609 xmlFree(*keySeq);
17610 *keySeq = NULL;
17611 }
17612 } /* if selector */
17613
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017614 sto->nbHistory--;
17615
17616deregister_check:
17617 /*
17618 * Deregister state objects if they reach the depth of creation.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017619 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017620 if ((sto->nbHistory == 0) && (sto->depth == depth)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017621#if DEBUG_IDC
17622 xmlGenericError(xmlGenericErrorContext, "IDC: STO pop '%s'\n",
17623 sto->sel->xpath);
17624#endif
17625 if (vctxt->xpathStates != sto) {
17626 xmlSchemaVErr(vctxt, vctxt->node,
17627 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017628 "Internal error: xmlSchemaXPathProcessHistory, "
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017629 "The state object to be removed is not the first "
17630 "in the list.\n",
17631 NULL, NULL);
17632 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017633 nextsto = sto->next;
17634 /*
17635 * Unlink from the list of active XPath state objects.
17636 */
17637 vctxt->xpathStates = sto->next;
17638 sto->next = vctxt->xpathStatePool;
17639 /*
17640 * Link it to the pool of reusable state objects.
17641 */
17642 vctxt->xpathStatePool = sto;
17643 sto = nextsto;
17644 } else
17645 sto = sto->next;
17646 } /* while (sto != NULL) */
17647 return (0);
17648}
17649
17650/**
17651 * xmlSchemaIDCRegisterMatchers:
17652 * @vctxt: the WXS validation context
17653 * @elemDecl: the element declaration
17654 *
17655 * Creates helper objects to evaluate IDC selectors/fields
17656 * successively.
17657 *
17658 * Returns 0 if OK and -1 on internal errors.
17659 */
17660static int
17661xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
17662 xmlSchemaElementPtr elemDecl)
17663{
17664 xmlSchemaIDCMatcherPtr matcher, last = NULL;
17665 xmlSchemaIDCPtr idc, refIdc;
17666 xmlSchemaIDCAugPtr aidc;
17667
17668 idc = (xmlSchemaIDCPtr) elemDecl->idcs;
17669 if (idc == NULL)
17670 return (0);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017671
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017672#if DEBUG_IDC
17673 {
17674 xmlChar *str = NULL;
17675 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017676 "IDC: REGISTER on %s, depth %d\n",
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017677 (char *) xmlSchemaFormatNsUriLocal(&str, vctxt->nodeInfo->namespaceName,
17678 vctxt->nodeInfo->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017679 FREE_AND_NULL(str)
17680 }
17681#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017682 if (vctxt->nodeInfo->idcMatchers != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017683 xmlSchemaVErr(vctxt, vctxt->node,
17684 XML_SCHEMAV_INTERNAL,
17685 "Internal error: xmlSchemaIDCRegisterMatchers: "
17686 "The chain of IDC matchers is expected to be empty.\n",
17687 NULL, NULL);
17688 return (-1);
17689 }
17690 do {
17691 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
17692 /*
17693 * Since IDCs bubbles are expensive we need to know the
17694 * depth at which the bubbles should stop; this will be
17695 * the depth of the top-most keyref IDC. If no keyref
17696 * references a key/unique IDC, the bubbleDepth will
17697 * be -1, indicating that no bubbles are needed.
17698 */
17699 refIdc = (xmlSchemaIDCPtr) idc->ref->item;
17700 if (refIdc != NULL) {
17701 /*
17702 * Lookup the augmented IDC.
17703 */
17704 aidc = vctxt->aidcs;
17705 while (aidc != NULL) {
17706 if (aidc->def == refIdc)
17707 break;
17708 aidc = aidc->next;
17709 }
17710 if (aidc == NULL) {
17711 xmlSchemaVErr(vctxt, vctxt->node,
17712 XML_SCHEMAV_INTERNAL,
17713 "Internal error: xmlSchemaIDCRegisterMatchers: "
17714 "Could not find an augmented IDC item for an IDC "
17715 "definition.\n",
17716 NULL, NULL);
17717 return (-1);
17718 }
17719 if ((aidc->bubbleDepth == -1) ||
17720 (vctxt->depth < aidc->bubbleDepth))
17721 aidc->bubbleDepth = vctxt->depth;
17722 }
17723 }
17724 /*
17725 * Lookup the augmented IDC item for the IDC definition.
17726 */
17727 aidc = vctxt->aidcs;
17728 while (aidc != NULL) {
17729 if (aidc->def == idc)
17730 break;
17731 aidc = aidc->next;
17732 }
17733 if (aidc == NULL) {
17734 xmlSchemaVErr(vctxt, vctxt->node,
17735 XML_SCHEMAV_INTERNAL,
17736 "Internal error: xmlSchemaIDCRegisterMatchers: "
17737 "Could not find an augmented IDC item for an IDC definition.\n",
17738 NULL, NULL);
17739 return (-1);
17740 }
17741 /*
17742 * Create an IDC matcher for every IDC definition.
17743 */
17744 matcher = (xmlSchemaIDCMatcherPtr)
17745 xmlMalloc(sizeof(xmlSchemaIDCMatcher));
17746 if (matcher == NULL) {
17747 xmlSchemaVErrMemory(vctxt,
17748 "allocating an IDC matcher", NULL);
17749 return (-1);
17750 }
17751 memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
17752 if (last == NULL)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017753 vctxt->nodeInfo->idcMatchers = matcher;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017754 else
17755 last->next = matcher;
17756 last = matcher;
17757
17758 matcher->type = IDC_MATCHER;
17759 matcher->depth = vctxt->depth;
17760 matcher->aidc = aidc;
17761#if DEBUG_IDC
17762 xmlGenericError(xmlGenericErrorContext, "IDC: register matcher\n");
17763#endif
17764 /*
17765 * Init the automaton state object.
17766 */
17767 if (xmlSchemaIDCAddStateObject(vctxt, matcher,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017768 idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017769 return (-1);
17770
17771 idc = idc->next;
17772 } while (idc != NULL);
17773 return (0);
17774}
17775
17776/**
17777 * xmlSchemaBubbleIDCNodeTables:
17778 * @depth: the current tree depth
17779 *
17780 * Merges IDC bindings of an element at @depth into the corresponding IDC
17781 * bindings of its parent element. If a duplicate note-table entry is found,
17782 * both, the parent node-table entry and child entry are discarded from the
17783 * node-table of the parent.
17784 *
17785 * Returns 0 if OK and -1 on internal errors.
17786 */
17787static int
17788xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
17789{
17790 xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017791 xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL, lastParBind = NULL; /* parent IDC bindings. */
17792 xmlSchemaPSVIIDCNodePtr node, parNode = NULL; /* node-table entries. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017793 xmlSchemaPSVIIDCKeyPtr key, parKey; /* keys of in a key-sequence. */
17794 xmlSchemaIDCAugPtr aidc;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017795 int i, j, k, ret = 0, oldNum, newDupls = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017796 int duplTop;
17797
17798 /*
17799 * The node table has the following sections:
17800 *
17801 * O --> old node-table entries (first)
17802 * O
17803 * + --> new node-table entries
17804 * +
17805 * % --> new duplicate node-table entries
17806 * %
17807 * # --> old duplicate node-table entries
17808 * # (last)
17809 *
17810 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017811 bind = vctxt->nodeInfo->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017812 if (bind == NULL) {
17813 /* Fine, no table, no bubbles. */
17814 return (0);
17815 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017816
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017817 parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
17818 /*
17819 * Walk all bindings; create new or add to existing bindings.
17820 * Remove duplicate key-sequences.
17821 */
17822start_binding:
17823 while (bind != NULL) {
17824 /*
17825 * Skip keyref IDCs.
17826 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017827 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
17828 bind = bind->next;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017829 continue;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017830 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017831 /*
17832 * Check if the key/unique IDC table needs to be bubbled.
17833 */
17834 aidc = vctxt->aidcs;
17835 do {
17836 if (aidc->def == bind->definition) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017837 if (aidc->bubbleDepth >= vctxt->depth) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017838 bind = bind->next;
17839 goto start_binding;
17840 }
17841 break;
17842 }
17843 aidc = aidc->next;
17844 } while (aidc != NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017845
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017846 if (parTable != NULL)
17847 parBind = *parTable;
17848 while (parBind != NULL) {
17849 /*
17850 * Search a matching parent binding for the
17851 * IDC definition.
17852 */
17853 if (parBind->definition == bind->definition) {
17854
17855 /*
17856 * Compare every node-table entry of the child node,
17857 * i.e. the key-sequence within, ...
17858 */
17859 oldNum = parBind->nbNodes; /* Skip newly added items. */
17860 duplTop = oldNum + parBind->nbDupls;
17861
17862 for (i = 0; i < bind->nbNodes; i++) {
17863 node = bind->nodeTable[i];
17864 if (node == NULL)
17865 continue;
17866 /*
17867 * ...with every key-sequence of the parent node, already
17868 * evaluated to be a duplicate key-sequence.
17869 */
17870 if (parBind->nbDupls != 0) {
17871 j = bind->nbNodes + newDupls;
17872 while (j < duplTop) {
17873 parNode = parBind->nodeTable[j];
17874 for (k = 0; k < bind->definition->nbFields; k++) {
17875 key = node->keys[k];
17876 parKey = parNode->keys[k];
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017877 ret = xmlSchemaAreValuesEqual(vctxt, key->type,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017878 key->compValue,
17879 parKey->type, parKey->compValue);
17880 if (ret == -1) {
17881 /* TODO: Internal error */
17882 return(-1);
17883 } else if (ret == 0)
17884 break;
17885
17886 }
17887 if (ret == 1)
17888 /* Duplicate found. */
17889 break;
17890 j++;
17891 }
17892 if (j != duplTop) {
17893 /* Duplicate found. */
17894 continue;
17895 }
17896 }
17897 /*
17898 * ... and with every key-sequence of the parent node.
17899 */
17900 j = 0;
17901 while (j < oldNum) {
17902 parNode = parBind->nodeTable[j];
17903 /*
17904 * Compare key by key.
17905 */
17906 for (k = 0; k < parBind->definition->nbFields; k++) {
17907 key = node->keys[k];
17908 parKey = parNode->keys[k];
17909
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017910 ret = xmlSchemaAreValuesEqual(vctxt, key->type,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017911 key->compValue,
17912 parKey->type, parKey->compValue);
17913 if (ret == -1) {
17914 /* TODO: Internal error */
17915 } else if (ret == 0)
17916 break;
17917
17918 }
17919 if (ret == 1)
17920 /*
17921 * The key-sequences are equal.
17922 */
17923 break;
17924 j++;
17925 }
17926 if (j != oldNum) {
17927 /*
17928 * Handle duplicates.
17929 */
17930 newDupls++;
17931 oldNum--;
17932 parBind->nbNodes--;
17933 /*
17934 * Move last old item to pos of duplicate.
17935 */
17936 parBind->nodeTable[j] =
17937 parBind->nodeTable[oldNum];
17938
17939 if (parBind->nbNodes != oldNum) {
17940 /*
17941 * If new items exist, move last new item to
17942 * last of old items.
17943 */
17944 parBind->nodeTable[oldNum] =
17945 parBind->nodeTable[parBind->nbNodes];
17946 }
17947 /*
17948 * Move duplicate to last pos of new/old items.
17949 */
17950 parBind->nodeTable[parBind->nbNodes] = parNode;
17951
17952 } else {
17953 /*
17954 * Add the node-table entry (node and key-sequence) of
17955 * the child node to the node table of the parent node.
17956 */
17957 if (parBind->nodeTable == NULL) {
17958 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
17959 xmlMalloc(1 * sizeof(xmlSchemaPSVIIDCNodePtr));
17960 if (parBind->nodeTable == NULL) {
17961 xmlSchemaVErrMemory(NULL,
17962 "allocating IDC list of node-table items", NULL);
17963 return(-1);
17964 }
17965 parBind->sizeNodes = 1;
17966 } else if (duplTop >= parBind->sizeNodes) {
17967 parBind->sizeNodes++;
17968 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
17969 xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
17970 sizeof(xmlSchemaPSVIIDCNodePtr));
17971 if (parBind->nodeTable == NULL) {
17972 xmlSchemaVErrMemory(NULL,
17973 "re-allocating IDC list of node-table items", NULL);
17974 return(-1);
17975 }
17976 }
17977
17978 /*
17979 * Move first old duplicate to last position
17980 * of old duplicates +1.
17981 */
17982 if (parBind->nbDupls != 0) {
17983 parBind->nodeTable[duplTop] =
17984 parBind->nodeTable[parBind->nbNodes + newDupls];
17985 }
17986 /*
17987 * Move first new duplicate to last position of
17988 * new duplicates +1.
17989 */
17990 if (newDupls != 0) {
17991 parBind->nodeTable[parBind->nbNodes + newDupls] =
17992 parBind->nodeTable[parBind->nbNodes];
17993 }
17994 /*
17995 * Append the new node-table entry to the 'new node-table
17996 * entries' section.
17997 */
17998 parBind->nodeTable[parBind->nbNodes] = node;
17999 parBind->nbNodes++;
18000 duplTop++;
18001 }
18002 }
18003 parBind->nbDupls += newDupls;
18004 break;
18005 }
18006 if (parBind->next == NULL)
18007 lastParBind = parBind;
18008 parBind = parBind->next;
18009 }
18010 if (parBind == NULL) {
18011 /*
18012 * No binding for the IDC was found: create a new one and
18013 * copy all node-tables.
18014 */
18015 parBind = xmlSchemaIDCNewBinding(bind->definition);
18016 if (parBind == NULL)
18017 return(-1);
18018
18019 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
18020 xmlMalloc(bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
18021 if (parBind->nodeTable == NULL) {
18022 xmlSchemaVErrMemory(NULL,
18023 "allocating an array of IDC node-table items", NULL);
18024 xmlSchemaIDCFreeBinding(parBind);
18025 return(-1);
18026 }
18027 parBind->sizeNodes = bind->nbNodes;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018028 parBind->nbNodes = bind->nbNodes;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018029 memcpy(parBind->nodeTable, bind->nodeTable,
18030 bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018031 if (*parTable == NULL)
18032 *parTable = parBind;
18033 else
18034 lastParBind->next = parBind;
18035 }
18036 bind = bind->next;
18037 }
18038 return (0);
18039}
18040
18041/**
18042 * xmlSchemaCheckCVCIDCKeyRef:
18043 * @vctxt: the WXS validation context
18044 * @elemDecl: the element declaration
18045 *
18046 * Check the cvc-idc-keyref constraints.
18047 */
18048static int
18049xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
18050{
18051 xmlSchemaPSVIIDCBindingPtr refbind, bind;
18052
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018053 refbind = vctxt->nodeInfo->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018054 /*
18055 * Find a keyref.
18056 */
18057 while (refbind != NULL) {
18058 if (refbind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
18059 int i, j, k, res;
18060 xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
18061 xmlSchemaPSVIIDCKeyPtr refKey, key;
18062
18063 /*
18064 * Find the referred key/unique.
18065 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018066 bind = vctxt->nodeInfo->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018067 do {
18068 if ((xmlSchemaIDCPtr) refbind->definition->ref->item ==
18069 bind->definition)
18070 break;
18071 bind = bind->next;
18072 } while (bind != NULL);
18073
18074 /*
18075 * Search for a matching key-sequences.
18076 */
18077 for (i = 0; i < refbind->nbNodes; i++) {
18078 res = 0;
18079 if (bind != NULL) {
18080 refKeys = refbind->nodeTable[i]->keys;
18081 for (j = 0; j < bind->nbNodes; j++) {
18082 keys = bind->nodeTable[j]->keys;
18083 for (k = 0; k < bind->definition->nbFields; k++) {
18084 refKey = refKeys[k];
18085 key = keys[k];
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018086 res = xmlSchemaAreValuesEqual(vctxt,
18087 key->type, key->compValue,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018088 refKey->type, refKey->compValue);
18089 if (res == 0)
18090 break;
18091 else if (res == -1) {
18092 return (-1);
18093 }
18094 }
18095 if (res == 1) {
18096 /*
18097 * Match found.
18098 */
18099 break;
18100 }
18101 }
18102 }
18103 if (res == 0) {
18104 /* TODO: Report the key-sequence. */
18105 xmlSchemaVCustomErr(vctxt,
18106 XML_SCHEMAV_CVC_IDC,
18107 refbind->nodeTable[i]->node,
18108 (xmlSchemaTypePtr) refbind->definition,
18109 "No matching key-sequence found", NULL);
18110 }
18111 }
18112 }
18113 refbind = refbind->next;
18114 }
18115 return (0);
18116}
18117#endif /* IDC_ENABLED */
18118
18119#ifdef ELEM_INFO_ENABLED
18120/**
18121 * xmlSchemaBeginElement:
18122 * @vctxt: the WXS validation context
18123 *
18124 * Just a temporary workaround to simulate streaming validation
18125 * a bit.
18126 */
18127static void
18128xmlSchemaBeginElement(xmlSchemaValidCtxtPtr vctxt)
18129{
18130 vctxt->depth++;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018131 vctxt->nodeInfo = xmlSchemaGetFreshElemInfo(vctxt, vctxt->depth);
18132 vctxt->nodeInfo->node = vctxt->node;
18133 vctxt->nodeInfo->localName = vctxt->node->name;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018134 if (vctxt->node->ns != NULL)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018135 vctxt->nodeInfo->namespaceName = vctxt->node->ns->href;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018136 else
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018137 vctxt->nodeInfo->namespaceName = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018138}
18139
18140/**
18141 * xmlSchemaEndElement:
18142 * @vctxt: the WXS validation context
18143 *
18144 * Just a temporary workaround to simulate streaming validation
18145 * a bit.
18146 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018147static int
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018148xmlSchemaEndElement(xmlSchemaValidCtxtPtr vctxt)
18149{
18150 if (vctxt->depth < 0) {
18151 /* TODO: raise error? */
18152 vctxt->depth--;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018153 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018154 }
18155#ifdef IDC_ENABLED
18156 /*
18157 * Evaluate the history of changes of active state objects.
18158 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018159 if (xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1)
18160 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018161
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018162 if (vctxt->nodeInfo->value != NULL) {
18163 xmlSchemaFreeValue(vctxt->nodeInfo->value);
18164 vctxt->nodeInfo->value = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018165 }
18166 /*
18167 * TODO: 6 The element information item must be ·valid· with respect to each of
18168 * the {identity-constraint definitions} as per Identity-constraint
18169 * Satisfied (§3.11.4).
18170 */
18171 /*
18172 * Validate IDC keyrefs.
18173 */
18174 xmlSchemaCheckCVCIDCKeyRef(vctxt);
18175#endif
18176
18177 /*
18178 * Merge/free the IDC table.
18179 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018180 if (vctxt->nodeInfo->idcTable != NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018181#ifdef IDC_ENABLED
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018182#ifdef DEBUG_IDC
18183 xmlSchemaDebugDumpIDCTable(stdout,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018184 vctxt->nodeInfo->namespaceName,
18185 vctxt->nodeInfo->localName,
18186 vctxt->nodeInfo->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018187#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018188 if (vctxt->depth > 0) {
18189 /*
18190 * Merge the IDC node table with the table of the parent node.
18191 */
18192 xmlSchemaBubbleIDCNodeTables(vctxt);
18193 }
18194 /*
18195 * TODO: Don't free the PSVI IDC tables if they are
18196 * requested for the PSVI.
18197 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018198 xmlSchemaIDCFreeIDCTable(vctxt->nodeInfo->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018199#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018200 vctxt->nodeInfo->idcTable = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018201 }
18202
18203 /*
18204 * Cleanup IDC matchers.
18205 */
18206#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018207 if (vctxt->nodeInfo->idcMatchers != NULL) {
18208 xmlSchemaIDCFreeMatcherList(vctxt->nodeInfo->idcMatchers);
18209 vctxt->nodeInfo->idcMatchers = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018210 }
18211#endif
18212
18213 /*
18214 * Skip further processing if we are on the validation root.
18215 */
18216 if (vctxt->depth == 0) {
18217 vctxt->depth--;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018218 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018219 }
18220
18221 /*
18222 * Reset the bubbleDepth if needed.
18223 */
18224#ifdef IDC_ENABLED
18225 if (vctxt->aidcs != NULL) {
18226 xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
18227 do {
18228 if (aidc->bubbleDepth == vctxt->depth) {
18229 /*
18230 * A bubbleDepth of a key/unique IDC matches the current
18231 * depth, this means that we are leaving the scope of the
18232 * top-most keyref IDC.
18233 */
18234 aidc->bubbleDepth = -1;
18235 }
18236 aidc = aidc->next;
18237 } while (aidc != NULL);
18238 }
18239#endif
18240 vctxt->depth--;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018241 /*
18242 * Clear the current elemInfo.
18243 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018244 if (vctxt->nodeInfo->value != NULL) {
18245 xmlSchemaFreeValue(vctxt->nodeInfo->value);
18246 vctxt->nodeInfo->value = NULL;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018247 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018248 vctxt->nodeInfo = vctxt->elemInfos[vctxt->depth];
18249 vctxt->node = vctxt->nodeInfo->node;
18250
18251 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018252}
18253
18254#endif /* ELEM_INFO_ENABLED */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018255
18256/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018257 * xmlSchemaValidateElementByDeclaration:
Daniel Veillard4255d502002-04-16 15:50:10 +000018258 * @ctxt: a schema validation context
18259 * @node: the top node.
18260 *
18261 * Validate the content of an element type.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018262 * Validation Rule: Element Locally Valid (Element)
Daniel Veillard4255d502002-04-16 15:50:10 +000018263 *
18264 * Returns 0 if the element is schemas valid, a positive error code
18265 * number otherwise and -1 in case of internal or API error.
18266 */
18267static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018268xmlSchemaValidateElementByDeclaration(xmlSchemaValidCtxtPtr ctxt,
18269 xmlSchemaElementPtr elemDecl)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018270{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018271 xmlNodePtr elem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018272 int ret = 0;
18273 xmlSchemaTypePtr actualType = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018274 xmlAttrPtr attr;
18275 xmlChar *attrValue;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018276 int nilled = 0, elemHasContent = -1;
Daniel Veillard3646d642004-06-02 19:19:14 +000018277
18278 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018279 * This one is called by xmlSchemaValidateElementByWildcardInternal,
18280 * xmlSchemaValidateElementByAnyType and xmlSchemaValidateElement.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018281 * Note that @elemDecl will be the declaration and never the
18282 * reference to a declaration.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018283 */
Daniel Veillard3646d642004-06-02 19:19:14 +000018284
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018285 if (ctxt == NULL) {
18286 xmlSchemaVErr(ctxt, NULL, XML_SCHEMAV_INTERNAL,
18287 "Internal error: xmlSchemaValidateElementByDeclaration, "
18288 "bad arguments.\n",
18289 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018290 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000018291 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018292
18293 elem = ctxt->node;
18294
18295 /*
18296 * cvc-elt (3.3.4) : 1
18297 */
18298 if (elemDecl == NULL) {
18299 xmlSchemaVCustomErr(ctxt,
18300 XML_SCHEMAV_CVC_ELT_1,
18301 elem, NULL,
18302 "No matching declaration available", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018303 /*
18304 * Evaluate IDCs even if an error occured.
18305 */
18306#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018307 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018308 return (-1);
18309#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018310 return (ctxt->err);
18311 }
18312 /*
18313 * cvc-elt (3.3.4) : 2
18314 */
18315 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
18316 xmlSchemaVCustomErr(ctxt,
18317 XML_SCHEMAV_CVC_ELT_2,
18318 elem, NULL,
18319 "The element declaration is abstract", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018320 /*
18321 * Evaluate IDCs even if an error occured.
18322 */
18323#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018324 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018325 return (-1);
18326#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018327 return (ctxt->err);
18328 }
18329
18330 /*
18331 * cvc-elt (3.3.4) : 3
18332 * Handle 'xsi:nil'.
18333 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018334
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018335 attr = xmlHasNsProp(elem, BAD_CAST "nil", xmlSchemaInstanceNs);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018336 if (attr != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018337 attrValue = xmlNodeGetContent((xmlNodePtr) attr);
18338 ctxt->node = (xmlNodePtr) attr;
18339 ctxt->cur = attr->children;
18340 ret = xmlSchemaValidateSimpleTypeValue(ctxt,
18341 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
18342 BAD_CAST attrValue, 1, 1, 1, 1);
18343 ctxt->node = elem;
18344 ctxt->type = (xmlSchemaTypePtr) elemDecl;
18345 if (ret < 0) {
18346 xmlSchemaVCustomErr(ctxt,
18347 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018348 (xmlNodePtr) attr, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018349 "Internal error: xmlSchemaValidateElementByDeclaration, "
18350 "validating the attribute 'xsi:nil'", NULL);
18351 if (attrValue != NULL)
18352 xmlFree(attrValue);
18353 return (-1);
18354 }
18355 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018356 /*
18357 * cvc-elt (3.3.4) : 3.1
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018358 */
18359 xmlSchemaVCustomErr(ctxt,
18360 XML_SCHEMAV_CVC_ELT_3_1,
18361 elem, NULL,
18362 "The element is not 'nillable'", NULL);
18363 } else {
18364 if (xmlStrEqual(BAD_CAST attrValue, BAD_CAST "true") ||
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018365 xmlStrEqual(BAD_CAST attrValue, BAD_CAST "1")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018366 ret = 0;
18367 /*
18368 * cvc-elt (3.3.4) : 3.2.1
18369 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018370 elemHasContent = xmlSchemaHasElemOrCharContent(elem);
18371 if (elemHasContent == 1) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018372 xmlSchemaVCustomErr(ctxt,
18373 XML_SCHEMAV_CVC_ELT_3_2_1,
18374 /* XML_SCHEMAS_ERR_NOTEMPTY, */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018375 elem, (xmlSchemaTypePtr) elemDecl,
18376 "The 'nilled' element must have no character or "
18377 "element content", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018378 ret = XML_SCHEMAV_CVC_ELT_3_2_1;
18379 }
18380 /*
18381 * cvc-elt (3.3.4) : 3.2.2
18382 */
18383 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
18384 (elemDecl->value != NULL)) {
18385 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_CVC_ELT_3_2_2,
18386 /* XML_SCHEMAS_ERR_HAVEDEFAULT, */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018387 elem, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018388 "There is a fixed value constraint defined for "
18389 "the 'nilled' element", NULL);
18390 ret = XML_SCHEMAV_CVC_ELT_3_2_2;
18391 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018392 if (ret == 0)
18393 nilled = 1;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018394 }
18395 }
18396 if (attrValue != NULL)
18397 xmlFree(attrValue);
18398 }
18399
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018400
18401 actualType = elemDecl->subtypes;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018402 /*
18403 * cvc-elt (3.3.4) : 4
18404 * Handle 'xsi:type'.
18405 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018406
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018407 attr = xmlHasNsProp(elem, BAD_CAST "type", xmlSchemaInstanceNs);
18408 if (attr != NULL) {
18409 xmlChar *nsName = NULL, *local = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018410
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018411 /*
18412 * TODO: We should report a *warning* that the type was overriden
18413 * by the instance.
18414 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018415
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018416 /*
18417 * cvc-elt (3.3.4) : 4.1
18418 */
18419 attrValue = xmlNodeGetContent((xmlNodePtr) attr);
18420 ret = xmlSchemaValQNameAcquire(attrValue, attr->parent,
18421 &nsName, &local);
18422 if (ret < 0) {
18423 xmlSchemaVCustomErr(ctxt,
18424 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018425 (xmlNodePtr) attr, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018426 "Internal error: xmlSchemaValidateElementByDeclaration, "
18427 "validating the attribute 'xsi:type'", NULL);;
18428 FREE_AND_NULL(attrValue)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018429 FREE_AND_NULL(nsName)
18430 FREE_AND_NULL(local)
18431 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018432 } else if (ret == 1) {
18433 xmlSchemaVSimpleTypeErr(ctxt,
18434 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
18435 (xmlNodePtr) attr, attrValue,
18436 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME));
18437 } else if (ret == 2) {
18438 xmlSchemaVCustomErr(ctxt,
18439 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
18440 (xmlNodePtr) attr,
18441 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
18442 "The QName value '%s' has no "
18443 "corresponding namespace declaration in scope",
18444 attrValue);
18445 } else {
18446 /*
18447 * cvc-elt (3.3.4) : 4.2
18448 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018449 actualType = xmlSchemaGetType(ctxt->schema, local, nsName);
18450 if (actualType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018451 xmlChar *strA = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018452
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018453 xmlSchemaVCustomErr(ctxt,
18454 XML_SCHEMAV_CVC_ELT_4_2,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018455 (xmlNodePtr) attr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018456 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
18457 "The value %s does not resolve to a type "
18458 "definition",
18459 xmlSchemaFormatNsUriLocal(&strA, nsName, local));
18460 FREE_AND_NULL(strA);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018461 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018462 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018463 * URGENT TODO: cvc-elt (3.3.4) : 4.3 (Type Derivation OK)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018464 */
18465 }
18466 }
18467 FREE_AND_NULL(attrValue)
18468 FREE_AND_NULL(nsName)
18469 FREE_AND_NULL(local)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018470 }
18471 /* TODO: Change the handling of missing types according to
18472 * the spec.
18473 */
18474 if (actualType == NULL) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018475 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018476 XML_SCHEMAV_CVC_TYPE_1,
18477 elem, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018478 "The type definition is absent", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018479 /*
18480 * Evaluate IDCs even if an error occured.
18481 */
18482#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018483 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018484 return (-1);
18485#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018486 return (XML_SCHEMAV_CVC_TYPE_1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018487 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018488
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018489 /*
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018490 * Remember the actual-type definition.
18491 */
18492#ifdef ELEM_INFO_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018493 ctxt->nodeInfo->typeDef = actualType;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018494#endif
18495
18496 /*
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018497 * TODO: Since this should be already checked by the content model automaton,
18498 * and we want to get rid of the XML_SCHEMAS_ERR... types, the error code
18499 * has been changed to XML_SCHEMAV_INTERNAL.
18500 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018501 /*
Daniel Veillard4255d502002-04-16 15:50:10 +000018502 if (child == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000018503 if (decl->minOccurs > 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018504 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018505 XML_SCHEMAS_ERR_MISSING,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018506 "Element %s: missing child %s\n",
18507 node->name, decl->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018508 }
18509 return (ctxt->err);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018510 }
18511 */
Daniel Veillard4255d502002-04-16 15:50:10 +000018512 /*
18513 * Verify the element matches
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018514 * TODO, FIXME: Can this still happen here? Isn't this already checked
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018515 * by the content model automaton?
Daniel Veillardc0826a72004-08-10 14:17:33 +000018516 if (!xmlStrEqual(child->name, decl->name)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018517 xmlSchemaVErr3(ctxt, node, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018518 XML_SCHEMAS_ERR_WRONGELEM,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018519 "Element %s: missing child %s found %s\n",
18520 node->name, decl->name, child->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018521 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000018522 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018523 */
18524 if (elemHasContent == -1)
18525 elemHasContent = xmlSchemaHasElemOrCharContent(elem);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018526
18527 /*
18528 * IDC: Register identity-constraint XPath matchers.
18529 */
18530#ifdef IDC_ENABLED
18531 if (elemDecl->idcs != NULL)
18532 xmlSchemaIDCRegisterMatchers(ctxt, elemDecl);
18533 /*
18534 * Evaluate IDCs.
18535 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018536 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018537 return (-1);
18538#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018539 /*
18540 * cvc-elt (3.3.4) : 5
18541 * The appropriate case among the following must be true:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018542 */
Daniel Veillard4255d502002-04-16 15:50:10 +000018543 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018544 * cvc-elt (3.3.4) : 5.1
18545 * If the declaration has a {value constraint},
18546 * the item has neither element nor character [children] and
18547 * clause 3.2 has not applied, then all of the following must be true:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018548 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018549 if ((elemHasContent == 0) && (nilled == 0) && (elemDecl->value != NULL)) {
18550 /*
18551 * cvc-elt (3.3.4) : 5.1.1
18552 * If the ·actual type definition· is a ·local type definition·
18553 * then the canonical lexical representation of the {value constraint}
18554 * value must be a valid default for the ·actual type definition· as
18555 * defined in Element Default Valid (Immediate) (§3.3.6).
18556 */
18557 /*
18558 * NOTE: 'local' above means types aquired by xsi:type.
18559 */
18560 ret = 0;
18561 if (actualType != elemDecl->subtypes) {
18562 xmlSchemaCreatePCtxtOnVCtxt(ctxt);
18563 ret = xmlSchemaCheckCOSValidDefault(ctxt->pctxt, ctxt, actualType,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018564 elemDecl->value, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018565 if (ret < 0) {
18566 xmlSchemaVCustomErr(ctxt,
18567 XML_SCHEMAV_INTERNAL,
18568 elem, actualType,
18569 "Internal error: xmlSchemaValidateElementByDeclaration, "
18570 "validating a default value", NULL);
18571 return (-1);
18572 }
18573 }
18574 /*
18575 * cvc-elt (3.3.4) : 5.1.2
18576 * The element information item with the canonical lexical
18577 * representation of the {value constraint} value used as its
18578 * ·normalized value· must be ·valid· with respect to the
18579 * ·actual type definition· as defined by Element Locally Valid (Type)
18580 * (§3.3.4).
18581 */
18582 /*
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018583 * Disable validation of the simple content, if it was already
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018584 * done above.
18585 */
18586 if (ret == 0) {
18587 if (actualType != elemDecl->subtypes)
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018588 ret = xmlSchemaValidateElementByType(ctxt, actualType, 0, 0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018589 else
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018590 ret = xmlSchemaValidateElementByType(ctxt, actualType, 0, 1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018591 ctxt->node = elem;
18592 if (ret < 0) {
18593 xmlSchemaVCustomErr(ctxt,
18594 XML_SCHEMAV_INTERNAL,
18595 elem, actualType,
18596 "Internal error: xmlSchemaValidateElementByDeclaration, "
18597 "validating against the type", NULL);
18598 return (-1);
18599 }
18600 /*
18601 * PSVI: Create a text node on the instance element.
18602 */
18603 if (ctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
18604 xmlNodePtr textChild;
18605
18606 textChild = xmlNewText(elemDecl->value);
18607 if (textChild == NULL) {
18608 xmlSchemaVCustomErr(ctxt,
18609 XML_SCHEMAV_INTERNAL,
18610 elem, actualType,
18611 "Internal error: xmlSchemaValidateElementByDeclaration, "
18612 "could not create a default text node for the instance",
18613 NULL);
18614 } else
18615 xmlAddChild(elem, textChild);
18616 }
18617 }
18618
18619 } else {
18620 /*
18621 * 5.2.1 The element information item must be ·valid· with respect
18622 * to the ·actual type definition· as defined by Element Locally
18623 * Valid (Type) (§3.3.4).
18624 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018625 ret = xmlSchemaValidateElementByType(ctxt, actualType, nilled, 1);
18626 /*
18627 * Consume the computed value for IDCs, ect. Note that default
18628 * values are not supported yet.
18629 */
18630#ifdef ELEM_INFO_ENABLED
18631 if (ctxt->value != NULL) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018632 ctxt->nodeInfo->value = ctxt->value;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018633 ctxt->value = NULL;
18634 }
18635#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018636 ctxt->node = elem;
18637 if (ret < 0) {
18638 xmlSchemaVCustomErr(ctxt,
18639 XML_SCHEMAV_INTERNAL,
18640 elem, actualType,
18641 "Internal error: xmlSchemaValidateElementByDeclaration, "
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000018642 "calling validation by type", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018643 return (-1);
18644 }
18645 /*
18646 * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
18647 * not applied, all of the following must be true:
18648 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018649 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) && (nilled == 0)) {
18650 /*
18651 * 5.2.2.1 The element information item must have no element
18652 * information item [children].
18653 *
18654 * TODO REDUNDANT: If the actual type exists, the above call to
18655 * xmlSchemaValidateElementByType will already check for element
18656 * nodes.
18657 */
18658 if (xmlSchemaHasElemContent(elem)) {
18659 xmlSchemaVCustomErr(ctxt,
18660 XML_SCHEMAV_CVC_ELT_5_2_2_1,
18661 elem, (xmlSchemaTypePtr) elemDecl,
18662 "Elements in the content are not allowed if it is "
18663 "constrained by a fixed value", NULL);
18664 } else {
18665 /*
18666 * 5.2.2.2 The appropriate case among the following must
18667 * be true:
18668 */
18669
18670 if (actualType->contentType == XML_SCHEMA_CONTENT_MIXED) {
18671 xmlChar *value;
18672 /*
18673 * 5.2.2.2.1 If the {content type} of the ·actual type
18674 * definition· is mixed, then the *initial value* of the
18675 * item must match the canonical lexical representation
18676 * of the {value constraint} value.
18677 *
18678 * ... the *initial value* of an element information
18679 * item is the string composed of, in order, the
18680 * [character code] of each character information item in
18681 * the [children] of that element information item.
18682 */
18683 value = xmlNodeListGetString(elem->doc, elem->children, 1);
18684 if (! xmlStrEqual(BAD_CAST value, elemDecl->value)) {
18685 /*
18686 * TODO: Report invalid & expected values as well.
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018687 * TODO: Implement the canonical stuff.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018688 */
18689 xmlSchemaVCustomErr(ctxt,
18690 XML_SCHEMAV_CVC_ELT_5_2_2_2_1,
18691 elem, (xmlSchemaTypePtr) elemDecl,
18692 "The value does not match the cononical "
18693 "lexical representation of the fixed constraint",
18694 NULL);
18695 }
18696 if (value != NULL)
18697 xmlFree(value);
18698 } else if ((actualType->contentType ==
18699 XML_SCHEMA_CONTENT_SIMPLE) ||
18700 (actualType->contentType == XML_SCHEMA_CONTENT_BASIC)) {
18701 xmlChar *value;
18702
18703 /*
18704 * 5.2.2.2.2 If the {content type} of the ·actual type
18705 * definition· is a simple type definition, then the
18706 * *actual value* of the item must match the canonical
18707 * lexical representation of the {value constraint} value.
18708 */
18709 /*
18710 * TODO: *actual value* is the normalized value, impl. this.
18711 * TODO: Report invalid & expected values as well.
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018712 * TODO: Implement the canonical stuff.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018713 *
18714 */
18715 value = xmlNodeListGetString(elem->doc, elem->children, 1);
18716 if (! xmlStrEqual(BAD_CAST value, elemDecl->value)) {
18717 xmlSchemaVCustomErr(ctxt,
18718 XML_SCHEMAV_CVC_ELT_5_2_2_2_2,
18719 elem, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018720 "The normalized value does not match the canonical "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018721 "lexical representation of the fixed constraint",
18722 NULL);
18723 }
18724 if (value != NULL)
18725 xmlFree(value);
18726
18727 }
18728 /*
18729 * TODO: What if the content type is not 'mixed' or simple?
18730 */
18731
18732 }
18733
18734 }
18735 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018736 /*
18737 * TODO: 7 If the element information item is the ·validation root·, it must be
18738 * ·valid· per Validation Root Valid (ID/IDREF) (§3.3.4).
18739 */
18740
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018741 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000018742}
18743
Daniel Veillard4255d502002-04-16 15:50:10 +000018744/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018745 * xmlSchemaValidateElementByWildcardInternal:
Daniel Veillardc0826a72004-08-10 14:17:33 +000018746 * @ctxt: a schema validation context
18747 * @node: the top node.
18748 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018749 * Represents the recursive portion of xmlSchemaValidateElementByWildcard.
18750 * Not intended to be used by other functions.
Daniel Veillardc0826a72004-08-10 14:17:33 +000018751 *
18752 * Returns 0 if the element is valid, a positive error code
18753 * number otherwise and -1 in case of an internal error.
18754 */
18755static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018756xmlSchemaValidateElementByWildcardInternal(xmlSchemaValidCtxtPtr ctxt,
18757 xmlSchemaWildcardPtr wild,
18758 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +000018759{
18760 const xmlChar *uri;
18761 int ret = 0;
18762 xmlNodePtr child;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018763
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018764 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018765 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
18766 if (ret == -1) {
18767 xmlSchemaVCustomErr(ctxt,
18768 XML_SCHEMAV_INTERNAL,
18769 ctxt->node, NULL,
18770 "Internal error: xmlSchemaValidateElement, "
18771 "assembling schema by xsi", NULL);
18772 return (-1);
18773 }
18774 /*
18775 * NOTE: We won't react on schema parser errors here.
18776 * TODO: But a warning would be nice.
18777 */
18778 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000018779 if (wild->processContents != XML_SCHEMAS_ANY_SKIP) {
18780 xmlSchemaElementPtr decl = NULL;
18781
18782 if (node->ns != NULL)
18783 decl = xmlHashLookup3(ctxt->schema->elemDecl,
18784 node->name, node->ns->href, NULL);
18785 else
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018786 decl = xmlHashLookup3(ctxt->schema->elemDecl, node->name,
18787 NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018788 if (decl != NULL) {
18789 ctxt->node = node;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018790 ret = xmlSchemaValidateElementByDeclaration(ctxt, decl);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018791 if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018792 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000018793 "Internal error: xmlSchemaValidateAnyInternal, "
18794 "validating an element in the context of a wildcard.",
18795 NULL, NULL);
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +000018796 }
18797 return (ret);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018798 } else if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
18799 /* TODO: Change to proper error code. */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018800 xmlSchemaVWildcardErr(ctxt, XML_SCHEMAV_CVC_ELT_1,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018801 node, wild, "No matching global declaration available");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018802 /*
18803 * Evaluate IDCs even if a validation error occured.
18804 */
18805#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018806 if (xmlSchemaXPathEvaluate(ctxt,XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018807 return(-1);
18808#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +000018809 return (ctxt->err);
18810 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018811 /*
18812 * Evaluate IDCs; we need to know if an IDC field resolves to
18813 * such a node. This node has no type definition and will
18814 * definitely result in an IDC validation error if an IDC field
18815 * resolves.
18816 */
18817#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018818 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018819 return(-1);
18820#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +000018821 }
18822 if (node->children != NULL) {
18823 child = node->children;
18824 do {
18825 if (child->type == XML_ELEMENT_NODE) {
18826 if (child->ns != NULL)
18827 uri = child->ns->href;
18828 else
18829 uri = NULL;
18830 if (xmlSchemaMatchesWildcardNs(wild, uri) == 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018831 /* TODO: error code. */
18832 xmlSchemaVWildcardErr(ctxt, XML_SCHEMAV_ELEMENT_CONTENT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000018833 child, wild,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018834 "The namespace of the element is not allowed");
Daniel Veillardc0826a72004-08-10 14:17:33 +000018835 return (ctxt->err);
18836 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018837#ifdef ELEM_INFO_ENABLED
18838 ctxt->node = child;
18839 xmlSchemaBeginElement(ctxt);
18840#endif
18841 /*
18842 * Recurse over the children.
18843 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018844 ret = xmlSchemaValidateElementByWildcardInternal(ctxt,
18845 wild, child);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018846 if (ret == -1)
18847 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018848#ifdef ELEM_INFO_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018849 if (xmlSchemaEndElement(ctxt) == -1)
18850 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018851#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +000018852 if (ret != 0)
18853 return (ret);
18854 }
18855 child = child->next;
18856 } while (child != NULL);
18857 }
18858 return (0);
18859}
18860
18861/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018862 * xmlSchemaValidateElementContByWildcard:
Daniel Veillardc0826a72004-08-10 14:17:33 +000018863 * @ctxt: a schema validation context
18864 *
18865 * Returns 0 if the element is valid, a positive error code
18866 * number otherwise and -1 in case of an internal or API error.
18867 */
18868static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018869xmlSchemaValidateElementByWildcard(xmlSchemaValidCtxtPtr ctxt,
18870 xmlSchemaTypePtr type)
Daniel Veillardc0826a72004-08-10 14:17:33 +000018871{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018872 if ((type == NULL) || (type->type != XML_SCHEMA_TYPE_ANY) ||
18873 (ctxt->node == NULL)) {
18874 xmlSchemaVCustomErr(ctxt,
18875 XML_SCHEMAV_INTERNAL, ctxt->node, NULL,
18876 "Internal error: xmlSchemaValidateElementByWildcard, "
18877 "bad arguments", NULL);
18878 return (-1);
18879 }
18880 return(xmlSchemaValidateElementByWildcardInternal(ctxt,
18881 type->attributeWildcard, ctxt->node));
Daniel Veillardc0826a72004-08-10 14:17:33 +000018882}
18883
18884/**
William M. Brack2f2a6632004-08-20 23:09:47 +000018885 * xmlSchemaValidateAnyTypeContent:
18886 * @ctxt: a schema validation context
18887 * @node: the current element
18888 *
18889 * This one validates the content of an element of the type
18890 * 'anyType'. The process contents of the wildcard of 'anyType' is "lax",
18891 * thus elements in the subtree will be validated, if a corresponding
18892 * declaration in the schema exists.
18893 *
18894 * Returns 0 if the element and its subtree is valid, a positive error code
18895 * otherwise and -1 in case of an internal or API error.
18896 */
18897static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018898xmlSchemaValidateElementByAnyType(xmlSchemaValidCtxtPtr ctxt,
18899 xmlSchemaTypePtr type)
William M. Brack2f2a6632004-08-20 23:09:47 +000018900{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018901 xmlSchemaTypePtr oldtype;
18902 xmlNodePtr top, cur;
18903 xmlSchemaElementPtr decl;
William M. Brack2f2a6632004-08-20 23:09:47 +000018904 int skipContent, ret;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018905
18906 if ((type == NULL) || (ctxt->node == NULL))
18907 return (-1);
18908
18909 if (ctxt->node->children == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +000018910 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018911
18912 oldtype = ctxt->type;
18913 top = ctxt->node;
18914 /*
18915 * STREAM: Child nodes are processed.
18916 */
18917 cur = ctxt->node->children;
18918 while (cur != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +000018919 skipContent = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018920 if (cur->type == XML_ELEMENT_NODE) {
William M. Brack2f2a6632004-08-20 23:09:47 +000018921 /*
18922 * The process contents of the wildcard is "lax", thus
18923 * we need to validate the element if a declaration
18924 * exists.
18925 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018926 if (cur->ns != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +000018927 decl = xmlHashLookup3(ctxt->schema->elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018928 cur->name, cur->ns->href, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000018929 else
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018930 decl = xmlHashLookup3(ctxt->schema->elemDecl, cur->name, NULL, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000018931 if (decl != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018932 ctxt->node = cur;
18933 ret = xmlSchemaValidateElementByDeclaration(ctxt, decl);
18934 ctxt->node = top;
William M. Brack2f2a6632004-08-20 23:09:47 +000018935 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018936 xmlSchemaVErr(ctxt, cur, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000018937 "Internal error: xmlSchemaValidateAnyTypeContent, "
18938 "validating an element in the context of a wildcard.",
18939 NULL, NULL);
18940 return (ret);
18941 } else if (ret > 0)
18942 return (ret);
18943 skipContent = 1;
18944 }
18945 }
18946 /*
18947 * Browse the full subtree, deep first.
18948 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018949 if ((skipContent == 0) && (cur->children != NULL)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000018950 /* deep first */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018951 cur = cur->children;
18952 } else if ((cur != top) && (cur->next != NULL)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000018953 /* then siblings */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018954 cur = cur->next;
18955 } else if (cur != top) {
William M. Brack2f2a6632004-08-20 23:09:47 +000018956 /* go up to parents->next if needed */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018957 while (cur != top) {
18958 if (cur->parent != NULL)
18959 cur = cur->parent;
18960 if ((cur != top) && (cur->next != NULL)) {
18961 cur = cur->next;
William M. Brack2f2a6632004-08-20 23:09:47 +000018962 break;
18963 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018964 if (cur->parent == NULL) {
18965 cur = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000018966 break;
18967 }
18968 }
18969 /* exit condition */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018970 if (cur == top)
18971 cur = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000018972 } else
18973 break;
18974 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018975 ctxt->type = oldtype;
William M. Brack2f2a6632004-08-20 23:09:47 +000018976 return (0);
18977}
18978
18979/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018980 * xmlSchemaValidateElementByComplexType:
Daniel Veillard4255d502002-04-16 15:50:10 +000018981 * @ctxt: a schema validation context
18982 * @node: the top node.
18983 *
18984 * Validate the content of an element expected to be a complex type type
18985 * xmlschema-1.html#cvc-complex-type
18986 * Validation Rule: Element Locally Valid (Complex Type)
18987 *
18988 * Returns 0 if the element is schemas valid, a positive error code
Daniel Veillard01fa6152004-06-29 17:04:39 +000018989 * number otherwise and -1 in case of internal or API error.
18990 * Note on reported errors: Although it might be nice to report
18991 * the name of the simple/complex type, used to validate the content
18992 * of a node, it is quite unnecessary: for global defined types
18993 * the local name of the element is equal to the NCName of the type,
18994 * for local defined types it makes no sense to output the internal
18995 * computed name of the type. TODO: Instead, one should attach the
18996 * struct of the type involved to the error handler - this allows
18997 * the report of any additional information by the user.
Daniel Veillard4255d502002-04-16 15:50:10 +000018998 */
18999static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019000xmlSchemaValidateElementByComplexType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019001 xmlSchemaTypePtr type,
19002 int valSimpleContent)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019003{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019004 xmlSchemaTypePtr oldtype;
19005 xmlNodePtr elem, child;
Daniel Veillard01fa6152004-06-29 17:04:39 +000019006 int ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +000019007 const xmlChar *nsUri;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019008 xmlSchemaAttrStatePtr attrs = NULL, attrTop = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000019009
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019010 if ((ctxt == NULL) || (type->type != XML_SCHEMA_TYPE_COMPLEX))
19011 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000019012
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019013 oldtype = ctxt->type;
19014 ctxt->type = type;
19015 elem = ctxt->node;
19016
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019017 /*
19018 * Verify the attributes
19019 */
19020 /*
19021 * TODO: This "attrTop" thing is not needed any more.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019022 */
19023 /* NOTE: removed, since a check for abstract is
19024 * done in the cvc-type constraint.
19025 *
19026 *
19027 * if (type->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
19028 * xmlSchemaVComplexTypeErr(ctxt,
19029 * XML_SCHEMAV_CVC_COMPLEX_TYPE_1,
19030 * elem, type,
19031 * "The type definition is abstract");
19032 * return (XML_SCHEMAV_CVC_COMPLEX_TYPE_1);
19033 *}
19034 */
19035
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019036 attrs = ctxt->attr;
19037 attrTop = ctxt->attrTop;
19038 /*
19039 * STREAM: Attribute nodes are processed.
19040 */
19041 xmlSchemaRegisterAttributes(ctxt, elem->properties);
19042 xmlSchemaValidateAttributes(ctxt, elem, type);
19043 if (ctxt->attr != NULL)
19044 xmlSchemaFreeAttributeStates(ctxt->attr);
19045 ctxt->attr = attrs;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019046 ctxt->attrTop = attrTop;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019047
19048 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019049 * TODO: This one creates a regexp even if no content
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019050 * model was defined. Somehow ->contModel is always not NULL
19051 * for complex types, even if they are empty.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019052 * TODO: Check if the obove still occurs.
19053 */
Daniel Veillard4255d502002-04-16 15:50:10 +000019054 switch (type->contentType) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000019055 case XML_SCHEMA_CONTENT_EMPTY: {
19056 /*
19057 * 1 If the {content type} is empty, then the element information
19058 * item has no character or element information item [children].
Daniel Veillard3646d642004-06-02 19:19:14 +000019059 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000019060 /*
19061 * TODO: Is the entity stuff correct?
19062 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019063 if (xmlSchemaHasElemOrCharContent(elem) == 1) {
William M. Brack2f2a6632004-08-20 23:09:47 +000019064 xmlSchemaVComplexTypeErr(ctxt,
19065 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019066 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000019067 "Character or element content is not allowed, "
19068 "because the content type is empty");
Daniel Veillard01fa6152004-06-29 17:04:39 +000019069 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019070 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000019071 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019072 case XML_SCHEMA_CONTENT_MIXED:
19073 if ((type->subtypes == NULL) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019074 (type->baseType->builtInType == XML_SCHEMAS_ANYTYPE)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019075 /*
19076 * The type has 'anyType' as its base and no content model
19077 * is defined -> use 'anyType' as the type to validate
19078 * against.
19079 */
19080 ret = xmlSchemaValidateElementByAnyType(ctxt, type->baseType);
19081 /* TODO: Handle -1. */
19082 break;
19083 }
19084 /* No break on purpose. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000019085 case XML_SCHEMA_CONTENT_ELEMENTS:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019086 {
19087 xmlRegExecCtxtPtr oldregexp = NULL;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019088 xmlChar *values[10];
19089 int terminal, nbval = 10, nbneg;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019090
19091 /*
19092 * Content model check initialization.
19093 */
19094 if (type->contModel != NULL) {
19095 oldregexp = ctxt->regexp;
19096 ctxt->regexp = xmlRegNewExecCtxt(type->contModel,
19097 (xmlRegExecCallbacks)
19098 xmlSchemaValidateCallback, ctxt);
19099#ifdef DEBUG_AUTOMATA
19100 xmlGenericError(xmlGenericErrorContext, "====> %s\n", elem->name);
19101#endif
19102 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019103 /*
19104 * STREAM: Children are processed.
19105 */
19106 child = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000019107 while (child != NULL) {
19108 if (child->type == XML_ELEMENT_NODE) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000019109 if (child->ns != NULL)
19110 nsUri = child->ns->href;
19111 else
19112 nsUri = NULL;
19113 ret = xmlRegExecPushString2(ctxt->regexp,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019114 child->name, nsUri, child);
19115 if (ctxt->err == XML_SCHEMAV_INTERNAL)
19116 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019117 /*
19118 * URGENT TODO: Could we anchor an error report
19119 * here to notify of invalid elements?
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019120 * TODO: Perhaps it would be better to report
19121 * only the first erroneous element and then break.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019122 */
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019123#ifdef DEBUG_AUTOMATA
Daniel Veillard01fa6152004-06-29 17:04:39 +000019124 if (ret < 0)
19125 xmlGenericError(xmlGenericErrorContext,
19126 " --> %s Error\n", child->name);
William M. Bracke7091952004-05-11 15:09:58 +000019127 else
19128 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard01fa6152004-06-29 17:04:39 +000019129 " --> %s\n", child->name);
19130#endif
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019131 if (ret < 0) {
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019132 xmlRegExecErrInfo(ctxt->regexp, NULL, &nbval, &nbneg,
19133 &values[0], &terminal);
19134 xmlSchemaVComplexTypeElemErr(ctxt,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019135 XML_SCHEMAV_ELEMENT_CONTENT,
19136 child, NULL/* type */,
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019137 "This element is not expected",
19138 nbval, nbneg, values);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019139 ret = 1;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019140 /*
19141 * Note that this will skip further validation of the
19142 * content.
19143 */
19144 break;
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019145 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000019146 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) &&
19147 /*
19148 * TODO: Ask Daniel if this are all character nodes.
19149 */
19150 (((child->type == XML_TEXT_NODE) && (!IS_BLANK_NODE(child))) ||
19151 (child->type == XML_ENTITY_NODE) ||
19152 (child->type == XML_ENTITY_REF_NODE) ||
19153 (child->type == XML_CDATA_SECTION_NODE))) {
19154 /*
19155 * 2.3 If the {content type} is element-only, then the
19156 * element information item has no character information
19157 * item [children] other than those whose [character
19158 * code] is defined as a white space in [XML 1.0 (Second
19159 * Edition)].
19160 */
William M. Brack2f2a6632004-08-20 23:09:47 +000019161 xmlSchemaVComplexTypeErr(ctxt,
19162 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019163 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000019164 "Character content is not allowed, "
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019165 "because the content type is element-only");
19166 ret = 1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000019167 break;
19168 }
19169 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019170 }
19171 /*
19172 * Content model check finalization.
19173 */
19174 if (type->contModel != NULL) {
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019175 if (ret == 0) {
19176 xmlRegExecNextValues(ctxt->regexp, &nbval, &nbneg,
19177 &values[0], &terminal);
19178 if (nbval + nbneg != 0) {
19179 /*
19180 * If a next value still exists, I does not have to
19181 * mean that there's an element missing, since it
19182 * might be an optional element. So double check it.
19183 */
19184 ret = xmlRegExecPushString(ctxt->regexp,
19185 NULL, NULL);
19186 if (ret <= 0) {
19187 ret = 1;
19188 xmlSchemaVComplexTypeElemErr(ctxt,
19189 XML_SCHEMAV_ELEMENT_CONTENT,
19190 elem, type, "Missing child element(s)",
19191 nbval, nbneg, values);
19192 } else
19193 ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019194#ifdef DEBUG_AUTOMATA
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019195 xmlGenericError(xmlGenericErrorContext,
19196 "====> %s : %d\n", elem->name, ret);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019197#endif
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019198 }
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019199#ifdef DEBUG_CONTENT
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019200 if (ret == 0)
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019201 xmlGenericError(xmlGenericErrorContext,
19202 "Element %s content check succeeded\n",
19203 elem->name);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019204#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019205 }
19206 xmlRegFreeExecCtxt(ctxt->regexp);
19207 ctxt->regexp = oldregexp;
19208 }
19209 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000019210 break;
19211 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019212 case XML_SCHEMA_CONTENT_BASIC:
19213 /*
19214 * If the simple content was already validated
19215 * (e.g. a default value), the content need not
19216 * to be validated again.
19217 */
19218 if (valSimpleContent == 1) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000019219 xmlChar *value = NULL;
19220 /*
19221 * We hit a complexType with a simpleContent resolving
19222 * to a user derived or built-in simple type.
William M. Brack2f2a6632004-08-20 23:09:47 +000019223 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000019224 /*
19225 * 2.2 If the {content type} is a simple type definition,
19226 * then the element information item has no element
19227 * information item [children], and the ·normalized value·
19228 * of the element information item is ·valid· with respect
19229 * to that simple type definition as defined by String
19230 * Valid (§3.14.4).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019231 */
19232 /*
19233 * STREAM: Children are processed.
19234 */
19235 child = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000019236 while (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019237 /*
19238 * TODO: Could the entity stuff produce elements
19239 * as well?
19240 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000019241 if (child->type == XML_ELEMENT_NODE) {
William M. Brack2f2a6632004-08-20 23:09:47 +000019242 xmlSchemaVComplexTypeErr(ctxt,
19243 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019244 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000019245 "Element content is not allowed, because "
19246 "the content type is a simple type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000019247 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
19248 break;
19249 }
19250 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019251 }
19252 ctxt->node = elem;
19253 ctxt->cur = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000019254 if (ret == 0) {
19255 /*
19256 * Validate the character content against a simple type.
Daniel Veillard3646d642004-06-02 19:19:14 +000019257 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019258 /*
19259 * STREAM: Children are processed.
19260 */
19261 if (elem->children == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000019262 value = NULL;
19263 else
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019264 value = xmlNodeGetContent(elem);
19265 /*
19266 * URGENT TODO: Should facets for the simple type validation be
19267 * disabled, if the derivation of facets for complex types
19268 * is implemented?
19269 */
19270 /*
19271 * NOTE: This call won't check the correct types of the
19272 * content nodes, since this should be done here.
19273 */
19274 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type, value, 1, 1, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000019275 if (ret > 0) {
19276 /*
19277 * NOTE: Although an error will be reported by
19278 * xmlSchemaValidateSimpleTypeValue, the spec wants
19279 * a specific complex type error to be reported
19280 * additionally.
19281 */
19282 xmlSchemaVComplexTypeErr(ctxt,
19283 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019284 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000019285 "The character content is not valid");
Daniel Veillard01fa6152004-06-29 17:04:39 +000019286 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
19287 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019288 xmlSchemaVErr(ctxt, elem, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000019289 "Internal error: xmlSchemaValidateComplexType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000019290 "Element '%s': Error while validating character "
19291 "content against complex type '%s'.\n",
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019292 elem->name, type->name);
19293 if (value != NULL)
19294 xmlFree(value);
19295 ctxt->type = oldtype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000019296 return (-1);
19297 }
William M. Brack2f2a6632004-08-20 23:09:47 +000019298 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000019299 if (ret == 0) {
19300 /*
19301 * Apply facets of the complexType. Be sure to pass the
19302 * built-in type to xmlSchemaValidateFacetsInternal.
19303 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019304 /* URGENT TODO: I don't know yet if the facets of the simple type
Daniel Veillard01fa6152004-06-29 17:04:39 +000019305 * are used, or if the facets, defined by this complex type,
19306 * are to be used only. This here applies both facet sets.
19307 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000019308
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019309 ret = xmlSchemaValidateFacetsInternal(ctxt,
19310 type, value, 0, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000019311 if (ret > 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +000019312 xmlSchemaVComplexTypeErr(ctxt,
19313 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019314 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000019315 "The character content is not valid");
Daniel Veillard01fa6152004-06-29 17:04:39 +000019316 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
19317 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019318 xmlSchemaVErr(ctxt, elem, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000019319 "Internal error: xmlSchemaValidateComplexType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000019320 "Element '%s': Error while validating character "
19321 "content against complex type '%s'; failed to "
Daniel Veillard01fa6152004-06-29 17:04:39 +000019322 "apply facets.\n",
19323 type->name, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019324 if (value != NULL)
19325 xmlFree(value);
19326 ctxt->type = oldtype;
19327 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000019328 }
19329 }
19330 if (value != NULL)
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019331 xmlFree(value);
19332
Daniel Veillard01fa6152004-06-29 17:04:39 +000019333 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019334 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019335 default:
19336 TODO xmlGenericError(xmlGenericErrorContext,
19337 "unimplemented content type %d\n",
19338 type->contentType);
Daniel Veillard4255d502002-04-16 15:50:10 +000019339 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019340 ctxt->type = oldtype;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019341 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000019342}
19343
19344/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019345 * xmlSchemaValidateElementByType:
Daniel Veillard4255d502002-04-16 15:50:10 +000019346 * @ctxt: a schema validation context
19347 * @elem: an element
19348 * @type: the list of type declarations
19349 *
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019350 * Validation Rule: Element Locally Valid (Type).
Daniel Veillard4255d502002-04-16 15:50:10 +000019351 *
19352 * Returns 0 if the element is schemas valid, a positive error code
19353 * number otherwise and -1 in case of internal or API error.
19354 */
19355static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019356xmlSchemaValidateElementByType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019357 xmlSchemaTypePtr type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019358 int isNil,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019359 int valSimpleContent)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019360{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019361 int ret;
Daniel Veillard4255d502002-04-16 15:50:10 +000019362
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019363
19364 if ((ctxt == NULL) || (type == NULL)) {
19365 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_INTERNAL, NULL, NULL,
19366 "Internal error: xmlSchemaValidateElementByType, "
19367 "bad arguments", NULL);
19368 return (-1);
19369 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019370 /*
19371 * This one is called by "xmlSchemaValidateElementByDeclaration".
19372 * It will forward to the proper validation
19373 * procedures for the given type.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019374 */
19375 if (type == NULL) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019376 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019377 XML_SCHEMAV_CVC_TYPE_1,
19378 ctxt->node, NULL,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019379 "The type definition is absent", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019380 return (XML_SCHEMAV_CVC_TYPE_1);
19381 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019382
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019383 if (type->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019384 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019385 XML_SCHEMAV_CVC_TYPE_2,
19386 ctxt->node, type,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019387 "The type definition is abstract", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019388 return (XML_SCHEMAV_CVC_TYPE_2);
19389 }
19390
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019391 switch (type->type) {
19392 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019393 ret = xmlSchemaValidateElementByComplexType(ctxt, type,
19394 valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019395 break;
19396 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019397 ret = xmlSchemaValidateElementBySimpleType(ctxt, type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019398 isNil, valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019399 break;
19400 case XML_SCHEMA_TYPE_BASIC:
19401 if (type->builtInType == XML_SCHEMAS_ANYTYPE)
19402 ret = xmlSchemaValidateElementByAnyType(ctxt, type);
19403 else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019404 ret = xmlSchemaValidateElementBySimpleType(ctxt, type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019405 isNil, valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019406 break;
19407 default:
19408 ret = -1;
19409 break;
19410 }
19411 if (ret == -1)
19412 return (-1);
19413 else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019414 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000019415}
19416
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019417static int
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019418xmlSchemaPostCreateVal(xmlSchemaValidCtxtPtr vctxt,
19419 const xmlChar *value,
19420 xmlSchemaValPtr *val)
19421{
19422 xmlSchemaTypePtr prim;
19423
19424 if (val == NULL) {
19425 xmlSchemaVErr(vctxt, vctxt->nodeInfo->node,
19426 XML_SCHEMAV_INTERNAL,
19427 "Internal error: xmlSchemaPostCreateVal, "
19428 "bad arguments", NULL, NULL);
19429 return (-1);
19430 }
19431 /*
19432 * Only string or anySimpleType values are expected to be post-created.
19433 */
19434 prim = xmlSchemaGetPrimitiveType(vctxt->nodeInfo->typeDef);
19435 if ((prim->builtInType == XML_SCHEMAS_STRING) ||
19436 (prim->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
19437 {
19438#if 0
19439 builtIn = xmlSchemaGetBuiltInTypeAncestor(vctxt->nodeInfo->typeDef);
19440#endif
19441 if (value == NULL)
19442 /* TODO: Can this happen at all? */
19443 *val = xmlSchemaNewStringValue(XML_SCHEMAS_STRING,
19444 xmlStrdup(BAD_CAST ""));
19445 else
19446 *val = xmlSchemaNewStringValue(XML_SCHEMAS_STRING, value);
19447 if ((*val) == NULL) {
19448 xmlSchemaVErr(vctxt, vctxt->nodeInfo->node,
19449 XML_SCHEMAV_INTERNAL,
19450 "Internal error: xmlSchemaPostCreateVal, "
19451 "failed to create the value", NULL, NULL);
19452 return (-1);
19453 }
19454 return (0);
19455 }
19456 xmlSchemaVErr(vctxt, vctxt->nodeInfo->node,
19457 XML_SCHEMAV_INTERNAL,
19458 "Internal error: xmlSchemaPostCreateVal, "
19459 "the given type is not supported", NULL, NULL);
19460 return (-1);
19461}
19462
19463static int
19464xmlSchemaCheckAttrLocallyValid(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019465 xmlSchemaAttrStatePtr state)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019466{
19467 xmlChar *value;
19468 const xmlChar *defValue;
19469 xmlSchemaValPtr defVal;
19470 int fixed;
19471 int ret;
19472
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019473 if (vctxt->attrInfo->typeDef == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019474 state->state = XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED;
19475 return (XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED);
19476 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019477 vctxt->node = vctxt->attrInfo->node;
19478 vctxt->cur = vctxt->node->children;
19479 /* STREAM */
19480 value = xmlNodeListGetString(vctxt->node->doc, vctxt->cur, 1);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019481
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019482 /*
19483 * NOTE: This call also checks the content nodes for correct type.
19484 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019485 ret = xmlSchemaValidateSimpleTypeValue(vctxt, vctxt->attrInfo->typeDef,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019486 value, 1, 1, 1, 1);
19487
19488 /*
19489 * Handle 'fixed' attributes.
19490 */
19491 if (ret > 0) {
19492 state->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
19493 /*
19494 * NOTE: Fixed value constraints will be not
19495 * applied if the value was invalid, because:
19496 * 1. The validation process does not return a precomputed
19497 * value.
19498 * 2. An invalid value implies a violation of a fixed
19499 * value constraint.
19500 */
19501 } else if (ret == 0) {
19502 state->state = XML_SCHEMAS_ATTR_CHECKED;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019503 if (xmlSchemaGetEffectiveValueConstraint(
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019504 (xmlSchemaAttributePtr) vctxt->attrInfo->decl,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019505 &fixed, &defValue, &defVal) && (fixed == 1)) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000019506
19507 int ws = xmlSchemaGetWhiteSpaceFacetValue(
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019508 vctxt->nodeInfo->typeDef);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019509 /*
19510 * cvc-au : Attribute Locally Valid (Use)
19511 * For an attribute information item to be·valid·
19512 * with respect to an attribute use its ·normalized
19513 * value· must match the canonical lexical representation
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019514 * of the attribute use's {value constraint} value, if it
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019515 * is present and fixed.
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019516 *
19517 * TODO: Use somehow the *normalized* value and the *canonical*
19518 * fixed value. This here compares the canonical values of both.
19519 * The normalized value of, for example, a float type can differ
19520 * from its canonical representation. This all means that a fixed
19521 * value can only be OK, if it's present in the canonical form in
19522 * the instance.
19523 * NOTE: Since the value for string and anySimpleType is not always
19524 * precomputed during validation, we need to do it now.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019525 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019526 if (vctxt->value == NULL) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000019527 /*
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019528 * Post-create the value.
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000019529 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019530 if (xmlSchemaPostCreateVal(vctxt, value, &(vctxt->value)) == -1) {
19531 ret = -1;
19532 goto exit;
19533 }
19534 value = NULL;
19535 }
19536 if (defVal == NULL) {
19537 xmlChar *str;
19538
19539 /*
19540 * Post-create the default/fixed value.
19541 */
19542 if (defValue == NULL)
19543 str = xmlStrdup(BAD_CAST "");
19544 else
19545 str = xmlStrdup(defValue);
19546 if (xmlSchemaPostCreateVal(vctxt, str, &defVal) == -1) {
19547 ret = -1;
19548 FREE_AND_NULL(str)
19549 goto exit;
19550 }
19551 ((xmlSchemaAttributePtr) vctxt->attrInfo->decl)->defVal = defVal;
19552 }
19553 if (xmlSchemaCompareValuesWhtsp(vctxt->value,
19554 (xmlSchemaWhitespaceValueType) ws,
19555 defVal,
19556 (xmlSchemaWhitespaceValueType) ws) != 0)
19557 {
19558 state->state = XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019559 }
19560 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019561 }
19562exit:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019563 if (value != NULL) {
19564 xmlFree(value);
19565 }
19566 return (ret);
19567}
19568
Daniel Veillard4255d502002-04-16 15:50:10 +000019569/**
19570 * xmlSchemaValidateAttributes:
19571 * @ctxt: a schema validation context
19572 * @elem: an element
Daniel Veillard3646d642004-06-02 19:19:14 +000019573 * @type: the complexType holding the attribute uses
Daniel Veillard4255d502002-04-16 15:50:10 +000019574 *
19575 * Validate the attributes of an element.
19576 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000019577 * 1. Existent, invalid attributes are reported in the form
19578 * "prefix:localName".
19579 * Reason: readability - it is easier to find the actual XML
19580 * representation of the attributes QName.
19581 * 2. Missing attributes are reported in the form
19582 * {"URI", "localName"}.
19583 * This is necessary, since the the prefix need not to be declared
19584 * at all, and thus is not computable.
19585 *
Daniel Veillard4255d502002-04-16 15:50:10 +000019586 * Returns 0 if the element is schemas valid, a positive error code
19587 * number otherwise and -1 in case of internal or API error.
19588 */
19589static int
Daniel Veillard3646d642004-06-02 19:19:14 +000019590xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem, xmlSchemaTypePtr type)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019591{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019592 const xmlChar *nsURI;
Daniel Veillard3646d642004-06-02 19:19:14 +000019593 int ret;
19594 xmlAttrPtr attr; /* An attribute on the element. */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019595 const xmlChar *defValue;
19596 xmlSchemaValPtr defVal;
19597 int fixed;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019598 xmlSchemaAttributeLinkPtr attrUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000019599 xmlSchemaAttributePtr attrDecl;
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000019600 int found;
William M. Brack803812b2004-06-03 02:11:24 +000019601 xmlSchemaAttrStatePtr curState, reqAttrStates = NULL, reqAttrStatesTop = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019602 xmlSchemaAttrStatePtr defAttrStates = NULL, defAttrStatesTop = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019603 xmlNodePtr oldnode;
Daniel Veillard3646d642004-06-02 19:19:14 +000019604#ifdef DEBUG_ATTR_VALIDATION
19605 int redundant = 0;
19606#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000019607
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019608
Daniel Veillardc0826a72004-08-10 14:17:33 +000019609 /*
19610 * Allow all attributes if the type is anyType.
19611 */
19612 if (type == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE))
19613 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019614
19615 oldnode = ctxt->node;
19616 if (type != NULL)
19617 attrUse = type->attributeUses;
Daniel Veillard3646d642004-06-02 19:19:14 +000019618 while (attrUse != NULL) {
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000019619 found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000019620 attrDecl = attrUse->attr;
19621#ifdef DEBUG_ATTR_VALIDATION
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019622 printf("attr use - name: %s\n", xmlSchemaGetAttrName(attrDecl));
Daniel Veillard3646d642004-06-02 19:19:14 +000019623 printf("attr use - use: %d\n", attrDecl->occurs);
19624#endif
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019625 for (curState = ctxt->attr; curState != NULL; curState = curState->next) {
Daniel Veillard3646d642004-06-02 19:19:14 +000019626
19627 if (curState->decl == attrUse->attr) {
19628#ifdef DEBUG_ATTR_VALIDATION
19629 redundant = 1;
19630#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019631 }
Daniel Veillard3646d642004-06-02 19:19:14 +000019632 attr = curState->attr;
19633#ifdef DEBUG_ATTR_VALIDATION
19634 printf("attr - name: %s\n", attr->name);
19635 if (attr->ns != NULL)
19636 printf("attr - ns: %s\n", attr->ns->href);
19637 else
19638 printf("attr - ns: none\n");
19639#endif
19640 /* TODO: Can this ever happen? */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019641 if (attr == NULL)
19642 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000019643 if (attrDecl->ref != NULL) {
19644 if (!xmlStrEqual(attr->name, attrDecl->ref))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019645 continue;
19646 if (attr->ns != NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000019647 if ((attrDecl->refNs == NULL) ||
19648 (!xmlStrEqual(attr->ns->href, attrDecl->refNs)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019649 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000019650 } else if (attrDecl->refNs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019651 continue;
19652 }
19653 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000019654 if (!xmlStrEqual(attr->name, attrDecl->name))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019655 continue;
19656 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +000019657 * handle the namespaces checks here
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019658 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000019659 if (attr->ns == NULL) {
19660 /*
William M. Bracke7091952004-05-11 15:09:58 +000019661 * accept an unqualified attribute only if the target
19662 * namespace of the declaration is absent.
Daniel Veillardbe9c6322003-11-22 20:37:51 +000019663 */
Daniel Veillard3646d642004-06-02 19:19:14 +000019664 if (attrDecl->targetNamespace != NULL)
William M. Bracke7091952004-05-11 15:09:58 +000019665 /*
19666 * This check was removed, since the target namespace
19667 * was evaluated during parsing and already took
19668 * "attributeFormDefault" into account.
19669 */
19670 /* ((attributes->flags & XML_SCHEMAS_ATTR_NSDEFAULT) == 0)) */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000019671 continue;
19672 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000019673 if (attrDecl->targetNamespace == NULL)
Daniel Veillardbe9c6322003-11-22 20:37:51 +000019674 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000019675 if (!xmlStrEqual(attrDecl->targetNamespace,
Daniel Veillardbe9c6322003-11-22 20:37:51 +000019676 attr->ns->href))
19677 continue;
19678 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019679 }
Daniel Veillard3646d642004-06-02 19:19:14 +000019680#ifdef DEBUG_ATTR_VALIDATION
19681 printf("found\n");
19682#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019683 found = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +000019684 curState->decl = attrDecl;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019685 curState->state = XML_SCHEMAS_ATTR_VALIDATE_VALUE;
19686 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019687 ret = xmlSchemaCheckAttrLocallyValid(ctxt, attrDecl, curState, attr);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019688 */
Daniel Veillard3646d642004-06-02 19:19:14 +000019689 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019690 if (!found) {
19691 if (attrDecl->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
19692 xmlSchemaAttrStatePtr tmp;
19693
Daniel Veillard3646d642004-06-02 19:19:14 +000019694#ifdef DEBUG_ATTR_VALIDATION
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019695 printf("required attr not found\n");
Daniel Veillard3646d642004-06-02 19:19:14 +000019696#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019697 /*
19698 * Add a new dummy attribute state.
19699 */
19700 tmp = (xmlSchemaAttrStatePtr) xmlMalloc(sizeof(xmlSchemaAttrState));
19701 if (tmp == NULL) {
19702 xmlSchemaVErrMemory(ctxt, "registering required attributes", NULL);
19703 ctxt->node = oldnode;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019704 goto fatal_exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019705 }
19706 tmp->attr = NULL;
19707 tmp->state = XML_SCHEMAS_ATTR_MISSING;
19708 tmp->decl = attrDecl;
19709 tmp->next = NULL;
19710
19711 if (reqAttrStates == NULL) {
19712 reqAttrStates = tmp;
19713 reqAttrStatesTop = tmp;
19714 } else {
19715 reqAttrStatesTop->next = tmp;
19716 reqAttrStatesTop = tmp;
19717 }
19718 } else if ((attrDecl->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
19719 (xmlSchemaGetEffectiveValueConstraint(attrDecl,
19720 &fixed, &defValue, &defVal))) {
19721 xmlSchemaAttrStatePtr tmp;
19722 /*
19723 * Handle non existent default/fixed attributes.
19724 */
19725 tmp = (xmlSchemaAttrStatePtr)
19726 xmlMalloc(sizeof(xmlSchemaAttrState));
19727 if (tmp == NULL) {
19728 xmlSchemaVErrMemory(ctxt,
19729 "registering schema specified attributes", NULL);
19730 ctxt->node = oldnode;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019731 goto fatal_exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019732 }
19733 tmp->attr = NULL;
19734 tmp->state = XML_SCHEMAS_ATTR_DEFAULT;
19735 tmp->decl = attrDecl;
19736 tmp->value = defValue;
19737 tmp->next = NULL;
19738
19739 if (defAttrStates == NULL) {
19740 defAttrStates = tmp;
19741 defAttrStates = tmp;
19742 } else {
19743 defAttrStates->next = tmp;
19744 defAttrStatesTop = tmp;
19745 }
19746 }
Daniel Veillard3646d642004-06-02 19:19:14 +000019747 }
19748 attrUse = attrUse->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000019749 }
Daniel Veillard3646d642004-06-02 19:19:14 +000019750 /*
19751 * Add required attributes to the attribute states of the context.
19752 */
19753 if (reqAttrStates != NULL) {
19754 if (ctxt->attr == NULL) {
19755 ctxt->attr = reqAttrStates;
19756 } else {
19757 ctxt->attrTop->next = reqAttrStates;
19758 }
19759 ctxt->attrTop = reqAttrStatesTop;
Daniel Veillardc0826a72004-08-10 14:17:33 +000019760 }
Daniel Veillard3646d642004-06-02 19:19:14 +000019761 /*
19762 * Process wildcards.
19763 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019764
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019765 if ((type != NULL) && (type->attributeWildcard != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000019766#ifdef DEBUG_ATTR_VALIDATION
19767 xmlSchemaWildcardNsPtr ns;
19768 printf("matching wildcard: [%d] of complexType: %s\n", type->attributeWildcard, type->name);
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019769 if (type->attributeWildcard->processContents ==
19770 XML_SCHEMAS_ANY_LAX)
19771 printf("processContents: lax\n");
19772 else if (type->attributeWildcard->processContents ==
19773 XML_SCHEMAS_ANY_STRICT)
19774 printf("processContents: strict\n");
19775 else
19776 printf("processContents: skip\n");
Daniel Veillard3646d642004-06-02 19:19:14 +000019777 if (type->attributeWildcard->any)
19778 printf("type: any\n");
19779 else if (type->attributeWildcard->negNsSet != NULL) {
19780 printf("type: negated\n");
19781 if (type->attributeWildcard->negNsSet->value == NULL)
19782 printf("ns: (absent)\n");
19783 else
19784 printf("ns: %s\n", type->attributeWildcard->negNsSet->value);
19785 } else if (type->attributeWildcard->nsSet != NULL) {
19786 printf("type: set\n");
19787 ns = type->attributeWildcard->nsSet;
19788 while (ns != NULL) {
19789 if (ns->value == NULL)
19790 printf("ns: (absent)\n");
19791 else
19792 printf("ns: %s\n", ns->value);
19793 ns = ns->next;
19794 }
19795 } else
19796 printf("empty\n");
19797
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019798
19799#endif
Daniel Veillard3646d642004-06-02 19:19:14 +000019800 curState = ctxt->attr;
19801 while (curState != NULL) {
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019802 if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
19803 if (curState->attr->ns != NULL)
19804 nsURI = curState->attr->ns->href;
19805 else
19806 nsURI = NULL;
19807 if (xmlSchemaMatchesWildcardNs(type->attributeWildcard,
19808 nsURI)) {
19809 /*
19810 * Handle processContents.
19811 */
19812 if ((type->attributeWildcard->processContents ==
19813 XML_SCHEMAS_ANY_LAX) ||
19814 (type->attributeWildcard->processContents ==
19815 XML_SCHEMAS_ANY_STRICT)) {
19816
19817 attr = curState->attr;
19818 attrDecl = xmlSchemaGetAttribute(ctxt->schema,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019819 attr->name, nsURI);
19820 curState->decl = attrDecl;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019821 if (attrDecl != NULL) {
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019822 curState->decl = attrDecl;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019823 curState->state = XML_SCHEMAS_ATTR_VALIDATE_VALUE;
19824 /* TODO
19825 ret = xmlSchemaCheckAttrLocallyValid(ctxt, attrDecl, curState, attr);
19826 */
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019827 } else if (type->attributeWildcard->processContents ==
19828 XML_SCHEMAS_ANY_LAX) {
19829 curState->state = XML_SCHEMAS_ATTR_CHECKED;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019830 } else
19831 curState->state = XML_SCHEMAS_ATTR_WILD_NO_DECL;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019832 } else
Daniel Veillard3646d642004-06-02 19:19:14 +000019833 curState->state = XML_SCHEMAS_ATTR_CHECKED;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019834 }
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019835 }
Daniel Veillard3646d642004-06-02 19:19:14 +000019836 curState = curState->next;
19837 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019838 }
19839
Daniel Veillardc0826a72004-08-10 14:17:33 +000019840 if (ctxt->attr != NULL) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019841 int valueNeeded;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019842
19843 /*
19844 * Validate the value of the attribute.
19845 */
19846 if (ctxt->value != NULL) {
19847 xmlSchemaFreeValue(ctxt->value);
19848 ctxt->value = NULL;
19849 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000019850 curState = ctxt->attr;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019851 while ((curState != NULL) && (curState != ctxt->attrTop->next)) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019852 valueNeeded = 0;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019853 switch (curState->state) {
19854 case XML_SCHEMAS_ATTR_VALIDATE_VALUE:
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019855
19856 /*
19857 * Create an attribute info if needed.
19858 */
19859 if (ctxt->attrInfo == NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019860 ctxt->attrInfo = (xmlSchemaNodeInfoPtr)
19861 xmlMalloc(sizeof(xmlSchemaNodeInfo));
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019862 if (ctxt->attrInfo == NULL) {
19863 xmlSchemaVErrMemory(ctxt,
19864 "allocating an attribute info", NULL);
19865 goto fatal_exit;
19866 }
19867 }
19868 /*
19869 * Init the attribute info.
19870 */
19871 ctxt->attrInfo->flags = 0;
19872 ctxt->attrInfo->node = (xmlNodePtr) curState->attr;
19873 ctxt->attrInfo->decl = (xmlSchemaTypePtr) curState->decl;
19874 ctxt->attrInfo->value = NULL;
19875 if (curState->decl != NULL)
19876 ctxt->attrInfo->typeDef = curState->decl->subtypes;
19877 else
19878 ctxt->attrInfo->typeDef = NULL;
19879 if (curState->attr->ns != NULL)
19880 ctxt->attrInfo->namespaceName =
19881 curState->attr->ns->href;
19882 else
19883 ctxt->attrInfo->namespaceName = NULL;
19884 ctxt->attrInfo->localName = curState->attr->name;
19885
19886 ctxt->nodeInfo = ctxt->attrInfo;
19887
19888#ifdef IDC_ENABLED
19889 /*
19890 * Evaluate IDCs.
19891 */
19892 if (ctxt->xpathStates != NULL) {
19893 ret = xmlSchemaXPathEvaluate(ctxt,
19894 XML_ATTRIBUTE_NODE);
19895 if (ret == -1)
19896 goto fatal_exit;
19897 }
19898
19899#endif
19900 ret = xmlSchemaCheckAttrLocallyValid(ctxt, curState);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019901 if (ret == -1)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019902 goto fatal_exit;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019903 if ((ret != 0) && (ctxt->value != NULL)) {
19904 xmlSchemaFreeValue(ctxt->value);
19905 ctxt->value = NULL;
19906 }
19907 /* No break on purpose. */
19908 case XML_SCHEMAS_ATTR_CHECKED:
19909#ifdef IDC_ENABLED
19910 if (ctxt->xpathStates != NULL) {
19911 /*
19912 * Evaluate IDCs.
19913 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019914 if (ctxt->value != NULL) {
19915 ctxt->attrInfo->value = ctxt->value;
19916 ctxt->value = NULL;
19917 }
19918 if (xmlSchemaXPathProcessHistory(ctxt, ctxt->depth +1) == -1)
19919 goto fatal_exit;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019920 }
19921 break;
19922#endif
19923 default:
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019924 break;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019925 }
19926 curState = curState->next;
19927 }
19928
19929 /*
19930 * Report missing and illegal attributes.
19931 */
19932 curState = ctxt->attr;
19933 while ((curState != NULL) && (curState != ctxt->attrTop->next)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000019934 if (curState->state != XML_SCHEMAS_ATTR_CHECKED) {
19935 attr = curState->attr;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019936 if (curState->decl != NULL) {
19937 if (curState->decl->ref != NULL)
19938 attrDecl = curState->decl->refDecl;
19939 else
19940 attrDecl = curState->decl;
19941 } else
19942 attrDecl = NULL;
19943 if (curState->state == XML_SCHEMAS_ATTR_MISSING) {
19944 xmlSchemaVMissingAttrErr(ctxt, elem, attrDecl);
19945 } else if (curState->state ==
19946 XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED) {
19947 xmlSchemaVCustomErr(ctxt,
19948 XML_SCHEMAV_CVC_ATTRIBUTE_2,
19949 (xmlNodePtr) attr,
19950 (xmlSchemaTypePtr) attrDecl,
19951 "The type definition is absent",
19952 NULL);
19953 } else if (curState->state ==
19954 XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE) {
19955 xmlSchemaVCustomErr(ctxt,
19956 XML_SCHEMAV_CVC_AU,
19957 (xmlNodePtr) attr, (xmlSchemaTypePtr) attrDecl,
19958 "The value does not match the fixed value "
19959 "constraint", NULL);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019960 } else if (curState->state == XML_SCHEMAS_ATTR_WILD_NO_DECL) {
19961 xmlSchemaVWildcardErr(ctxt,
19962 XML_SCHEMAV_CVC_WILDCARD,
19963 (xmlNodePtr) attr,
19964 type->attributeWildcard,
19965 "No global attribute declaration found, but "
19966 "stipulated by the strict processContents of "
19967 "the wildcard");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019968 } else if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000019969 /* TODO: "prohibited" won't ever be touched here!.
19970 (curState->state == XML_SCHEMAS_ATTR_PROHIBITED))
19971 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019972 /*
19973 * TODO: One might report different error messages
19974 * for the following errors.
19975 */
19976 if ((type == NULL) || (type->attributeWildcard == NULL)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000019977 xmlSchemaVIllegalAttrErr(ctxt,
19978 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, attr);
19979 } else {
19980 xmlSchemaVIllegalAttrErr(ctxt,
19981 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, attr);
19982 }
19983 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000019984 }
19985 curState = curState->next;
19986 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019987 }
19988
19989 /*
19990 * Add missing default/fixed attributes.
19991 */
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000019992 if (defAttrStates != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019993 curState = defAttrStates;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000019994
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019995 while (curState != NULL) {
19996 attrDecl = curState->decl;
19997 if (attrDecl->ref != NULL)
19998 attrDecl = attrDecl->refDecl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019999
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000020000#ifdef IDC_ENABLED
20001 /*
20002 * Evaluate IDCs on default attributes.
20003 */
20004 if (ctxt->xpathStates != NULL) {
20005 /*
20006 * Create an attribute info if needed.
20007 */
20008 if (ctxt->attrInfo == NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020009 ctxt->attrInfo = (xmlSchemaNodeInfoPtr)
20010 xmlMalloc(sizeof(xmlSchemaNodeInfo));
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000020011 if (ctxt->attrInfo == NULL) {
20012 xmlSchemaVErrMemory(ctxt,
20013 "allocating an attribute info", NULL);
20014 goto fatal_exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020015 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020016 ctxt->attrInfo->value = NULL;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000020017 }
20018 /*
20019 * Init the attribute info.
Kasimier T. Buchcik285ebab2005-03-04 18:04:59 +000020020 * TODO: Hmm, maby a bit oversized this all.
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000020021 */
20022 ctxt->attrInfo->flags = 0;
20023 ctxt->attrInfo->decl = (xmlSchemaTypePtr) attrDecl;
20024 ctxt->attrInfo->node = NULL;
20025 ctxt->attrInfo->typeDef = attrDecl->subtypes;
20026 ctxt->attrInfo->namespaceName = attrDecl->targetNamespace;
20027 ctxt->attrInfo->localName = attrDecl->name;
20028
20029 ctxt->nodeInfo = ctxt->attrInfo;
20030
20031 ret = xmlSchemaXPathEvaluate(ctxt,
20032 XML_ATTRIBUTE_NODE);
20033 if (ret == -1)
20034 goto fatal_exit;
20035 if (ctxt->attrInfo->value != NULL) {
20036 xmlSchemaFreeValue(ctxt->attrInfo->value);
20037 ctxt->attrInfo->value = NULL;
20038 }
20039 if (ret > 0) {
Kasimier T. Buchcik285ebab2005-03-04 18:04:59 +000020040 /*
20041 * IDCs will consume the precomputed default value,
20042 * so we need to clone it somehow.
20043 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020044 /*
20045 * string or anySimpleType does not create a precomputed value
20046 * by default, so it will be created here on demand.
20047 * TODO: default/fixed attributes are a bit unoptimized:
20048 * the string value will be hold by ->defValue and inside
20049 * the precomputed value.
20050 */
20051 if (attrDecl->defVal == NULL) {
20052 xmlChar *str = xmlStrdup(attrDecl->defValue);
20053
20054 if (xmlSchemaPostCreateVal(ctxt,
20055 str,
20056 &(attrDecl->defVal)) == -1) {
20057 FREE_AND_NULL(str)
20058 goto fatal_exit;
20059 }
20060 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000020061 ctxt->attrInfo->value = xmlSchemaCopyValue(attrDecl->defVal);
20062 /* TODO: error on NULL return. */
20063 }
Kasimier T. Buchcik285ebab2005-03-04 18:04:59 +000020064
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000020065 if (xmlSchemaXPathProcessHistory(ctxt, ctxt->depth +1) == -1)
20066 goto fatal_exit;
20067 }
20068#endif
20069
20070 if (ctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
20071 /*
20072 * PSVI: Add a new attribute node to the current element.
20073 */
20074 if (attrDecl->targetNamespace == NULL) {
20075 xmlNewProp(elem, attrDecl->name, curState->value);
20076 } else {
20077 xmlNsPtr ns;
20078
20079 ns = xmlSearchNsByHref(elem->doc, elem,
20080 attrDecl->targetNamespace);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020081 if (ns == NULL) {
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000020082 xmlChar prefix[12];
20083 int counter = 1;
20084
20085 attr = curState->attr;
20086 /*
20087 * Create a namespace declaration on the validation
20088 * root node if no namespace declaration is in scope.
20089 */
20090 snprintf((char *) prefix, sizeof(prefix), "p");
20091 /*
20092 * This is somehow not performant, since the ancestor
20093 * axis beyond @elem will be searched as well.
20094 */
20095 ns = xmlSearchNs(elem->doc, elem, BAD_CAST prefix);
20096 while (ns != NULL) {
20097 if (counter > 1000) {
20098 xmlSchemaVErr(ctxt, (xmlNodePtr) attr,
20099 XML_SCHEMAV_INTERNAL,
20100 "Internal error: xmlSchemaValidateAttributes, "
20101 "could not compute a ns prefix for "
20102 "default/fixed attribute '%s'.\n",
20103 attrDecl->name, NULL);
20104
20105 break;
20106 }
20107 snprintf((char *) prefix,
20108 sizeof(prefix), "p%d", counter++);
20109 ns = xmlSearchNs(elem->doc, elem,
20110 BAD_CAST prefix);
20111 }
20112 if (ns == NULL) {
20113 ns = xmlNewNs(ctxt->validationRoot,
20114 attrDecl->targetNamespace, BAD_CAST prefix);
20115 xmlNewNsProp(elem, ns, attrDecl->name,
20116 curState->value);
20117 }
20118 } else {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020119 xmlNewNsProp(elem, ns, attrDecl->name,
20120 curState->value);
20121 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020122 }
20123 }
20124 curState = curState->next;
20125 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000020126 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020127 ret = ctxt->err;
20128 goto exit;
20129
20130fatal_exit:
20131 ret = -1;
20132
20133exit:
20134
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020135 if (defAttrStates != NULL)
20136 xmlSchemaFreeAttributeStates(defAttrStates);
20137
Daniel Veillard3646d642004-06-02 19:19:14 +000020138#ifdef DEBUG_ATTR_VALIDATION
20139 if (redundant)
20140 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020141 "xmlSchemaValidateAttributes: redundant call by "
20142 "type: %s\n", type->name);
Daniel Veillard3646d642004-06-02 19:19:14 +000020143#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020144 ctxt->nodeInfo = ctxt->elemInfos[ctxt->depth];
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020145 ctxt->node = oldnode;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020146 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000020147}
20148
20149/**
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020150 * xmlSchemaStartValidation:
Daniel Veillard4255d502002-04-16 15:50:10 +000020151 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000020152 *
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020153 * The starting point of the validation, called by
20154 * xmlSchemaValidateDocument and xmlSchemaValidateOneElement.
Daniel Veillard4255d502002-04-16 15:50:10 +000020155 *
20156 * Returns 0 if the element is schemas valid, a positive error code
20157 * number otherwise and -1 in case of internal or API error.
20158 */
20159static int
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020160xmlSchemaStartValidation(xmlSchemaValidCtxtPtr ctxt)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020161{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020162 xmlSchemaElementPtr elemDecl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020163 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000020164
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020165 ctxt->err = 0;
20166 ctxt->nberrors = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020167 if (ctxt->schema == NULL) {
20168 /*
20169 * No schema was specified at time of creation of the validation
20170 * context. Use xsi:schemaLocation and xsi:noNamespaceSchemaLocation
20171 * of the instance to build a schema.
20172 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020173 if (ctxt->pctxt == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020174 if (xmlSchemaCreatePCtxtOnVCtxt(ctxt) == -1)
20175 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020176 ctxt->schema = xmlSchemaNewSchema(ctxt->pctxt);
20177 if (ctxt->schema == NULL)
20178 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020179 ctxt->xsiAssemble = 1;
20180 } else
20181 ctxt->xsiAssemble = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020182 /*
20183 * Assemble new schemata using xsi.
Daniel Veillardc0826a72004-08-10 14:17:33 +000020184 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020185 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020186 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
20187 if (ret == -1) {
20188 xmlSchemaVCustomErr(ctxt,
20189 XML_SCHEMAV_INTERNAL,
20190 ctxt->node, NULL,
20191 "Internal error: xmlSchemaValidateElement, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020192 "assembling schema by xsi", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020193 }
20194 /*
20195 * NOTE: We won't react on schema parser errors here.
20196 * TODO: But a warning would be nice.
20197 */
20198 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020199 if (ret != -1) {
20200 if (ctxt->node->ns != NULL)
20201 elemDecl = xmlSchemaGetElem(ctxt->schema, ctxt->node->name,
20202 ctxt->node->ns->href);
20203 else
20204 elemDecl = xmlSchemaGetElem(ctxt->schema, ctxt->node->name, NULL);
20205
20206 if (elemDecl == NULL) {
20207 xmlSchemaVCustomErr(ctxt,
20208 XML_SCHEMAV_CVC_ELT_1,
20209 ctxt->node, NULL,
20210 "No matching global declaration available", NULL);
20211 ret = XML_SCHEMAV_CVC_ELT_1;
20212 } else {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020213 /*
20214 * Augment the IDC definitions.
20215 */
20216 if (ctxt->schema->idcDef != NULL) {
20217 xmlHashScan(ctxt->schema->idcDef,
20218 (xmlHashScanner) xmlSchemaAugmentIDC, ctxt);
20219 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020220 ctxt->depth = -1;
20221 xmlSchemaBeginElement(ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020222 ret = xmlSchemaValidateElementByDeclaration(ctxt, elemDecl);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020223 xmlSchemaEndElement(ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020224 if (ret < 0) {
20225 xmlSchemaVCustomErr(ctxt,
20226 XML_SCHEMAV_INTERNAL, ctxt->node, NULL,
20227 "Internal error: xmlSchemaValidateElement, "
20228 "calling validation by declaration", NULL);
20229 }
20230 }
20231 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020232
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020233 if (ctxt->xsiAssemble) {
20234 if (ctxt->schema != NULL) {
20235 xmlSchemaFree(ctxt->schema);
20236 ctxt->schema = NULL;
20237 }
Daniel Veillard4255d502002-04-16 15:50:10 +000020238 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020239 xmlSchemaClearValidCtxt(ctxt);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020240 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000020241}
20242
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020243
Daniel Veillard4255d502002-04-16 15:50:10 +000020244/**
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000020245 * xmlSchemaValidateOneElement:
20246 * @ctxt: a schema validation context
20247 * @elem: an element node
20248 *
20249 * Validate a branch of a tree, starting with the given @elem.
20250 *
20251 * Returns 0 if the element and its subtree is valid, a positive error
20252 * code number otherwise and -1 in case of an internal or API error.
20253 */
20254int
20255xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
20256{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020257 if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000020258 return (-1);
20259
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020260 if (ctxt->schema == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020261 xmlSchemaVErr(ctxt, NULL,
20262 XML_SCHEMAV_INTERNAL,
20263 "API error: xmlSchemaValidateOneElement, "
20264 "no schema specified.\n", NULL, NULL);
20265 return (-1);
20266 }
20267
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000020268 ctxt->doc = elem->doc;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020269 ctxt->node = elem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020270 ctxt->validationRoot = elem;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020271 return (xmlSchemaStartValidation(ctxt));
Daniel Veillard4255d502002-04-16 15:50:10 +000020272}
20273
20274/************************************************************************
20275 * *
20276 * SAX Validation code *
20277 * *
20278 ************************************************************************/
20279
20280/************************************************************************
20281 * *
20282 * Validation interfaces *
20283 * *
20284 ************************************************************************/
20285
20286/**
20287 * xmlSchemaNewValidCtxt:
20288 * @schema: a precompiled XML Schemas
20289 *
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020290 * Create an XML Schemas validation context based on the given schema.
Daniel Veillard4255d502002-04-16 15:50:10 +000020291 *
20292 * Returns the validation context or NULL in case of error
20293 */
20294xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020295xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
20296{
Daniel Veillard4255d502002-04-16 15:50:10 +000020297 xmlSchemaValidCtxtPtr ret;
20298
20299 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
20300 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020301 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000020302 return (NULL);
20303 }
20304 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
Daniel Veillardc0826a72004-08-10 14:17:33 +000020305 ret->schema = schema;
Daniel Veillard4255d502002-04-16 15:50:10 +000020306 return (ret);
20307}
20308
20309/**
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020310 * xmlSchemaClearValidCtxt:
20311 * @ctxt: the schema validation context
20312 *
20313 * Free the resources associated to the schema validation context;
20314 * leaves some fields alive intended for reuse of the context.
20315 */
20316static void
20317xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
20318{
20319 if (vctxt == NULL)
20320 return;
20321
20322 vctxt->validationRoot = NULL;
20323 if (vctxt->attr != NULL) {
20324 xmlSchemaFreeAttributeStates(vctxt->attr);
20325 vctxt->attr = NULL;
20326 }
20327 if (vctxt->value != NULL) {
20328 xmlSchemaFreeValue(vctxt->value);
20329 vctxt->value = NULL;
20330 }
20331 /*
20332 * Augmented IDC information.
20333 */
20334 if (vctxt->aidcs != NULL) {
20335 xmlSchemaIDCAugPtr cur = vctxt->aidcs, next;
20336 do {
20337 next = cur->next;
20338 xmlFree(cur);
20339 cur = next;
20340 } while (cur != NULL);
20341 vctxt->aidcs = NULL;
20342 }
20343 if (vctxt->idcNodes != NULL) {
20344 int i;
20345 xmlSchemaPSVIIDCNodePtr item;
20346
20347 for (i = 0; i < vctxt->nbIdcNodes; i++) {
20348 item = vctxt->idcNodes[i];
20349 xmlFree(item->keys);
20350 xmlFree(item);
20351 }
20352 xmlFree(vctxt->idcNodes);
20353 vctxt->idcNodes = NULL;
20354 }
20355 /*
20356 * Note that we won't delete the XPath state pool here.
20357 */
20358 if (vctxt->xpathStates != NULL) {
20359 xmlSchemaFreeIDCStateObjList(vctxt->xpathStates);
20360 vctxt->xpathStates = NULL;
20361 }
20362 if (vctxt->attrInfo != NULL) {
20363 if (vctxt->attrInfo->value != NULL) {
20364 xmlSchemaFreeValue(vctxt->attrInfo->value);
20365 }
20366 memset(vctxt->attrInfo, 0, sizeof(xmlSchemaNodeInfo));
20367 }
20368 if (vctxt->elemInfos != NULL) {
20369 int i;
20370 xmlSchemaNodeInfoPtr info;
20371
20372 for (i = 0; i < vctxt->sizeElemInfos; i++) {
20373 info = vctxt->elemInfos[i];
20374 if (info == NULL)
20375 break;
20376 if (info->value != NULL) {
20377 xmlSchemaFreeValue(info->value);
20378 info->value = NULL;
20379 }
20380 if (info->idcMatchers != NULL) {
20381 xmlSchemaIDCFreeMatcherList(info->idcMatchers);
20382 info->idcMatchers = NULL;
20383 }
20384 if (info->idcTable != NULL) {
20385 xmlSchemaIDCFreeIDCTable(info->idcTable);
20386 info->idcTable = NULL;
20387 }
20388 }
20389 }
20390}
20391
20392/**
Daniel Veillard4255d502002-04-16 15:50:10 +000020393 * xmlSchemaFreeValidCtxt:
20394 * @ctxt: the schema validation context
20395 *
20396 * Free the resources associated to the schema validation context
20397 */
20398void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020399xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
20400{
Daniel Veillard4255d502002-04-16 15:50:10 +000020401 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020402 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000020403 if (ctxt->attr != NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000020404 xmlSchemaFreeAttributeStates(ctxt->attr);
Daniel Veillard88c58912002-04-23 07:12:20 +000020405 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020406 xmlSchemaFreeValue(ctxt->value);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020407 if (ctxt->pctxt != NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020408 xmlSchemaFreeParserCtxt(ctxt->pctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020409 if (ctxt->idcNodes != NULL) {
20410 int i;
20411 xmlSchemaPSVIIDCNodePtr item;
20412
20413 for (i = 0; i < ctxt->nbIdcNodes; i++) {
20414 item = ctxt->idcNodes[i];
20415 xmlFree(item->keys);
20416 xmlFree(item);
20417 }
20418 xmlFree(ctxt->idcNodes);
20419 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020420 if (ctxt->idcKeys != NULL) {
20421 int i;
20422 for (i = 0; i < ctxt->nbIdcKeys; i++)
20423 xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
20424 xmlFree(ctxt->idcKeys);
20425 }
20426
20427 if (ctxt->xpathStates != NULL)
20428 xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
20429 if (ctxt->xpathStatePool != NULL)
20430 xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
20431
20432 /*
20433 * Augmented IDC information.
20434 */
20435 if (ctxt->aidcs != NULL) {
20436 xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
20437 do {
20438 next = cur->next;
20439 xmlFree(cur);
20440 cur = next;
20441 } while (cur != NULL);
20442 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020443 if (ctxt->attrInfo != NULL) {
20444 if (ctxt->attrInfo->value != NULL)
20445 xmlSchemaFreeValue(ctxt->attrInfo->value);
20446 xmlFree(ctxt->attrInfo);
20447 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020448 if (ctxt->elemInfos != NULL) {
20449 int i;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020450 xmlSchemaNodeInfoPtr info;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020451
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020452 for (i = 0; i < ctxt->sizeElemInfos; i++) {
20453 info = ctxt->elemInfos[i];
20454 if (info == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020455 break;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020456 if (info->value != NULL)
20457 xmlSchemaFreeValue(info->value);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020458 if (info->idcMatchers != NULL)
20459 xmlSchemaIDCFreeMatcherList(info->idcMatchers);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020460 if (info->idcTable != NULL)
20461 xmlSchemaIDCFreeIDCTable(info->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020462 /*
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020463 * TODO: Don't know if those will have to be freed if in streaming
20464 * mode.
20465 *
20466 * xmlFree(info->localName);
20467 * if (info->namespaceName != NULL)
20468 * xmlFree(info->namespaceName);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020469 */
20470 xmlFree(info);
20471 }
20472 xmlFree(ctxt->elemInfos);
20473 }
Daniel Veillard4255d502002-04-16 15:50:10 +000020474 xmlFree(ctxt);
20475}
20476
20477/**
20478 * xmlSchemaSetValidErrors:
20479 * @ctxt: a schema validation context
20480 * @err: the error function
20481 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +000020482 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +000020483 *
William M. Brack2f2a6632004-08-20 23:09:47 +000020484 * Set the error and warning callback informations
Daniel Veillard4255d502002-04-16 15:50:10 +000020485 */
20486void
20487xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020488 xmlSchemaValidityErrorFunc err,
20489 xmlSchemaValidityWarningFunc warn, void *ctx)
20490{
Daniel Veillard4255d502002-04-16 15:50:10 +000020491 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020492 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000020493 ctxt->error = err;
20494 ctxt->warning = warn;
20495 ctxt->userData = ctx;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020496 if (ctxt->pctxt != NULL)
20497 xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
Daniel Veillard4255d502002-04-16 15:50:10 +000020498}
20499
20500/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000020501 * xmlSchemaGetValidErrors:
20502 * @ctxt: a XML-Schema validation context
20503 * @err: the error function result
20504 * @warn: the warning function result
20505 * @ctx: the functions context result
20506 *
20507 * Get the error and warning callback informations
20508 *
20509 * Returns -1 in case of error and 0 otherwise
20510 */
20511int
20512xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
20513 xmlSchemaValidityErrorFunc * err,
20514 xmlSchemaValidityWarningFunc * warn, void **ctx)
20515{
20516 if (ctxt == NULL)
20517 return (-1);
20518 if (err != NULL)
20519 *err = ctxt->error;
20520 if (warn != NULL)
20521 *warn = ctxt->warning;
20522 if (ctx != NULL)
20523 *ctx = ctxt->userData;
20524 return (0);
20525}
20526
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020527
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020528/**
Daniel Veillard6927b102004-10-27 17:29:04 +000020529 * xmlSchemaSetValidOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020530 * @ctxt: a schema validation context
20531 * @options: a combination of xmlSchemaValidOption
20532 *
20533 * Sets the options to be used during the validation.
20534 *
20535 * Returns 0 in case of success, -1 in case of an
20536 * API error.
20537 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020538int
20539xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
20540 int options)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020541
20542{
20543 int i;
20544
20545 if (ctxt == NULL)
20546 return (-1);
20547 /*
20548 * WARNING: Change the start value if adding to the
20549 * xmlSchemaValidOption.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020550 * TODO: Is there an other, more easy to maintain,
20551 * way?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020552 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020553 for (i = 1; i < (int) sizeof(int) * 8; i++) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020554 if (options & 1<<i) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020555 xmlSchemaVErr(ctxt, NULL,
20556 XML_SCHEMAV_INTERNAL,
20557 "Internal error: xmlSchemaSetValidOptions, "
20558 "invalid option argument.\n", NULL, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020559 return (-1);
20560 }
20561 }
20562 ctxt->options = options;
20563 return (0);
20564}
20565
20566/**
Daniel Veillard6927b102004-10-27 17:29:04 +000020567 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020568 * @ctxt: a schema validation context
20569 *
William M. Brack21e4ef22005-01-02 09:53:13 +000020570 * Get the validation context options.
20571 *
20572 * Returns the option combination or -1 on error.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020573 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020574int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020575xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
20576
20577{
20578 if (ctxt == NULL)
20579 return (-1);
20580 else
20581 return (ctxt->options);
20582}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020583
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020584
Daniel Veillard259f0df2004-08-18 09:13:18 +000020585/**
Daniel Veillard4255d502002-04-16 15:50:10 +000020586 * xmlSchemaValidateDoc:
20587 * @ctxt: a schema validation context
20588 * @doc: a parsed document tree
20589 *
20590 * Validate a document tree in memory.
20591 *
20592 * Returns 0 if the document is schemas valid, a positive error code
20593 * number otherwise and -1 in case of internal or API error.
20594 */
20595int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020596xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
20597{
Daniel Veillard4255d502002-04-16 15:50:10 +000020598 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020599 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000020600
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020601 ctxt->doc = doc;
20602 ctxt->node = xmlDocGetRootElement(doc);
20603 if (ctxt->node == NULL) {
20604 xmlSchemaVCustomErr(ctxt,
20605 XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
20606 (xmlNodePtr) doc, NULL,
20607 "The document has no document element", NULL);
20608 return (ctxt->err);
20609 }
20610 ctxt->validationRoot = ctxt->node;
20611 xmlSchemaStartValidation(ctxt);
20612
20613 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000020614}
20615
20616/**
20617 * xmlSchemaValidateStream:
20618 * @ctxt: a schema validation context
20619 * @input: the input to use for reading the data
20620 * @enc: an optional encoding information
20621 * @sax: a SAX handler for the resulting events
20622 * @user_data: the context to provide to the SAX handler.
20623 *
20624 * Validate a document tree in memory.
20625 *
20626 * Returns 0 if the document is schemas valid, a positive error code
20627 * number otherwise and -1 in case of internal or API error.
20628 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020629int
Daniel Veillard4255d502002-04-16 15:50:10 +000020630xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020631 xmlParserInputBufferPtr input, xmlCharEncoding enc,
20632 xmlSAXHandlerPtr sax, void *user_data)
20633{
Daniel Veillard4255d502002-04-16 15:50:10 +000020634 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020635 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000020636 ctxt->input = input;
20637 ctxt->enc = enc;
20638 ctxt->sax = sax;
20639 ctxt->user_data = user_data;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020640 TODO return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000020641}
20642
20643#endif /* LIBXML_SCHEMAS_ENABLED */