blob: 82c5087e379774aab9aec81f3d917f6abc45875f [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);
William M. Brack87640d52004-04-17 14:58:15 +0000558
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000559/************************************************************************
560 * *
561 * Datatype error handlers *
562 * *
563 ************************************************************************/
564
565/**
566 * xmlSchemaPErrMemory:
567 * @node: a context node
568 * @extra: extra informations
569 *
570 * Handle an out of memory condition
571 */
572static void
573xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
574 const char *extra, xmlNodePtr node)
575{
576 if (ctxt != NULL)
577 ctxt->nberrors++;
578 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
579 extra);
580}
581
582/**
583 * xmlSchemaPErr:
584 * @ctxt: the parsing context
585 * @node: the context node
586 * @error: the error code
587 * @msg: the error message
588 * @str1: extra data
589 * @str2: extra data
590 *
591 * Handle a parser error
592 */
593static void
594xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
595 const char *msg, const xmlChar * str1, const xmlChar * str2)
596{
597 xmlGenericErrorFunc channel = NULL;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000598 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000599 void *data = NULL;
600
601 if (ctxt != NULL) {
602 ctxt->nberrors++;
603 channel = ctxt->error;
604 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000605 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000606 }
Daniel Veillard659e71e2003-10-10 14:10:40 +0000607 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000608 error, XML_ERR_ERROR, NULL, 0,
609 (const char *) str1, (const char *) str2, NULL, 0, 0,
610 msg, str1, str2);
611}
612
613/**
614 * xmlSchemaPErr2:
615 * @ctxt: the parsing context
616 * @node: the context node
617 * @node: the current child
618 * @error: the error code
619 * @msg: the error message
620 * @str1: extra data
621 * @str2: extra data
622 *
623 * Handle a parser error
624 */
625static void
626xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
627 xmlNodePtr child, int error,
628 const char *msg, const xmlChar * str1, const xmlChar * str2)
629{
630 if (child != NULL)
631 xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
632 else
633 xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
634}
635
Daniel Veillard01fa6152004-06-29 17:04:39 +0000636
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000637/**
Daniel Veillard3646d642004-06-02 19:19:14 +0000638 * xmlSchemaPErrExt:
639 * @ctxt: the parsing context
640 * @node: the context node
641 * @error: the error code
642 * @strData1: extra data
643 * @strData2: extra data
644 * @strData3: extra data
645 * @msg: the message
646 * @str1: extra parameter for the message display
647 * @str2: extra parameter for the message display
648 * @str3: extra parameter for the message display
649 * @str4: extra parameter for the message display
650 * @str5: extra parameter for the message display
651 *
652 * Handle a parser error
653 */
654static void
655xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
656 const xmlChar * strData1, const xmlChar * strData2,
657 const xmlChar * strData3, const char *msg, const xmlChar * str1,
658 const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
659 const xmlChar * str5)
660{
661
662 xmlGenericErrorFunc channel = NULL;
663 xmlStructuredErrorFunc schannel = NULL;
664 void *data = NULL;
665
666 if (ctxt != NULL) {
667 ctxt->nberrors++;
668 channel = ctxt->error;
669 data = ctxt->userData;
670 schannel = ctxt->serror;
671 }
672 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
673 error, XML_ERR_ERROR, NULL, 0,
674 (const char *) strData1, (const char *) strData2,
William M. Brack803812b2004-06-03 02:11:24 +0000675 (const char *) strData3, 0, 0, msg, str1, str2,
676 str3, str4, str5);
Daniel Veillard3646d642004-06-02 19:19:14 +0000677}
Daniel Veillard01fa6152004-06-29 17:04:39 +0000678
Daniel Veillard3646d642004-06-02 19:19:14 +0000679
680/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000681 * xmlSchemaVTypeErrMemory:
682 * @node: a context node
683 * @extra: extra informations
684 *
685 * Handle an out of memory condition
686 */
687static void
688xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
689 const char *extra, xmlNodePtr node)
690{
691 if (ctxt != NULL) {
692 ctxt->nberrors++;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000693 ctxt->err = XML_SCHEMAV_INTERNAL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000694 }
695 __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
696 extra);
697}
698
699/**
700 * xmlSchemaVErr3:
701 * @ctxt: the validation context
702 * @node: the context node
703 * @error: the error code
704 * @msg: the error message
705 * @str1: extra data
706 * @str2: extra data
707 * @str3: extra data
708 *
709 * Handle a validation error
710 */
711static void
712xmlSchemaVErr3(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
713 const char *msg, const xmlChar *str1, const xmlChar *str2,
714 const xmlChar *str3)
715{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000716 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000717 xmlGenericErrorFunc channel = NULL;
718 void *data = NULL;
719
720 if (ctxt != NULL) {
721 ctxt->nberrors++;
722 ctxt->err = error;
723 channel = ctxt->error;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000724 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000725 data = ctxt->userData;
726 }
727 /* reajust to global error numbers */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000728 /* Removed, since the old schema error codes have been
729 * substituted for the global error codes.
730 *
731 * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
732 */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000733 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000734 error, XML_ERR_ERROR, NULL, 0,
735 (const char *) str1, (const char *) str2,
736 (const char *) str3, 0, 0,
737 msg, str1, str2, str3);
738}
Daniel Veillardc0826a72004-08-10 14:17:33 +0000739
740/**
741 * xmlSchemaVErrExt:
742 * @ctxt: the validation context
743 * @node: the context node
744 * @error: the error code
745 * @msg: the message
746 * @str1: extra parameter for the message display
747 * @str2: extra parameter for the message display
748 * @str3: extra parameter for the message display
749 * @str4: extra parameter for the message display
750 * @str5: extra parameter for the message display
751 *
752 * Handle a validation error
753 */
754static void
755xmlSchemaVErrExt(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
756 const char *msg, const xmlChar * str1,
757 const xmlChar * str2, const xmlChar * str3,
758 const xmlChar * str4, const xmlChar * str5)
759{
760 xmlStructuredErrorFunc schannel = NULL;
761 xmlGenericErrorFunc channel = NULL;
762 void *data = NULL;
763
764 if (ctxt != NULL) {
765 ctxt->nberrors++;
766 ctxt->err = error;
767 channel = ctxt->error;
768 schannel = ctxt->serror;
769 data = ctxt->userData;
770 }
771 /* reajust to global error numbers */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000772 /* Removed, since the old schema error codes have been
773 * substituted for the global error codes.
774 *
775 * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
776 */
Daniel Veillardc0826a72004-08-10 14:17:33 +0000777 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
778 error, XML_ERR_ERROR, NULL, 0, NULL, NULL, NULL, 0, 0,
779 msg, str1, str2, str3, str4, str5);
780}
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000781/**
782 * xmlSchemaVErr:
783 * @ctxt: the validation context
784 * @node: the context node
785 * @error: the error code
786 * @msg: the error message
787 * @str1: extra data
788 * @str2: extra data
789 *
790 * Handle a validation error
791 */
792static void
793xmlSchemaVErr(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
794 const char *msg, const xmlChar * str1, const xmlChar * str2)
795{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000796 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000797 xmlGenericErrorFunc channel = NULL;
798 void *data = NULL;
799
800 if (ctxt != NULL) {
801 ctxt->nberrors++;
802 ctxt->err = error;
803 channel = ctxt->error;
804 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000805 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000806 }
807 /* reajust to global error numbers */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000808 /* Removed, since the old schema error codes have been
809 * substituted for the global error codes.
810 *
811 * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
812 */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000813 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000814 error, XML_ERR_ERROR, NULL, 0,
815 (const char *) str1, (const char *) str2, NULL, 0, 0,
816 msg, str1, str2);
817}
Daniel Veillard4255d502002-04-16 15:50:10 +0000818
Daniel Veillardc0826a72004-08-10 14:17:33 +0000819/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000820 * xmlSchemaGetAttrName:
Daniel Veillardc0826a72004-08-10 14:17:33 +0000821 * @attr: the attribute declaration/use
822 *
823 * Returns the name of the attribute; if the attribute
824 * is a reference, the name of the referenced global type will be returned.
825 */
826static const xmlChar *
827xmlSchemaGetAttrName(xmlSchemaAttributePtr attr)
828{
829 if (attr->ref != NULL)
830 return(attr->ref);
831 else
832 return(attr->name);
833}
834
835/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000836 * xmlSchemaGetAttrTargetNsURI:
Daniel Veillardc0826a72004-08-10 14:17:33 +0000837 * @type: the type (element or attribute)
838 *
839 * Returns the target namespace URI of the type; if the type is a reference,
840 * the target namespace of the referenced type will be returned.
841 */
842static const xmlChar *
843xmlSchemaGetAttrTargetNsURI(xmlSchemaAttributePtr attr)
844{
845 if (attr->ref != NULL)
846 return (attr->refNs);
847 else
848 return(attr->targetNamespace);
849}
850
851/**
852 * xmlSchemaFormatNsUriLocal:
853 * @buf: the string buffer
854 * @uri: the namespace URI
855 * @local: the local name
856 *
857 * Returns a representation of the given URI used
858 * for error reports.
859 *
860 * Returns an empty string, if @ns is NULL, a formatted
861 * string otherwise.
862 */
863static const xmlChar*
864xmlSchemaFormatNsUriLocal(xmlChar **buf,
865 const xmlChar *uri, const xmlChar *local)
866{
867 if (*buf != NULL)
868 xmlFree(*buf);
869 if (uri == NULL) {
870 *buf = xmlStrdup(BAD_CAST "{'");
871 *buf = xmlStrcat(*buf, local);
872 } else {
873 *buf = xmlStrdup(BAD_CAST "{'");
874 *buf = xmlStrcat(*buf, uri);
875 *buf = xmlStrcat(*buf, BAD_CAST "', '");
876 *buf = xmlStrcat(*buf, local);
877 }
878 *buf = xmlStrcat(*buf, BAD_CAST "'}");
879 return ((const xmlChar *) *buf);
880}
881
882/**
883 * xmlSchemaFormatNsPrefixLocal:
884 * @buf: the string buffer
885 * @ns: the namespace
886 * @local: the local name
887 *
888 * Returns a representation of the given URI used
889 * for error reports.
890 *
891 * Returns an empty string, if @ns is NULL, a formatted
892 * string otherwise.
893 */
894static const xmlChar*
895xmlSchemaFormatNsPrefixLocal(xmlChar **buf,
896 xmlNsPtr ns, const xmlChar *local)
897{
898 if (*buf != NULL) {
899 xmlFree(*buf);
900 *buf = NULL;
901 }
902 if ((ns == NULL) || (ns->prefix == NULL))
903 return(local);
904 else {
905 *buf = xmlStrdup(ns->prefix);
906 *buf = xmlStrcat(*buf, BAD_CAST ":");
907 *buf = xmlStrcat(*buf, local);
908 }
909 return ((const xmlChar *) *buf);
910}
911
912/**
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000913 * xmlSchemaFormatQName:
914 * @buf: the string buffer
915 * @namespaceName: the namespace name
916 * @localName: the local name
917 *
918 * Returns the given QName in the format "{namespaceName}localName" or
919 * just "localName" if @namespaceName is NULL.
920 *
921 * Returns the localName if @namespaceName is NULL, a formatted
922 * string otherwise.
923 */
924static const xmlChar*
925xmlSchemaFormatQName(xmlChar **buf,
926 const xmlChar *namespaceName,
927 const xmlChar *localName)
928{
929 FREE_AND_NULL(*buf)
930 if (namespaceName == NULL)
931 return(localName);
932
933 *buf = xmlStrdup(BAD_CAST "{");
934 *buf = xmlStrcat(*buf, namespaceName);
935 *buf = xmlStrcat(*buf, BAD_CAST "}");
936 *buf = xmlStrcat(*buf, localName);
937
938 return ((const xmlChar *) *buf);
939}
940
941/**
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +0000942 * xmlSchemaWildcardPCToString:
943 * @pc: the type of processContents
944 *
945 * Returns a string representation of the type of
946 * processContents.
947 */
948static const xmlChar *
949xmlSchemaWildcardPCToString(int pc)
950{
951 switch (pc) {
952 case XML_SCHEMAS_ANY_SKIP:
953 return (BAD_CAST "skip");
954 case XML_SCHEMAS_ANY_LAX:
955 return (BAD_CAST "lax");
956 case XML_SCHEMAS_ANY_STRICT:
957 return (BAD_CAST "strict");
958 default:
959 return (BAD_CAST "invalid process contents");
960 }
961}
962
963/**
Daniel Veillardc0826a72004-08-10 14:17:33 +0000964 * xmlSchemaFormatItemForReport:
965 * @buf: the string buffer
966 * @itemDes: the designation of the item
967 * @itemName: the name of the item
968 * @item: the item as an object
969 * @itemNode: the node of the item
970 * @local: the local name
971 * @parsing: if the function is used during the parse
972 *
973 * Returns a representation of the given item used
974 * for error reports.
975 *
976 * The following order is used to build the resulting
977 * designation if the arguments are not NULL:
978 * 1a. If itemDes not NULL -> itemDes
979 * 1b. If (itemDes not NULL) and (itemName not NULL)
980 * -> itemDes + itemName
981 * 2. If the preceding was NULL and (item not NULL) -> item
982 * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
983 *
984 * If the itemNode is an attribute node, the name of the attribute
985 * will be appended to the result.
986 *
987 * Returns the formatted string and sets @buf to the resulting value.
988 */
989static xmlChar*
990xmlSchemaFormatItemForReport(xmlChar **buf,
991 const xmlChar *itemDes,
992 xmlSchemaTypePtr item,
993 xmlNodePtr itemNode,
994 int parsing)
995{
996 xmlChar *str = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +0000997 int named = 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +0000998
999 if (*buf != NULL) {
1000 xmlFree(*buf);
1001 *buf = NULL;
1002 }
1003
William M. Brack2f2a6632004-08-20 23:09:47 +00001004 if (itemDes != NULL) {
1005 *buf = xmlStrdup(itemDes);
1006 } else if (item != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001007 switch (item->type) {
1008 case XML_SCHEMA_TYPE_BASIC:
Daniel Veillardc0826a72004-08-10 14:17:33 +00001009 if (item->builtInType == XML_SCHEMAS_ANYTYPE)
1010 *buf = xmlStrdup(BAD_CAST "'anyType'");
1011 else if (item->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)
1012 *buf = xmlStrdup(BAD_CAST "'anySimpleType'");
1013 else {
1014 /* *buf = xmlStrdup(BAD_CAST "bi "); */
1015 /* *buf = xmlStrcat(*buf, xmlSchemaElemDesST); */
1016 *buf = xmlStrdup(BAD_CAST "'");
1017 *buf = xmlStrcat(*buf, item->name);
1018 *buf = xmlStrcat(*buf, BAD_CAST "'");
1019 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001020 break;
1021 case XML_SCHEMA_TYPE_SIMPLE:
Daniel Veillardc0826a72004-08-10 14:17:33 +00001022 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1023 *buf = xmlStrdup(xmlSchemaElemDesST);
1024 *buf = xmlStrcat(*buf, BAD_CAST " '");
1025 *buf = xmlStrcat(*buf, item->name);
1026 *buf = xmlStrcat(*buf, BAD_CAST "'");
1027 } else {
1028 *buf = xmlStrdup(xmlSchemaElemDesST);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001029 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001030 break;
1031 case XML_SCHEMA_TYPE_COMPLEX:
Daniel Veillardc0826a72004-08-10 14:17:33 +00001032 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1033 *buf = xmlStrdup(xmlSchemaElemDesCT);
1034 *buf = xmlStrcat(*buf, BAD_CAST " '");
1035 *buf = xmlStrcat(*buf, item->name);
1036 *buf = xmlStrcat(*buf, BAD_CAST "'");
1037 } else {
1038 *buf = xmlStrdup(xmlSchemaElemDesCT);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001039 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001040 break;
1041 case XML_SCHEMA_TYPE_ATTRIBUTE: {
1042 xmlSchemaAttributePtr attr;
1043
1044 attr = (xmlSchemaAttributePtr) item;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001045 if ((attr->flags & XML_SCHEMAS_ATTR_GLOBAL) ||
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001046 (attr->ref == NULL)) {
1047 *buf = xmlStrdup(xmlSchemaElemDesAttrDecl);
1048 *buf = xmlStrcat(*buf, BAD_CAST " '");
1049 *buf = xmlStrcat(*buf, attr->name);
1050 *buf = xmlStrcat(*buf, BAD_CAST "'");
1051 } else {
1052 *buf = xmlStrdup(xmlSchemaElemDesAttrRef);
1053 *buf = xmlStrcat(*buf, BAD_CAST " '");
1054 *buf = xmlStrcat(*buf, attr->refPrefix);
1055 *buf = xmlStrcat(*buf, BAD_CAST ":");
1056 *buf = xmlStrcat(*buf, attr->ref);
1057 *buf = xmlStrcat(*buf, BAD_CAST "'");
1058 }
1059 }
1060 break;
1061 case XML_SCHEMA_TYPE_ELEMENT: {
1062 xmlSchemaElementPtr elem;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001063
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001064 elem = (xmlSchemaElementPtr) item;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001065 if ((elem->flags & XML_SCHEMAS_ELEM_GLOBAL) ||
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001066 (elem->ref == NULL)) {
1067 *buf = xmlStrdup(xmlSchemaElemDesElemDecl);
1068 *buf = xmlStrcat(*buf, BAD_CAST " '");
1069 *buf = xmlStrcat(*buf, elem->name);
1070 *buf = xmlStrcat(*buf, BAD_CAST "'");
1071 } else {
1072 *buf = xmlStrdup(xmlSchemaElemDesElemRef);
1073 *buf = xmlStrcat(*buf, BAD_CAST " '");
1074 *buf = xmlStrcat(*buf, elem->refPrefix);
1075 *buf = xmlStrcat(*buf, BAD_CAST ":");
1076 *buf = xmlStrcat(*buf, elem->ref);
1077 *buf = xmlStrcat(*buf, BAD_CAST "'");
1078 }
1079 }
1080 break;
1081 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1082 case XML_SCHEMA_TYPE_IDC_KEY:
1083 case XML_SCHEMA_TYPE_IDC_KEYREF:
1084 if (item->type == XML_SCHEMA_TYPE_IDC_UNIQUE)
1085 *buf = xmlStrdup(BAD_CAST "unique '");
1086 else if (item->type == XML_SCHEMA_TYPE_IDC_KEY)
1087 *buf = xmlStrdup(BAD_CAST "key '");
1088 else
1089 *buf = xmlStrdup(BAD_CAST "keyRef '");
1090 *buf = xmlStrcat(*buf, ((xmlSchemaIDCPtr) item)->name);
1091 *buf = xmlStrcat(*buf, BAD_CAST "'");
1092 break;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00001093 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001094 *buf = xmlStrdup(xmlSchemaWildcardPCToString(
1095 ((xmlSchemaWildcardPtr) item)->processContents));
1096 *buf = xmlStrcat(*buf, BAD_CAST " wildcard");
1097 break;
1098 case XML_SCHEMA_FACET_MININCLUSIVE:
1099 case XML_SCHEMA_FACET_MINEXCLUSIVE:
1100 case XML_SCHEMA_FACET_MAXINCLUSIVE:
1101 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
1102 case XML_SCHEMA_FACET_TOTALDIGITS:
1103 case XML_SCHEMA_FACET_FRACTIONDIGITS:
1104 case XML_SCHEMA_FACET_PATTERN:
1105 case XML_SCHEMA_FACET_ENUMERATION:
1106 case XML_SCHEMA_FACET_WHITESPACE:
1107 case XML_SCHEMA_FACET_LENGTH:
1108 case XML_SCHEMA_FACET_MAXLENGTH:
1109 case XML_SCHEMA_FACET_MINLENGTH:
1110 *buf = xmlStrdup(BAD_CAST "facet '");
1111 *buf = xmlStrcat(*buf, xmlSchemaFacetTypeToString(item->type));
1112 *buf = xmlStrcat(*buf, BAD_CAST "'");
1113 break;
1114 case XML_SCHEMA_TYPE_NOTATION:
1115 *buf = xmlStrdup(BAD_CAST "notation");
1116 break;
1117 case XML_SCHEMA_TYPE_GROUP:
1118 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1119 *buf = xmlStrdup(xmlSchemaElemModelGrDef);
1120 *buf = xmlStrcat(*buf, BAD_CAST " '");
1121 *buf = xmlStrcat(*buf, item->name);
1122 *buf = xmlStrcat(*buf, BAD_CAST "'");
1123 } else {
1124 *buf = xmlStrdup(xmlSchemaElemModelGrRef);
1125 *buf = xmlStrcat(*buf, BAD_CAST " '");
1126 *buf = xmlStrcat(*buf, item->ref);
1127 *buf = xmlStrcat(*buf, BAD_CAST "'");
1128 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00001129 break;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001130 default:
William M. Brack2f2a6632004-08-20 23:09:47 +00001131 named = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001132 }
William M. Brack2f2a6632004-08-20 23:09:47 +00001133 } else
1134 named = 0;
1135
1136 if ((named == 0) && (itemNode != NULL)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00001137 xmlNodePtr elem;
1138
1139 if (itemNode->type == XML_ATTRIBUTE_NODE)
1140 elem = itemNode->parent;
1141 else
1142 elem = itemNode;
1143 *buf = xmlStrdup(BAD_CAST "Element '");
1144 if (parsing)
1145 *buf = xmlStrcat(*buf, elem->name);
1146 else
1147 *buf = xmlStrcat(*buf,
1148 xmlSchemaFormatNsPrefixLocal(&str, elem->ns, elem->name));
1149 *buf = xmlStrcat(*buf, BAD_CAST "'");
1150 }
1151 if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
1152 *buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
1153 *buf = xmlStrcat(*buf, xmlSchemaFormatNsPrefixLocal(&str,
1154 itemNode->ns, itemNode->name));
1155 *buf = xmlStrcat(*buf, BAD_CAST "'");
1156 }
1157 FREE_AND_NULL(str);
1158
1159 return (*buf);
1160}
1161
1162/**
1163 * xmlSchemaPFormatItemDes:
1164 * @buf: the string buffer
1165 * @item: the item as a schema object
1166 * @itemNode: the item as a node
1167 *
1168 * If the pointer to @buf is not NULL and @but holds no value,
1169 * the value is set to a item designation using
1170 * xmlSchemaFormatItemForReport. This one avoids adding
1171 * an attribute designation postfix.
1172 *
1173 * Returns a string of all enumeration elements.
1174 */
1175static void
1176xmlSchemaPRequestItemDes(xmlChar **buf,
1177 xmlSchemaTypePtr item,
1178 xmlNodePtr itemNode)
1179{
1180 if ((buf == 0) || (*buf != NULL))
1181 return;
1182 if (itemNode->type == XML_ATTRIBUTE_NODE)
1183 itemNode = itemNode->parent;
1184 xmlSchemaFormatItemForReport(buf, NULL, item, itemNode, 1);
1185}
1186
1187/**
1188 * xmlSchemaFormatFacetEnumSet:
1189 * @buf: the string buffer
1190 * @type: the type holding the enumeration facets
1191 *
1192 * Builds a string consisting of all enumeration elements.
1193 *
1194 * Returns a string of all enumeration elements.
1195 */
1196static const xmlChar *
1197xmlSchemaFormatFacetEnumSet(xmlChar **buf, xmlSchemaTypePtr type)
1198{
1199 xmlSchemaFacetLinkPtr link;
1200
1201 if (*buf != NULL)
1202 xmlFree(*buf);
1203 *buf = NULL;
1204 for (link = type->facetSet; link != NULL; link = link->next) {
1205 if (link->facet->type == XML_SCHEMA_FACET_ENUMERATION) {
1206 if (*buf == NULL) {
1207 *buf = xmlStrdup(BAD_CAST "'");
1208 *buf = xmlStrcat(*buf, link->facet->value);
1209 *buf = xmlStrcat(*buf, BAD_CAST "'");
1210 } else {
1211 *buf = xmlStrcat(*buf, BAD_CAST ", '");
1212 *buf = xmlStrcat(*buf, link->facet->value);
1213 *buf = xmlStrcat(*buf, BAD_CAST "'");
1214 }
1215 }
1216 }
1217 return ((const xmlChar *) *buf);
1218}
1219
1220/**
1221 * xmlSchemaVFacetErr:
1222 * @ctxt: the schema validation context
1223 * @error: the error code
1224 * @node: the node to be validated
1225 * @value: the value of the node
1226 * @type: the type holding the facet
1227 * @facet: the facet
1228 * @message: the error message of NULL
1229 * @str1: extra data
1230 * @str2: extra data
1231 * @str3: extra data
1232 *
1233 * Reports a facet validation error.
1234 * TODO: Should this report the value of an element as well?
1235 */
1236static void
1237xmlSchemaVFacetErr(xmlSchemaValidCtxtPtr ctxt,
1238 xmlParserErrors error,
1239 xmlNodePtr node,
1240 const xmlChar *value,
1241 unsigned long length,
1242 xmlSchemaTypePtr type,
1243 xmlSchemaFacetPtr facet,
1244 const char *message,
1245 const xmlChar *str1,
1246 const xmlChar *str2,
1247 const xmlChar *str3)
1248{
1249 xmlChar *str = NULL, *msg = NULL;
1250 xmlSchemaTypeType facetType;
1251
1252 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
1253 msg = xmlStrcat(msg, BAD_CAST " [");
1254 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1255 msg = xmlStrcat(msg, BAD_CAST ", facet '");
1256 if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
1257 facetType = XML_SCHEMA_FACET_ENUMERATION;
1258 /*
1259 * If enumerations are validated, one must not expect the
1260 * facet to be given.
1261 */
1262 } else
1263 facetType = facet->type;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001264 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facetType));
Daniel Veillardc0826a72004-08-10 14:17:33 +00001265 msg = xmlStrcat(msg, BAD_CAST "']: ");
1266 if (message == NULL) {
1267 /*
1268 * Use a default message.
1269 */
1270 if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
1271 (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
1272 (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
1273
1274 char len[25], actLen[25];
1275
1276 /* FIXME, TODO: What is the max expected string length of the
1277 * this value?
1278 */
1279 if (node->type == XML_ATTRIBUTE_NODE)
1280 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
1281 else
1282 msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
1283
1284 snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
1285 snprintf(actLen, 24, "%lu", length);
1286
1287 if (facetType == XML_SCHEMA_FACET_LENGTH)
1288 msg = xmlStrcat(msg,
1289 BAD_CAST "this differs from the allowed length of '%s'.\n");
1290 else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
1291 msg = xmlStrcat(msg,
1292 BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
1293 else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
1294 msg = xmlStrcat(msg,
1295 BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
1296
1297 if (node->type == XML_ATTRIBUTE_NODE)
1298 xmlSchemaVErrExt(ctxt, node, error,
1299 (const char *) msg,
1300 value, (const xmlChar *) actLen, (const xmlChar *) len,
1301 NULL, NULL);
1302 else
1303 xmlSchemaVErr(ctxt, node, error,
1304 (const char *) msg,
1305 (const xmlChar *) actLen, (const xmlChar *) len);
1306
1307 } else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
1308 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
1309 "of the set {%s}.\n");
1310 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
1311 xmlSchemaFormatFacetEnumSet(&str, type));
1312 } else if (facetType == XML_SCHEMA_FACET_PATTERN) {
1313 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
1314 "by the pattern '%s'.\n");
1315 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
1316 facet->value);
1317 } else if (node->type == XML_ATTRIBUTE_NODE) {
1318 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
1319 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value, NULL);
1320 } else {
1321 msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
1322 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
1323 }
1324 } else {
1325 msg = xmlStrcat(msg, (const xmlChar *) message);
1326 msg = xmlStrcat(msg, BAD_CAST ".\n");
1327 xmlSchemaVErr3(ctxt, node, error, (const char *) msg, str1, str2, str3);
1328 }
1329 FREE_AND_NULL(str)
1330 xmlFree(msg);
1331}
1332
1333/**
1334 * xmlSchemaVSimpleTypeErr:
1335 * @ctxt: the schema validation context
1336 * @error: the error code
1337 * @type: the type used for validation
1338 * @node: the node containing the validated value
1339 * @value: the validated value
1340 *
1341 * Reports a simple type validation error.
1342 * TODO: Should this report the value of an element as well?
1343 */
1344static void
1345xmlSchemaVSimpleTypeErr(xmlSchemaValidCtxtPtr ctxt,
1346 xmlParserErrors error,
1347 xmlNodePtr node,
1348 const xmlChar *value,
1349 xmlSchemaTypePtr type)
1350{
1351 xmlChar *str = NULL, *msg = NULL;
1352
1353 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
1354 msg = xmlStrcat(msg, BAD_CAST " [");
1355 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1356 if (node->type == XML_ATTRIBUTE_NODE) {
1357 msg = xmlStrcat(msg, BAD_CAST "]: The value '%s' is not valid.\n");
1358 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value, NULL);
1359 } else {
1360 msg = xmlStrcat(msg, BAD_CAST "]: The character content is not valid.\n");
1361 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
1362 }
1363 FREE_AND_NULL(str)
1364 xmlFree(msg);
1365}
1366
1367/**
William M. Brack2f2a6632004-08-20 23:09:47 +00001368 * xmlSchemaVComplexTypeErr:
1369 * @ctxt: the schema validation context
1370 * @error: the error code
1371 * @node: the node containing the validated value
1372 * @type: the complex type used for validation
1373 * @message: the error message
1374 *
1375 * Reports a complex type validation error.
1376 */
1377static void
1378xmlSchemaVComplexTypeErr(xmlSchemaValidCtxtPtr ctxt,
1379 xmlParserErrors error,
1380 xmlNodePtr node,
1381 xmlSchemaTypePtr type,
1382 const char *message)
1383{
1384 xmlChar *str = NULL, *msg = NULL;
1385
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00001386 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00001387 /* Specify the complex type only if it is global. */
1388 if ((type != NULL) && (type->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00001389 msg = xmlStrcat(msg, BAD_CAST " [");
1390 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1391 msg = xmlStrcat(msg, BAD_CAST "]");
1392 }
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001393 msg = xmlStrcat(msg, BAD_CAST ": %s.\n");
1394 xmlSchemaVErr(ctxt, node, error, (const char *) msg,
William M. Brack2f2a6632004-08-20 23:09:47 +00001395 (const xmlChar *) message, NULL);
1396 FREE_AND_NULL(str)
1397 xmlFree(msg);
1398}
1399
1400/**
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001401 * xmlSchemaVComplexTypeElemErr:
1402 * @ctxt: the schema validation context
1403 * @error: the error code
1404 * @node: the node containing the validated value
1405 * @type: the complex type used for validation
1406 * @message: the error message
1407 *
1408 * Reports a complex type validation error.
1409 */
1410static void
1411xmlSchemaVComplexTypeElemErr(xmlSchemaValidCtxtPtr ctxt,
1412 xmlParserErrors error,
1413 xmlNodePtr node,
1414 xmlSchemaTypePtr type,
1415 const char *message,
1416 int nbval,
1417 int nbneg,
1418 xmlChar **values)
1419{
1420 xmlChar *str = NULL, *msg = NULL;
1421 xmlChar *localName, *nsName;
1422 const xmlChar *cur, *end;
1423 int i;
1424
1425 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
1426 /* Specify the complex type only if it is global. */
1427 if ((type != NULL) && (type->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
1428 msg = xmlStrcat(msg, BAD_CAST " [");
1429 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1430 msg = xmlStrcat(msg, BAD_CAST "]");
1431 FREE_AND_NULL(str)
1432 }
1433 msg = xmlStrcat(msg, BAD_CAST ": ");
1434 msg = xmlStrcat(msg, (const xmlChar *) message);
1435 /*
1436 * Note that is does not make sense to report that we have a
1437 * wildcard here, since the wildcard might be unfolded into
1438 * multiple transitions.
1439 */
1440 if (nbval + nbneg > 0) {
1441 if (nbval + nbneg > 1) {
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00001442 str = xmlStrdup(BAD_CAST ". Expected is one of ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001443 } else
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00001444 str = xmlStrdup(BAD_CAST ". Expected is ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001445 nsName = NULL;
1446
1447 for (i = 0; i < nbval + nbneg; i++) {
1448 cur = values[i];
1449 /*
1450 * Get the local name.
1451 */
1452 localName = NULL;
1453
1454 end = cur;
1455 if (*end == '*') {
1456 localName = xmlStrdup(BAD_CAST "*");
1457 *end++;
1458 } else {
1459 while ((*end != 0) && (*end != '|'))
1460 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001461 localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001462 }
1463 if (*end != 0) {
1464 *end++;
1465 /*
1466 * Skip "*|*" if they come with negated expressions, since
1467 * they represent the same negated wildcard.
1468 */
1469 if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
1470 /*
1471 * Get the namespace name.
1472 */
1473 cur = end;
1474 if (*end == '*') {
1475 nsName = xmlStrdup(BAD_CAST "{*}");
1476 } else {
1477 while (*end != 0)
1478 end++;
1479
1480 if (i >= nbval)
1481 nsName = xmlStrdup(BAD_CAST "{##other:");
1482 else
1483 nsName = xmlStrdup(BAD_CAST "{");
1484
1485 nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
1486 nsName = xmlStrcat(nsName, BAD_CAST "}");
1487 }
1488 str = xmlStrcat(str, BAD_CAST nsName);
1489 FREE_AND_NULL(nsName)
1490 } else {
1491 FREE_AND_NULL(localName);
1492 continue;
1493 }
1494 }
1495 str = xmlStrcat(str, BAD_CAST localName);
1496 FREE_AND_NULL(localName);
1497
1498 if (i < nbval + nbneg -1)
1499 str = xmlStrcat(str, BAD_CAST ", ");
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00001500 }
1501 str = xmlStrcat(str, BAD_CAST " )");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001502 msg = xmlStrcat(msg, BAD_CAST str);
1503 FREE_AND_NULL(str)
1504 }
1505 msg = xmlStrcat(msg, BAD_CAST ".\n");
1506 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
1507 xmlFree(msg);
1508}
1509
1510/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00001511 * xmlSchemaPMissingAttrErr:
1512 * @ctxt: the schema validation context
1513 * @ownerDes: the designation of the owner
1514 * @ownerName: the name of the owner
1515 * @ownerItem: the owner as a schema object
1516 * @ownerElem: the owner as an element node
1517 * @node: the parent element node of the missing attribute node
1518 * @type: the corresponding type of the attribute node
1519 *
1520 * Reports an illegal attribute.
1521 */
1522static void
1523xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
1524 xmlParserErrors error,
1525 xmlChar **ownerDes,
1526 xmlSchemaTypePtr ownerItem,
1527 xmlNodePtr ownerElem,
1528 const char *name,
1529 const char *message)
1530{
1531 xmlChar *des = NULL;
1532
1533 if (ownerDes == NULL)
1534 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
1535 else if (*ownerDes == NULL) {
1536 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
1537 des = *ownerDes;
1538 } else
1539 des = *ownerDes;
1540 if (message != NULL)
1541 xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
1542 else
1543 xmlSchemaPErr(ctxt, ownerElem, error,
1544 "%s: The attribute '%s' is required but missing.\n",
1545 BAD_CAST des, BAD_CAST name);
1546 if (ownerDes == NULL)
1547 FREE_AND_NULL(des);
1548}
1549
William M. Brack2f2a6632004-08-20 23:09:47 +00001550/**
1551 * xmlSchemaCompTypeToString:
1552 * @type: the type of the schema item
1553 *
1554 * Returns the component name of a schema item.
1555 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001556static const char *
1557xmlSchemaCompTypeToString(xmlSchemaTypeType type)
1558{
1559 switch (type) {
1560 case XML_SCHEMA_TYPE_SIMPLE:
1561 return("simple type definition");
1562 case XML_SCHEMA_TYPE_COMPLEX:
1563 return("complex type definition");
1564 case XML_SCHEMA_TYPE_ELEMENT:
1565 return("element declaration");
1566 case XML_SCHEMA_TYPE_ATTRIBUTE:
1567 return("attribute declaration");
1568 case XML_SCHEMA_TYPE_GROUP:
1569 return("model group definition");
1570 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1571 return("attribute group definition");
1572 case XML_SCHEMA_TYPE_NOTATION:
1573 return("notation declaration");
1574 default:
1575 return("Not a schema component");
1576 }
1577}
1578/**
1579 * xmlSchemaPResCompAttrErr:
1580 * @ctxt: the schema validation context
1581 * @error: the error code
1582 * @ownerDes: the designation of the owner
1583 * @ownerItem: the owner as a schema object
1584 * @ownerElem: the owner as an element node
1585 * @name: the name of the attribute holding the QName
1586 * @refName: the referenced local name
1587 * @refURI: the referenced namespace URI
1588 * @message: optional message
1589 *
1590 * Used to report QName attribute values that failed to resolve
1591 * to schema components.
1592 */
1593static void
1594xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
1595 xmlParserErrors error,
1596 xmlChar **ownerDes,
1597 xmlSchemaTypePtr ownerItem,
1598 xmlNodePtr ownerElem,
1599 const char *name,
1600 const xmlChar *refName,
1601 const xmlChar *refURI,
1602 xmlSchemaTypeType refType,
1603 const char *refTypeStr)
1604{
1605 xmlChar *des = NULL, *strA = NULL;
1606
1607 if (ownerDes == NULL)
1608 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
1609 else if (*ownerDes == NULL) {
1610 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
1611 des = *ownerDes;
1612 } else
1613 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001614 if (refTypeStr == NULL)
1615 refTypeStr = xmlSchemaCompTypeToString(refType);
1616 xmlSchemaPErrExt(ctxt, ownerElem, error,
1617 NULL, NULL, NULL,
1618 "%s, attribute '%s': The QName value %s does not resolve to a(n) "
1619 "%s.\n", BAD_CAST des, BAD_CAST name,
1620 xmlSchemaFormatNsUriLocal(&strA, refURI, refName),
1621 BAD_CAST refTypeStr, NULL);
1622 if (ownerDes == NULL)
1623 FREE_AND_NULL(des)
1624 FREE_AND_NULL(strA)
1625}
1626
William M. Brack2f2a6632004-08-20 23:09:47 +00001627/**
1628 * xmlSchemaPCustomAttrErr:
1629 * @ctxt: the schema parser context
1630 * @error: the error code
1631 * @ownerDes: the designation of the owner
1632 * @ownerItem: the owner as a schema object
1633 * @attr: the illegal attribute node
1634 *
1635 * Reports an illegal attribute during the parse.
1636 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001637static void
1638xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00001639 xmlParserErrors error,
1640 xmlChar **ownerDes,
1641 xmlSchemaTypePtr ownerItem,
1642 xmlAttrPtr attr,
1643 const char *msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001644{
1645 xmlChar *des = NULL;
1646
1647 if (ownerDes == NULL)
1648 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
1649 else if (*ownerDes == NULL) {
1650 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
1651 des = *ownerDes;
1652 } else
1653 des = *ownerDes;
1654 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
1655 "%s, attribute '%s': %s.\n",
1656 BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
1657 if (ownerDes == NULL)
1658 FREE_AND_NULL(des);
1659}
1660
1661/**
1662 * xmlSchemaPIllegalAttrErr:
William M. Brack2f2a6632004-08-20 23:09:47 +00001663 * @ctxt: the schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00001664 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00001665 * @ownerDes: the designation of the attribute's owner
1666 * @ownerItem: the attribute's owner item
Daniel Veillardc0826a72004-08-10 14:17:33 +00001667 * @attr: the illegal attribute node
1668 *
William M. Brack2f2a6632004-08-20 23:09:47 +00001669 * Reports an illegal attribute during the parse.
Daniel Veillardc0826a72004-08-10 14:17:33 +00001670 */
1671static void
1672xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
1673 xmlParserErrors error,
1674 xmlChar **ownerDes,
1675 xmlSchemaTypePtr ownerItem,
1676 xmlAttrPtr attr)
1677{
1678 xmlChar *des = NULL, *strA = NULL;
1679
1680 if (ownerDes == NULL)
1681 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
1682 else if (*ownerDes == NULL) {
1683 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
1684 des = *ownerDes;
1685 } else
1686 des = *ownerDes;
1687 xmlSchemaPErr(ctxt, (xmlNodePtr) attr, error,
1688 "%s: The attribute '%s' is not allowed.\n", BAD_CAST des,
1689 xmlSchemaFormatNsPrefixLocal(&strA, attr->ns, attr->name));
1690 if (ownerDes == NULL)
1691 FREE_AND_NULL(des);
1692 FREE_AND_NULL(strA);
1693}
1694
William M. Brack2f2a6632004-08-20 23:09:47 +00001695/**
1696 * xmlSchemaPAquireDes:
1697 * @des: the first designation
1698 * @itemDes: the second designation
1699 * @item: the schema item
1700 * @itemElem: the node of the schema item
1701 *
1702 * Creates a designation for an item.
1703 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001704static void
1705xmlSchemaPAquireDes(xmlChar **des,
1706 xmlChar **itemDes,
1707 xmlSchemaTypePtr item,
1708 xmlNodePtr itemElem)
1709{
1710 if (itemDes == NULL)
1711 xmlSchemaFormatItemForReport(des, NULL, item, itemElem, 1);
1712 else if (*itemDes == NULL) {
1713 xmlSchemaFormatItemForReport(itemDes, NULL, item, itemElem, 1);
1714 *des = *itemDes;
1715 } else
1716 *des = *itemDes;
1717}
1718
William M. Brack2f2a6632004-08-20 23:09:47 +00001719/**
1720 * xmlSchemaPCustomErr:
1721 * @ctxt: the schema parser context
1722 * @error: the error code
1723 * @itemDes: the designation of the schema item
1724 * @item: the schema item
1725 * @itemElem: the node of the schema item
1726 * @message: the error message
1727 * @str1: an optional param for the error message
1728 * @str2: an optional param for the error message
1729 * @str3: an optional param for the error message
1730 *
1731 * Reports an error during parsing.
1732 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001733static void
1734xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
1735 xmlParserErrors error,
1736 xmlChar **itemDes,
1737 xmlSchemaTypePtr item,
1738 xmlNodePtr itemElem,
1739 const char *message,
1740 const xmlChar *str1,
1741 const xmlChar *str2,
1742 const xmlChar *str3)
1743{
1744 xmlChar *des = NULL, *msg = NULL;
1745
1746 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
1747 msg = xmlStrdup(BAD_CAST "%s: ");
1748 msg = xmlStrcat(msg, (const xmlChar *) message);
1749 msg = xmlStrcat(msg, BAD_CAST ".\n");
1750 if ((itemElem == NULL) && (item != NULL))
1751 itemElem = item->node;
1752 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
1753 (const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
1754 if (itemDes == NULL)
1755 FREE_AND_NULL(des);
1756 FREE_AND_NULL(msg);
1757}
1758
William M. Brack2f2a6632004-08-20 23:09:47 +00001759/**
1760 * xmlSchemaPCustomErr:
1761 * @ctxt: the schema parser context
1762 * @error: the error code
1763 * @itemDes: the designation of the schema item
1764 * @item: the schema item
1765 * @itemElem: the node of the schema item
1766 * @message: the error message
1767 * @str1: the optional param for the error message
1768 *
1769 * Reports an error during parsing.
1770 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001771static void
1772xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
1773 xmlParserErrors error,
1774 xmlChar **itemDes,
1775 xmlSchemaTypePtr item,
1776 xmlNodePtr itemElem,
1777 const char *message,
1778 const xmlChar *str1)
1779{
1780 xmlSchemaPCustomErrExt(ctxt, error, itemDes, item, itemElem, message,
1781 str1, NULL, NULL);
1782}
1783
William M. Brack2f2a6632004-08-20 23:09:47 +00001784/**
1785 * xmlSchemaPAttrUseErr:
1786 * @ctxt: the schema parser context
1787 * @error: the error code
1788 * @itemDes: the designation of the schema type
1789 * @item: the schema type
1790 * @itemElem: the node of the schema type
1791 * @attr: the invalid schema attribute
1792 * @message: the error message
1793 * @str1: the optional param for the error message
1794 *
1795 * Reports an attribute use error during parsing.
1796 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001797static void
1798xmlSchemaPAttrUseErr(xmlSchemaParserCtxtPtr ctxt,
1799 xmlParserErrors error,
1800 xmlChar **itemDes,
1801 xmlSchemaTypePtr item,
1802 xmlNodePtr itemElem,
1803 const xmlSchemaAttributePtr attr,
1804 const char *message,
1805 const xmlChar *str1)
1806{
1807 xmlChar *des = NULL, *strA = NULL, *msg = NULL;
1808
1809 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
1810 xmlSchemaFormatNsUriLocal(&strA, xmlSchemaGetAttrTargetNsURI(attr),
1811 xmlSchemaGetAttrName(attr));
1812 msg = xmlStrdup(BAD_CAST "%s, attr. use %s: ");
1813 msg = xmlStrcat(msg, (const xmlChar *) message);
1814 msg = xmlStrcat(msg, BAD_CAST ".\n");
1815 if ((itemElem == NULL) && (item != NULL))
1816 itemElem = item->node;
1817 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
1818 (const char *) msg, BAD_CAST des, BAD_CAST strA, str1, NULL, NULL);
1819 if (itemDes == NULL)
1820 FREE_AND_NULL(des);
1821 FREE_AND_NULL(strA);
1822 xmlFree(msg);
1823}
1824
William M. Brack2f2a6632004-08-20 23:09:47 +00001825/**
1826 * xmlSchemaPIllegalFacetAtomicErr:
1827 * @ctxt: the schema parser context
1828 * @error: the error code
1829 * @itemDes: the designation of the type
1830 * @item: the schema type
1831 * @baseItem: the base type of type
1832 * @facet: the illegal facet
1833 *
1834 * Reports an illegal facet for atomic simple types.
1835 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001836static void
1837xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
1838 xmlParserErrors error,
1839 xmlChar **itemDes,
1840 xmlSchemaTypePtr item,
1841 xmlSchemaTypePtr baseItem,
1842 xmlSchemaFacetPtr facet)
1843{
1844 xmlChar *des = NULL, *strT = NULL;
1845
1846 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
1847 xmlSchemaPErrExt(ctxt, item->node, error, NULL, NULL, NULL,
1848 "%s: The facet '%s' is not allowed on types derived from the "
1849 "type %s.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001850 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type),
Daniel Veillardc0826a72004-08-10 14:17:33 +00001851 xmlSchemaFormatItemForReport(&strT, NULL, baseItem, NULL, 1),
1852 NULL, NULL);
1853 if (itemDes == NULL)
1854 FREE_AND_NULL(des);
1855 FREE_AND_NULL(strT);
1856}
1857
William M. Brack2f2a6632004-08-20 23:09:47 +00001858/**
1859 * xmlSchemaPIllegalFacetListUnionErr:
1860 * @ctxt: the schema parser context
1861 * @error: the error code
1862 * @itemDes: the designation of the schema item involved
1863 * @item: the schema item involved
1864 * @facet: the illegal facet
1865 *
1866 * Reports an illegal facet for <list> and <union>.
1867 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001868static void
1869xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
1870 xmlParserErrors error,
1871 xmlChar **itemDes,
1872 xmlSchemaTypePtr item,
1873 xmlSchemaFacetPtr facet)
1874{
1875 xmlChar *des = NULL, *strT = NULL;
1876
1877 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
1878 xmlSchemaPErr(ctxt, item->node, error,
1879 "%s: The facet '%s' is not allowed.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001880 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +00001881 if (itemDes == NULL)
1882 FREE_AND_NULL(des);
1883 FREE_AND_NULL(strT);
1884}
1885
1886/**
1887 * xmlSchemaPMutualExclAttrErr:
1888 * @ctxt: the schema validation context
1889 * @error: the error code
1890 * @elemDes: the designation of the parent element node
1891 * @attr: the bad attribute node
1892 * @type: the corresponding type of the attribute node
1893 *
1894 * Reports an illegal attribute.
1895 */
1896static void
1897xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
1898 xmlParserErrors error,
1899 xmlChar **ownerDes,
1900 xmlSchemaTypePtr ownerItem,
1901 xmlAttrPtr attr,
1902 const char *name1,
1903 const char *name2)
1904{
1905 xmlChar *des = NULL;
1906
1907 if (ownerDes == NULL)
1908 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
1909 else if (*ownerDes == NULL) {
1910 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
1911 des = *ownerDes;
1912 } else
1913 des = *ownerDes;
1914 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
1915 "%s: The attributes '%s' and '%s' are mutually exclusive.\n",
1916 BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
1917 if (ownerDes == NULL)
1918 FREE_AND_NULL(des)
1919}
1920
1921/**
1922 * xmlSchemaPSimpleTypeErr:
1923 * @ctxt: the schema validation context
1924 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00001925 * @type: the type specifier
Daniel Veillardc0826a72004-08-10 14:17:33 +00001926 * @ownerDes: the designation of the owner
1927 * @ownerItem: the schema object if existent
1928 * @node: the validated node
1929 * @value: the validated value
1930 *
1931 * Reports a simple type validation error.
1932 * TODO: Should this report the value of an element as well?
1933 */
1934static void
1935xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
1936 xmlParserErrors error,
1937 xmlChar **ownerDes,
1938 xmlSchemaTypePtr ownerItem,
1939 xmlNodePtr node,
William M. Brack2f2a6632004-08-20 23:09:47 +00001940 xmlSchemaTypePtr type,
Daniel Veillardc0826a72004-08-10 14:17:33 +00001941 const char *typeDes,
1942 const xmlChar *value,
1943 const char *message,
1944 const xmlChar *str1,
1945 const xmlChar *str2)
1946{
William M. Brack2f2a6632004-08-20 23:09:47 +00001947 xmlChar *des = NULL, *strA = NULL, *strT = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001948
1949 if (ownerDes == NULL)
1950 xmlSchemaPRequestItemDes(&des, ownerItem, node);
1951 else if (*ownerDes == NULL) {
1952 xmlSchemaPRequestItemDes(ownerDes, ownerItem, node);
1953 des = *ownerDes;
1954 } else
1955 des = *ownerDes;
William M. Brack2f2a6632004-08-20 23:09:47 +00001956 if (type != NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001957 typeDes = (const char *) xmlSchemaFormatItemForReport(&strT, NULL, type, NULL, 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001958 if (message == NULL) {
1959 /*
1960 * Use default messages.
1961 */
1962 if (node->type == XML_ATTRIBUTE_NODE) {
1963 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
1964 "%s, attribute '%s' [%s]: The value '%s' is not "
1965 "valid.\n",
1966 BAD_CAST des, xmlSchemaFormatNsPrefixLocal(&strA, node->ns,
1967 node->name), BAD_CAST typeDes, value, NULL);
1968 } else {
1969 xmlSchemaPErr(ctxt, node, error,
1970 "%s [%s]: The character content is not valid.\n",
1971 BAD_CAST des, BAD_CAST typeDes);
1972 }
1973 } else {
1974 xmlChar *msg;
1975
1976 msg = xmlStrdup(BAD_CAST "%s");
1977 if (node->type == XML_ATTRIBUTE_NODE)
1978 msg = xmlStrcat(msg, BAD_CAST ", attribute '%s'");
1979 msg = xmlStrcat(msg, BAD_CAST " [%s]: ");
1980 msg = xmlStrcat(msg, (const xmlChar *) message);
1981 msg = xmlStrcat(msg, BAD_CAST ".\n");
1982 if (node->type == XML_ATTRIBUTE_NODE) {
1983 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
1984 (const char *) msg,
1985 BAD_CAST des, xmlSchemaFormatNsPrefixLocal(&strA,
1986 node->ns, node->name), BAD_CAST typeDes, str1, str2);
1987 } else {
1988 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
1989 (const char *) msg,
1990 BAD_CAST des, BAD_CAST typeDes, str1, str2, NULL);
1991 }
1992 xmlFree(msg);
1993 }
1994 /* Cleanup. */
1995 FREE_AND_NULL(strA)
1996 FREE_AND_NULL(strT)
1997 if (ownerDes == NULL)
1998 FREE_AND_NULL(des)
1999}
2000
William M. Brack2f2a6632004-08-20 23:09:47 +00002001/**
2002 * xmlSchemaPContentErr:
2003 * @ctxt: the schema parser context
2004 * @error: the error code
2005 * @onwerDes: the designation of the holder of the content
2006 * @ownerItem: the owner item of the holder of the content
2007 * @ownerElem: the node of the holder of the content
2008 * @child: the invalid child node
2009 * @message: the optional error message
2010 * @content: the optional string describing the correct content
2011 *
2012 * Reports an error concerning the content of a schema element.
2013 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002014static void
2015xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
2016 xmlParserErrors error,
2017 xmlChar **ownerDes,
2018 xmlSchemaTypePtr ownerItem,
2019 xmlNodePtr ownerElem,
2020 xmlNodePtr child,
2021 const char *message,
2022 const char *content)
2023{
2024 xmlChar *des = NULL;
2025
2026 if (ownerDes == NULL)
2027 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
2028 else if (*ownerDes == NULL) {
2029 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
2030 des = *ownerDes;
2031 } else
2032 des = *ownerDes;
2033 if (message != NULL)
2034 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2035 "%s: %s.\n",
2036 BAD_CAST des, BAD_CAST message);
2037 else {
2038 if (content != NULL) {
2039 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2040 "%s: The content is not valid. Expected is %s.\n",
2041 BAD_CAST des, BAD_CAST content);
2042 } else {
2043 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2044 "%s: The content is not valid.\n",
2045 BAD_CAST des, NULL);
2046 }
2047 }
2048 if (ownerDes == NULL)
2049 FREE_AND_NULL(des)
2050}
2051
2052/**
2053 * xmlSchemaVIllegalAttrErr:
2054 * @ctxt: the schema validation context
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002055 * @error: the error code
Daniel Veillardc0826a72004-08-10 14:17:33 +00002056 * @attr: the illegal attribute node
2057 *
2058 * Reports an illegal attribute.
2059 */
2060static void
2061xmlSchemaVIllegalAttrErr(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002062 xmlParserErrors error,
William M. Brack2f2a6632004-08-20 23:09:47 +00002063 xmlAttrPtr attr)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002064{
2065 xmlChar *strE = NULL, *strA = NULL;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002066
2067 xmlSchemaVErr(ctxt, (xmlNodePtr) attr,
2068 error,
2069 /* XML_SCHEMAS_ERR_ATTRUNKNOWN, */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002070 "%s: The attribute '%s' is not allowed.\n",
2071 xmlSchemaFormatItemForReport(&strE, NULL, NULL, attr->parent, 0),
2072 xmlSchemaFormatNsPrefixLocal(&strA, attr->ns, attr->name));
2073 FREE_AND_NULL(strE)
2074 FREE_AND_NULL(strA)
2075}
2076
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002077
2078static int
2079xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
2080{
2081 switch (item->type) {
2082 case XML_SCHEMA_TYPE_COMPLEX:
2083 case XML_SCHEMA_TYPE_SIMPLE:
2084 case XML_SCHEMA_TYPE_GROUP:
2085 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
2086 return(1);
2087 break;
2088 case XML_SCHEMA_TYPE_ELEMENT:
2089 if ( ((xmlSchemaElementPtr) item)->flags &
2090 XML_SCHEMAS_ELEM_GLOBAL)
2091 return(1);
2092 break;
2093 case XML_SCHEMA_TYPE_ATTRIBUTE:
2094 if ( ((xmlSchemaAttributePtr) item)->flags &
2095 XML_SCHEMAS_ATTR_GLOBAL)
2096 return(1);
2097 break;
2098 /* Note that attribute groups are always global. */
2099 default:
2100 return(1);
2101 }
2102 return (0);
2103}
2104
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002105
2106static void
2107xmlSchemaStreamVCustomErr(xmlSchemaValidCtxtPtr vctxt,
2108 xmlParserErrors error,
2109 xmlSchemaNodeInfoPtr nodeInfo,
2110 xmlSchemaTypePtr type,
2111 const char *message,
2112 const xmlChar *str1,
2113 const xmlChar *str2)
2114{
2115 xmlChar *msg = NULL, *str = NULL;
2116
2117 msg = xmlStrdup(BAD_CAST "Element '");
2118
2119 if (vctxt->elemInfos[vctxt->depth] != nodeInfo) {
2120 xmlSchemaNodeInfoPtr elemInfo;
2121 /*
2122 * The node info is an attribute info.
2123 */
2124 elemInfo = vctxt->elemInfos[vctxt->depth];
2125 msg = xmlStrcat(msg, xmlSchemaFormatQName(&str,
2126 elemInfo->namespaceName, elemInfo->localName));
2127 msg = xmlStrcat(msg, BAD_CAST "', ");
2128 msg = xmlStrcat(msg, BAD_CAST "attribute '");
2129 }
2130 msg = xmlStrcat(msg, xmlSchemaFormatQName(&str,
2131 nodeInfo->namespaceName, nodeInfo->localName));
2132 msg = xmlStrcat(msg, BAD_CAST "'");
2133
2134 if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
2135 msg = xmlStrcat(msg, BAD_CAST " [");
2136 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str,
2137 NULL, type, NULL, 0));
2138 msg = xmlStrcat(msg, BAD_CAST "]");
2139 }
2140 msg = xmlStrcat(msg, BAD_CAST ": ");
2141
2142 msg = xmlStrcat(msg, (const xmlChar *) message);
2143 msg = xmlStrcat(msg, BAD_CAST ".\n");
2144 xmlSchemaVErr(vctxt, nodeInfo->node, error, (const char *) msg,
2145 str1, str2);
2146 FREE_AND_NULL(msg)
2147 FREE_AND_NULL(str)
2148}
2149
William M. Brack2f2a6632004-08-20 23:09:47 +00002150/**
2151 * xmlSchemaVCustomErr:
2152 * @ctxt: the schema validation context
2153 * @error: the error code
2154 * @node: the validated node
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002155 * @type: the schema type of the validated node
William M. Brack2f2a6632004-08-20 23:09:47 +00002156 * @message: the error message
2157 * @str1: the optional param for the message
2158 *
2159 * Reports a validation error.
2160 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002161static void
2162xmlSchemaVCustomErr(xmlSchemaValidCtxtPtr ctxt,
2163 xmlParserErrors error,
2164 xmlNodePtr node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002165 xmlSchemaTypePtr type,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002166 const char *message,
2167 const xmlChar *str1)
2168{
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002169 xmlChar *msg = NULL, *str = NULL;
2170
2171 if (node == NULL) {
2172 xmlSchemaVErr(ctxt, NULL,
2173 XML_SCHEMAV_INTERNAL,
2174 "Internal error: xmlSchemaVCustomErr, no node "
2175 "given.\n", NULL, NULL);
2176 return;
2177 }
2178 /* TODO: Are the HTML and DOCB doc nodes expected here? */
2179 if (node->type != XML_DOCUMENT_NODE) {
2180 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002181 if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002182 msg = xmlStrcat(msg, BAD_CAST " [");
2183 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
2184 msg = xmlStrcat(msg, BAD_CAST "]");
2185 }
2186 msg = xmlStrcat(msg, BAD_CAST ": ");
2187 } else
2188 msg = xmlStrdup((const xmlChar *) "");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002189 msg = xmlStrcat(msg, (const xmlChar *) message);
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002190 msg = xmlStrcat(msg, BAD_CAST ".\n");
2191 xmlSchemaVErr(ctxt, node, error, (const char *) msg, str1, NULL);
2192 FREE_AND_NULL(msg)
2193 FREE_AND_NULL(str)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002194}
2195
William M. Brack2f2a6632004-08-20 23:09:47 +00002196/**
William M. Brack2f2a6632004-08-20 23:09:47 +00002197 * xmlSchemaVWildcardErr:
2198 * @ctxt: the schema validation context
2199 * @error: the error code
2200 * @node: the validated node
2201 * @wild: the wildcard used
2202 * @message: the error message
2203 *
2204 * Reports an validation-by-wildcard error.
2205 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002206static void
2207xmlSchemaVWildcardErr(xmlSchemaValidCtxtPtr ctxt,
2208 xmlParserErrors error,
2209 xmlNodePtr node,
2210 xmlSchemaWildcardPtr wild,
2211 const char *message)
2212{
2213 xmlChar *des = NULL, *msg = NULL;
2214
2215 xmlSchemaFormatItemForReport(&des, NULL, NULL, node, 0);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00002216 msg = xmlStrdup(BAD_CAST "%s [");
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00002217 msg = xmlStrcat(msg, xmlSchemaWildcardPCToString(wild->processContents));
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002218 msg = xmlStrcat(msg, BAD_CAST " wildcard]: ");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002219 msg = xmlStrcat(msg, (const xmlChar *) message);
2220 msg = xmlStrcat(msg, BAD_CAST ".\n");
2221 xmlSchemaVErr(ctxt, node, error, (const char *) msg, BAD_CAST des, NULL);
2222 FREE_AND_NULL(des);
2223 FREE_AND_NULL(msg);
2224}
2225
2226/**
2227 * xmlSchemaVMissingAttrErr:
2228 * @ctxt: the schema validation context
2229 * @node: the parent element node of the missing attribute node
2230 * @type: the corresponding type of the attribute node
2231 *
2232 * Reports an illegal attribute.
2233 */
2234static void
2235xmlSchemaVMissingAttrErr(xmlSchemaValidCtxtPtr ctxt,
2236 xmlNodePtr elem,
2237 xmlSchemaAttributePtr type)
2238{
2239 const xmlChar *name, *uri;
2240 xmlChar *strE = NULL, *strA = NULL;
2241
2242 if (type->ref != NULL) {
2243 name = type->ref;
2244 uri = type->refNs;
2245 } else {
2246 name = type->name;
2247 uri = type->targetNamespace;
2248 }
2249 xmlSchemaVErr(ctxt, elem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002250 XML_SCHEMAV_CVC_COMPLEX_TYPE_4,
2251 /* XML_SCHEMAS_ERR_MISSING, */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002252 "%s: The attribute %s is required but missing.\n",
2253 xmlSchemaFormatItemForReport(&strE, NULL, NULL, elem, 0),
2254 xmlSchemaFormatNsUriLocal(&strA, uri, name));
2255 FREE_AND_NULL(strE)
2256 FREE_AND_NULL(strA)
2257}
2258
Daniel Veillard4255d502002-04-16 15:50:10 +00002259/************************************************************************
2260 * *
2261 * Allocation functions *
2262 * *
2263 ************************************************************************/
2264
2265/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002266 * xmlSchemaNewSchemaForParserCtxt:
William M. Brack08171912003-12-29 02:52:11 +00002267 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00002268 *
2269 * Allocate a new Schema structure.
2270 *
2271 * Returns the newly allocated structure or NULL in case or error
2272 */
2273static xmlSchemaPtr
2274xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
2275{
2276 xmlSchemaPtr ret;
2277
2278 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
2279 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002280 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002281 return (NULL);
2282 }
2283 memset(ret, 0, sizeof(xmlSchema));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002284 ret->dict = ctxt->dict;
Daniel Veillard500a1de2004-03-22 15:22:58 +00002285 xmlDictReference(ret->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00002286
2287 return (ret);
2288}
2289
2290/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002291 * xmlSchemaNewSchema:
2292 * @ctxt: a schema validation context
2293 *
2294 * Allocate a new Schema structure.
2295 *
2296 * Returns the newly allocated structure or NULL in case or error
2297 */
2298static xmlSchemaAssemblePtr
2299xmlSchemaNewAssemble(void)
2300{
2301 xmlSchemaAssemblePtr ret;
2302
2303 ret = (xmlSchemaAssemblePtr) xmlMalloc(sizeof(xmlSchemaAssemble));
2304 if (ret == NULL) {
2305 /* xmlSchemaPErrMemory(ctxt, "allocating assemble info", NULL); */
2306 return (NULL);
2307 }
2308 memset(ret, 0, sizeof(xmlSchemaAssemble));
2309 ret->items = NULL;
2310 return (ret);
2311}
2312
2313/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002314 * xmlSchemaNewFacet:
Daniel Veillard4255d502002-04-16 15:50:10 +00002315 *
2316 * Allocate a new Facet structure.
2317 *
2318 * Returns the newly allocated structure or NULL in case or error
2319 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00002320xmlSchemaFacetPtr
2321xmlSchemaNewFacet(void)
Daniel Veillard4255d502002-04-16 15:50:10 +00002322{
2323 xmlSchemaFacetPtr ret;
2324
2325 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
2326 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002327 return (NULL);
2328 }
2329 memset(ret, 0, sizeof(xmlSchemaFacet));
2330
2331 return (ret);
2332}
2333
2334/**
2335 * xmlSchemaNewAnnot:
William M. Brack08171912003-12-29 02:52:11 +00002336 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00002337 * @node: a node
2338 *
2339 * Allocate a new annotation structure.
2340 *
2341 * Returns the newly allocated structure or NULL in case or error
2342 */
2343static xmlSchemaAnnotPtr
2344xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
2345{
2346 xmlSchemaAnnotPtr ret;
2347
2348 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
2349 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002350 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
Daniel Veillard4255d502002-04-16 15:50:10 +00002351 return (NULL);
2352 }
2353 memset(ret, 0, sizeof(xmlSchemaAnnot));
2354 ret->content = node;
2355 return (ret);
2356}
2357
2358/**
Daniel Veillardfdc91562002-07-01 21:52:03 +00002359 * xmlSchemaFreeAnnot:
2360 * @annot: a schema type structure
2361 *
2362 * Deallocate a annotation structure
2363 */
2364static void
2365xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
2366{
2367 if (annot == NULL)
2368 return;
2369 xmlFree(annot);
2370}
2371
2372/**
Daniel Veillard1d913862003-11-21 00:28:39 +00002373 * xmlSchemaFreeImport:
2374 * @import: a schema import structure
2375 *
2376 * Deallocate an import structure
2377 */
2378static void
2379xmlSchemaFreeImport(xmlSchemaImportPtr import)
2380{
2381 if (import == NULL)
2382 return;
2383
2384 xmlSchemaFree(import->schema);
William M. Brack2f2a6632004-08-20 23:09:47 +00002385 xmlFreeDoc(import->doc);
Daniel Veillard1d913862003-11-21 00:28:39 +00002386 xmlFree(import);
2387}
2388
2389/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002390 * xmlSchemaFreeInclude:
2391 * @include: a schema include structure
2392 *
2393 * Deallocate an include structure
2394 */
2395static void
2396xmlSchemaFreeInclude(xmlSchemaIncludePtr include)
2397{
2398 if (include == NULL)
2399 return;
2400
2401 xmlFreeDoc(include->doc);
2402 xmlFree(include);
2403}
2404
2405/**
2406 * xmlSchemaFreeIncludeList:
2407 * @includes: a schema include list
2408 *
2409 * Deallocate an include structure
2410 */
2411static void
2412xmlSchemaFreeIncludeList(xmlSchemaIncludePtr includes)
2413{
2414 xmlSchemaIncludePtr next;
2415
2416 while (includes != NULL) {
2417 next = includes->next;
2418 xmlSchemaFreeInclude(includes);
2419 includes = next;
2420 }
2421}
2422
2423/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002424 * xmlSchemaFreeNotation:
2425 * @schema: a schema notation structure
2426 *
2427 * Deallocate a Schema Notation structure.
2428 */
2429static void
2430xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
2431{
2432 if (nota == NULL)
2433 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002434 xmlFree(nota);
2435}
2436
2437/**
2438 * xmlSchemaFreeAttribute:
2439 * @schema: a schema attribute structure
2440 *
2441 * Deallocate a Schema Attribute structure.
2442 */
2443static void
2444xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
2445{
2446 if (attr == NULL)
2447 return;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002448 if (attr->annot != NULL)
2449 xmlSchemaFreeAnnot(attr->annot);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002450 if (attr->defVal != NULL)
2451 xmlSchemaFreeValue(attr->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00002452 xmlFree(attr);
2453}
2454
2455/**
Daniel Veillard3646d642004-06-02 19:19:14 +00002456 * xmlSchemaFreeWildcardNsSet:
2457 * set: a schema wildcard namespace
2458 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00002459 * Deallocates a list of wildcard constraint structures.
Daniel Veillard3646d642004-06-02 19:19:14 +00002460 */
2461static void
2462xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
2463{
2464 xmlSchemaWildcardNsPtr next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002465
Daniel Veillard3646d642004-06-02 19:19:14 +00002466 while (set != NULL) {
2467 next = set->next;
2468 xmlFree(set);
2469 set = next;
2470 }
2471}
2472
2473/**
2474 * xmlSchemaFreeWildcard:
Daniel Veillard01fa6152004-06-29 17:04:39 +00002475 * @wildcard: a wildcard structure
Daniel Veillard3646d642004-06-02 19:19:14 +00002476 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00002477 * Deallocates a wildcard structure.
Daniel Veillard3646d642004-06-02 19:19:14 +00002478 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00002479void
Daniel Veillard3646d642004-06-02 19:19:14 +00002480xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
2481{
2482 if (wildcard == NULL)
2483 return;
2484 if (wildcard->annot != NULL)
2485 xmlSchemaFreeAnnot(wildcard->annot);
2486 if (wildcard->nsSet != NULL)
2487 xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
2488 if (wildcard->negNsSet != NULL)
2489 xmlFree(wildcard->negNsSet);
2490 xmlFree(wildcard);
2491}
2492
2493/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002494 * xmlSchemaFreeAttributeGroup:
2495 * @schema: a schema attribute group structure
2496 *
2497 * Deallocate a Schema Attribute Group structure.
2498 */
2499static void
2500xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attr)
2501{
2502 if (attr == NULL)
2503 return;
Daniel Veillard3646d642004-06-02 19:19:14 +00002504 if (attr->annot != NULL)
2505 xmlSchemaFreeAnnot(attr->annot);
2506 if ((attr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) &&
2507 (attr->attributeWildcard != NULL))
2508 xmlSchemaFreeWildcard(attr->attributeWildcard);
2509
Daniel Veillard4255d502002-04-16 15:50:10 +00002510 xmlFree(attr);
2511}
2512
2513/**
Daniel Veillard3646d642004-06-02 19:19:14 +00002514 * xmlSchemaFreeAttributeUseList:
Daniel Veillard01fa6152004-06-29 17:04:39 +00002515 * @attrUse: an attribute link
Daniel Veillard3646d642004-06-02 19:19:14 +00002516 *
2517 * Deallocate a list of schema attribute uses.
2518 */
2519static void
2520xmlSchemaFreeAttributeUseList(xmlSchemaAttributeLinkPtr attrUse)
2521{
2522 xmlSchemaAttributeLinkPtr next;
2523
2524 while (attrUse != NULL) {
2525 next = attrUse->next;
2526 xmlFree(attrUse);
2527 attrUse = next;
2528 }
2529}
2530
2531/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00002532 * xmlSchemaFreeTypeLinkList:
2533 * @alink: a type link
2534 *
2535 * Deallocate a list of types.
2536 */
2537static void
2538xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
2539{
2540 xmlSchemaTypeLinkPtr next;
2541
2542 while (link != NULL) {
2543 next = link->next;
2544 xmlFree(link);
2545 link = next;
2546 }
2547}
2548
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00002549#ifdef IDC_ENABLED
2550static void
2551xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
2552{
2553 xmlSchemaIDCStateObjPtr next;
2554 while (sto != NULL) {
2555 next = sto->next;
2556 if (sto->history != NULL)
2557 xmlFree(sto->history);
2558 if (sto->xpathCtxt != NULL)
2559 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
2560 xmlFree(sto);
2561 sto = next;
2562 }
2563}
2564
2565/**
2566 * xmlSchemaFreeIDC:
2567 * @idc: a identity-constraint definition
2568 *
2569 * Deallocates an identity-constraint definition.
2570 */
2571static void
2572xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)
2573{
2574 xmlSchemaIDCSelectPtr cur, prev;
2575
2576 if (idcDef == NULL)
2577 return;
2578 if (idcDef->annot != NULL)
2579 xmlSchemaFreeAnnot(idcDef->annot);
2580 if (idcDef->ref != NULL)
2581 xmlFree(idcDef->ref);
2582 /* Selector */
2583 if (idcDef->selector != NULL) {
2584 if (idcDef->selector->xpathComp != NULL)
2585 xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp);
2586 xmlFree(idcDef->selector);
2587 }
2588 /* Fields */
2589 if (idcDef->fields != NULL) {
2590 cur = idcDef->fields;
2591 do {
2592 prev = cur;
2593 cur = cur->next;
2594 if (prev->xpathComp != NULL)
2595 xmlFreePattern((xmlPatternPtr) prev->xpathComp);
2596 xmlFree(prev);
2597 } while (cur != NULL);
2598 }
2599 xmlFree(idcDef);
2600}
2601#endif /* IDC_ENABLED */
2602
Daniel Veillard01fa6152004-06-29 17:04:39 +00002603/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002604 * xmlSchemaFreeElement:
2605 * @schema: a schema element structure
2606 *
2607 * Deallocate a Schema Element structure.
2608 */
2609static void
2610xmlSchemaFreeElement(xmlSchemaElementPtr elem)
2611{
2612 if (elem == NULL)
2613 return;
Daniel Veillard32370232002-10-16 14:08:14 +00002614 if (elem->annot != NULL)
2615 xmlSchemaFreeAnnot(elem->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00002616 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002617 xmlRegFreeRegexp(elem->contModel);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002618 if (elem->defVal != NULL)
2619 xmlSchemaFreeValue(elem->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00002620 xmlFree(elem);
2621}
2622
2623/**
2624 * xmlSchemaFreeFacet:
2625 * @facet: a schema facet structure
2626 *
2627 * Deallocate a Schema Facet structure.
2628 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00002629void
Daniel Veillard4255d502002-04-16 15:50:10 +00002630xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
2631{
2632 if (facet == NULL)
2633 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002634 if (facet->val != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002635 xmlSchemaFreeValue(facet->val);
Daniel Veillard4255d502002-04-16 15:50:10 +00002636 if (facet->regexp != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002637 xmlRegFreeRegexp(facet->regexp);
Daniel Veillardfdc91562002-07-01 21:52:03 +00002638 if (facet->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002639 xmlSchemaFreeAnnot(facet->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00002640 xmlFree(facet);
2641}
2642
2643/**
2644 * xmlSchemaFreeType:
2645 * @type: a schema type structure
2646 *
2647 * Deallocate a Schema Type structure.
2648 */
2649void
2650xmlSchemaFreeType(xmlSchemaTypePtr type)
2651{
2652 if (type == NULL)
2653 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002654 if (type->annot != NULL)
Daniel Veillard32370232002-10-16 14:08:14 +00002655 xmlSchemaFreeAnnot(type->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00002656 if (type->facets != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002657 xmlSchemaFacetPtr facet, next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002658
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002659 facet = type->facets;
2660 while (facet != NULL) {
2661 next = facet->next;
2662 xmlSchemaFreeFacet(facet);
2663 facet = next;
2664 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002665 }
Daniel Veillard3646d642004-06-02 19:19:14 +00002666 if (type->type != XML_SCHEMA_TYPE_BASIC) {
2667 if (type->attributeUses != NULL)
2668 xmlSchemaFreeAttributeUseList(type->attributeUses);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002669 if ((type->attributeWildcard != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +00002670 ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002671 (type->flags & XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD))) {
2672 /*
2673 * NOTE: The only case where an attribute wildcard
2674 * is not owned, is if a complex type inherits it
2675 * from a base type.
2676 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002677 xmlSchemaFreeWildcard(type->attributeWildcard);
2678 }
2679 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00002680 if (type->memberTypes != NULL)
2681 xmlSchemaFreeTypeLinkList(type->memberTypes);
2682 if (type->facetSet != NULL) {
2683 xmlSchemaFacetLinkPtr next, link;
2684
2685 link = type->facetSet;
2686 do {
2687 next = link->next;
2688 xmlFree(link);
2689 link = next;
2690 } while (link != NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002691 }
2692 if (type->contModel != NULL)
2693 xmlRegFreeRegexp(type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00002694 xmlFree(type);
2695}
2696
2697/**
Daniel Veillardb0f397e2003-12-23 23:30:53 +00002698 * xmlSchemaFreeTypeList:
2699 * @type: a schema type structure
2700 *
2701 * Deallocate a Schema Type structure.
2702 */
2703static void
2704xmlSchemaFreeTypeList(xmlSchemaTypePtr type)
2705{
2706 xmlSchemaTypePtr next;
2707
2708 while (type != NULL) {
2709 next = type->redef;
2710 xmlSchemaFreeType(type);
2711 type = next;
2712 }
2713}
2714
2715/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002716 * xmlSchemaFree:
2717 * @schema: a schema structure
2718 *
2719 * Deallocate a Schema structure.
2720 */
2721void
2722xmlSchemaFree(xmlSchemaPtr schema)
2723{
2724 if (schema == NULL)
2725 return;
2726
Daniel Veillard4255d502002-04-16 15:50:10 +00002727 if (schema->notaDecl != NULL)
2728 xmlHashFree(schema->notaDecl,
2729 (xmlHashDeallocator) xmlSchemaFreeNotation);
2730 if (schema->attrDecl != NULL)
2731 xmlHashFree(schema->attrDecl,
2732 (xmlHashDeallocator) xmlSchemaFreeAttribute);
2733 if (schema->attrgrpDecl != NULL)
2734 xmlHashFree(schema->attrgrpDecl,
2735 (xmlHashDeallocator) xmlSchemaFreeAttributeGroup);
2736 if (schema->elemDecl != NULL)
2737 xmlHashFree(schema->elemDecl,
2738 (xmlHashDeallocator) xmlSchemaFreeElement);
2739 if (schema->typeDecl != NULL)
2740 xmlHashFree(schema->typeDecl,
Daniel Veillardb0f397e2003-12-23 23:30:53 +00002741 (xmlHashDeallocator) xmlSchemaFreeTypeList);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00002742 if (schema->groupDecl != NULL)
2743 xmlHashFree(schema->groupDecl,
2744 (xmlHashDeallocator) xmlSchemaFreeType);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00002745#ifdef IDC_ENABLED
2746 if (schema->idcDef != NULL)
2747 xmlHashFree(schema->idcDef,
2748 (xmlHashDeallocator) xmlSchemaFreeIDC);
2749#endif
Daniel Veillard1d913862003-11-21 00:28:39 +00002750 if (schema->schemasImports != NULL)
2751 xmlHashFree(schema->schemasImports,
2752 (xmlHashDeallocator) xmlSchemaFreeImport);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002753 if (schema->includes != NULL) {
2754 xmlSchemaFreeIncludeList((xmlSchemaIncludePtr) schema->includes);
2755 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002756 if (schema->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002757 xmlSchemaFreeAnnot(schema->annot);
Daniel Veillarddda22c12004-01-24 08:31:30 +00002758 if (schema->doc != NULL && !schema->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002759 xmlFreeDoc(schema->doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002760 xmlDictFree(schema->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00002761 xmlFree(schema);
2762}
2763
2764/************************************************************************
2765 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00002766 * Debug functions *
2767 * *
2768 ************************************************************************/
2769
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002770#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002771
Daniel Veillard4255d502002-04-16 15:50:10 +00002772/**
2773 * xmlSchemaElementDump:
2774 * @elem: an element
2775 * @output: the file output
2776 *
2777 * Dump the element
2778 */
2779static void
2780xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002781 const xmlChar * name ATTRIBUTE_UNUSED,
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002782 const xmlChar * namespace ATTRIBUTE_UNUSED,
2783 const xmlChar * context ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00002784{
2785 if (elem == NULL)
2786 return;
2787
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002788 if (elem->flags & XML_SCHEMAS_ELEM_REF) {
2789 fprintf(output, "Particle: %s", name);
2790 fprintf(output, ", term element: %s", elem->ref);
2791 if (elem->refNs != NULL)
2792 fprintf(output, " ns %s", elem->refNs);
2793 } else {
2794 fprintf(output, "Element");
2795 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
2796 fprintf(output, " (global)");
2797 fprintf(output, ": %s ", elem->name);
2798 if (namespace != NULL)
2799 fprintf(output, "ns %s", namespace);
2800 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002801 fprintf(output, "\n");
2802 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002803 fprintf(output, " min %d ", elem->minOccurs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002804 if (elem->maxOccurs >= UNBOUNDED)
2805 fprintf(output, "max: unbounded\n");
2806 else if (elem->maxOccurs != 1)
2807 fprintf(output, "max: %d\n", elem->maxOccurs);
2808 else
2809 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002810 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002811 /*
2812 * Misc other properties.
2813 */
2814 if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
2815 (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
2816 (elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
2817 (elem->flags & XML_SCHEMAS_ELEM_DEFAULT) ||
2818 (elem->id != NULL)) {
2819 fprintf(output, " props: ");
2820 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
2821 fprintf(output, "[fixed] ");
2822 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
2823 fprintf(output, "[default] ");
2824 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
2825 fprintf(output, "[abstract] ");
2826 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
2827 fprintf(output, "[nillable] ");
2828 if (elem->id != NULL)
2829 fprintf(output, "[id: '%s'] ", elem->id);
2830 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002831 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002832 /*
2833 * Default/fixed value.
2834 */
Daniel Veillard4255d502002-04-16 15:50:10 +00002835 if (elem->value != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002836 fprintf(output, " value: '%s'\n", elem->value);
2837 /*
2838 * Type.
2839 */
2840 if (elem->namedType != NULL) {
2841 fprintf(output, " type: %s ", elem->namedType);
2842 if (elem->namedTypeNs != NULL)
2843 fprintf(output, "ns %s\n", elem->namedTypeNs);
2844 else
2845 fprintf(output, "\n");
2846 }
2847 /*
2848 * Substitution group.
2849 */
2850 if (elem->substGroup != NULL) {
2851 fprintf(output, " substitutionGroup: %s ", elem->substGroup);
2852 if (elem->substGroupNs != NULL)
2853 fprintf(output, "ns %s\n", elem->substGroupNs);
2854 else
2855 fprintf(output, "\n");
2856 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002857}
2858
2859/**
2860 * xmlSchemaAnnotDump:
2861 * @output: the file output
2862 * @annot: a annotation
2863 *
2864 * Dump the annotation
2865 */
2866static void
2867xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
2868{
2869 xmlChar *content;
2870
2871 if (annot == NULL)
2872 return;
2873
2874 content = xmlNodeGetContent(annot->content);
2875 if (content != NULL) {
2876 fprintf(output, " Annot: %s\n", content);
2877 xmlFree(content);
2878 } else
2879 fprintf(output, " Annot: empty\n");
2880}
2881
2882/**
2883 * xmlSchemaTypeDump:
2884 * @output: the file output
2885 * @type: a type structure
2886 *
2887 * Dump a SchemaType structure
2888 */
2889static void
2890xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
2891{
2892 if (type == NULL) {
2893 fprintf(output, "Type: NULL\n");
2894 return;
2895 }
2896 fprintf(output, "Type: ");
2897 if (type->name != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002898 fprintf(output, "%s ", type->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00002899 else
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002900 fprintf(output, "no name ");
2901 if (type->targetNamespace != NULL)
2902 fprintf(output, "ns %s ", type->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00002903 switch (type->type) {
2904 case XML_SCHEMA_TYPE_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002905 fprintf(output, "[basic] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002906 break;
2907 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002908 fprintf(output, "[simple] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002909 break;
2910 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002911 fprintf(output, "[complex] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002912 break;
2913 case XML_SCHEMA_TYPE_SEQUENCE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002914 fprintf(output, "[sequence] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002915 break;
2916 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002917 fprintf(output, "[choice] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002918 break;
2919 case XML_SCHEMA_TYPE_ALL:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002920 fprintf(output, "[all] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002921 break;
2922 case XML_SCHEMA_TYPE_UR:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002923 fprintf(output, "[ur] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002924 break;
2925 case XML_SCHEMA_TYPE_RESTRICTION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002926 fprintf(output, "[restriction] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002927 break;
2928 case XML_SCHEMA_TYPE_EXTENSION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002929 fprintf(output, "[extension] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002930 break;
2931 default:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002932 fprintf(output, "[unknown type %d] ", type->type);
Daniel Veillard4255d502002-04-16 15:50:10 +00002933 break;
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002934 }
2935 fprintf(output, "content: ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002936 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002937 case XML_SCHEMA_CONTENT_UNKNOWN:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002938 fprintf(output, "[unknown] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002939 break;
2940 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002941 fprintf(output, "[empty] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002942 break;
2943 case XML_SCHEMA_CONTENT_ELEMENTS:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002944 fprintf(output, "[element] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002945 break;
2946 case XML_SCHEMA_CONTENT_MIXED:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002947 fprintf(output, "[mixed] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002948 break;
2949 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00002950 /* not used. */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002951 break;
2952 case XML_SCHEMA_CONTENT_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002953 fprintf(output, "[basic] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002954 break;
2955 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002956 fprintf(output, "[simple] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002957 break;
2958 case XML_SCHEMA_CONTENT_ANY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002959 fprintf(output, "[any] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002960 break;
Daniel Veillard4255d502002-04-16 15:50:10 +00002961 }
2962 fprintf(output, "\n");
2963 if ((type->minOccurs != 1) || (type->maxOccurs != 1)) {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002964 fprintf(output, " min: %d ", type->minOccurs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002965 if (type->maxOccurs >= UNBOUNDED)
2966 fprintf(output, "max: unbounded\n");
2967 else if (type->maxOccurs != 1)
2968 fprintf(output, "max: %d\n", type->maxOccurs);
2969 else
2970 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002971 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002972 if (type->base != NULL) {
2973 fprintf(output, " base type: %s", type->base);
2974 if (type->baseNs != NULL)
2975 fprintf(output, " ns %s\n", type->baseNs);
2976 else
2977 fprintf(output, "\n");
2978 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002979 if (type->annot != NULL)
2980 xmlSchemaAnnotDump(output, type->annot);
2981 if (type->subtypes != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002982 xmlSchemaTypePtr sub = type->subtypes;
Daniel Veillard4255d502002-04-16 15:50:10 +00002983
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002984 fprintf(output, " subtypes: ");
2985 while (sub != NULL) {
2986 fprintf(output, "%s ", sub->name);
2987 sub = sub->next;
2988 }
2989 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002990 }
2991
2992}
2993
2994/**
2995 * xmlSchemaDump:
2996 * @output: the file output
2997 * @schema: a schema structure
2998 *
2999 * Dump a Schema structure.
3000 */
3001void
3002xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
3003{
Daniel Veillardce682bc2004-11-05 17:22:25 +00003004 if (output == NULL)
3005 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003006 if (schema == NULL) {
3007 fprintf(output, "Schemas: NULL\n");
3008 return;
3009 }
3010 fprintf(output, "Schemas: ");
3011 if (schema->name != NULL)
3012 fprintf(output, "%s, ", schema->name);
3013 else
3014 fprintf(output, "no name, ");
3015 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00003016 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003017 else
3018 fprintf(output, "no target namespace");
3019 fprintf(output, "\n");
3020 if (schema->annot != NULL)
3021 xmlSchemaAnnotDump(output, schema->annot);
3022
3023 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
3024 output);
3025 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003026 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00003027}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003028
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003029#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00003030#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003031/**
3032 * xmlSchemaDebugDumpIDCTable:
3033 * @vctxt: the WXS validation context
3034 *
3035 * Displays the current IDC table for debug purposes.
3036 */
3037static void
3038xmlSchemaDebugDumpIDCTable(FILE * output,
3039 const xmlChar *namespaceName,
3040 const xmlChar *localName,
3041 xmlSchemaPSVIIDCBindingPtr bind)
3042{
3043 xmlChar *str = NULL, *value;
3044 xmlSchemaPSVIIDCNodePtr tab;
3045 xmlSchemaPSVIIDCKeyPtr key;
3046 int i, j, res;
3047
3048 fprintf(output, "IDC: TABLES on %s\n",
3049 xmlSchemaFormatNsUriLocal(&str, namespaceName, localName));
3050 FREE_AND_NULL(str)
3051
3052 if (bind == NULL)
3053 return;
3054 do {
3055 fprintf(output, "IDC: BINDING %s\n",
3056 xmlSchemaFormatNsUriLocal(&str, bind->definition->targetNamespace,
3057 bind->definition->name));
3058 FREE_AND_NULL(str)
3059 for (i = 0; i < bind->nbNodes; i++) {
3060 tab = bind->nodeTable[i];
3061 fprintf(output, " ( ");
3062 for (j = 0; j < bind->definition->nbFields; j++) {
3063 key = tab->keys[j];
3064 if ((key != NULL) && (key->compValue != NULL)) {
3065#ifdef IDC_VALUE_SUPPORT
3066 res = xmlSchemaGetCanonValue(key->compValue, &value);
3067#else
3068 value = xmlStrdup(BAD_CAST "dummy-value");
3069 res = 0;
3070#endif
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003071 if (res >= 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003072 fprintf(output, "\"%s\" ", value);
3073 else
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003074 fprintf(output, "CANON-VALUE-FAILED ");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003075 if (res == 0)
3076 FREE_AND_NULL(value)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003077 } else if (key != NULL)
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003078 fprintf(output, "(no val), ");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003079 else
3080 fprintf(output, "(key missing), ");
3081 }
3082 fprintf(output, ")\n");
3083 }
3084 bind = bind->next;
3085 } while (bind != NULL);
3086}
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00003087#endif /* DEBUG_IDC */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003088#endif /* IDC_ENABLED */
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00003089#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +00003090
3091/************************************************************************
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003092 * *
3093 * Utilities *
3094 * *
3095 ************************************************************************/
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003096
Daniel Veillardc0826a72004-08-10 14:17:33 +00003097/**
3098 * xmlSchemaGetPropNode:
3099 * @node: the element node
3100 * @name: the name of the attribute
3101 *
3102 * Seeks an attribute with a name of @name in
3103 * no namespace.
3104 *
3105 * Returns the attribute or NULL if not present.
3106 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003107static xmlAttrPtr
Daniel Veillardc0826a72004-08-10 14:17:33 +00003108xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
Daniel Veillard01fa6152004-06-29 17:04:39 +00003109{
3110 xmlAttrPtr prop;
3111
Daniel Veillardc0826a72004-08-10 14:17:33 +00003112 if ((node == NULL) || (name == NULL))
3113 return(NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003114 prop = node->properties;
3115 while (prop != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00003116 if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
3117 return(prop);
3118 prop = prop->next;
3119 }
3120 return (NULL);
3121}
3122
3123/**
3124 * xmlSchemaGetPropNodeNs:
3125 * @node: the element node
3126 * @uri: the uri
3127 * @name: the name of the attribute
3128 *
3129 * Seeks an attribute with a local name of @name and
3130 * a namespace URI of @uri.
3131 *
3132 * Returns the attribute or NULL if not present.
3133 */
3134static xmlAttrPtr
3135xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
3136{
3137 xmlAttrPtr prop;
3138
3139 if ((node == NULL) || (name == NULL))
3140 return(NULL);
3141 prop = node->properties;
3142 while (prop != NULL) {
3143 if ((prop->ns != NULL) &&
3144 xmlStrEqual(prop->name, BAD_CAST name) &&
3145 xmlStrEqual(prop->ns->href, BAD_CAST uri))
Daniel Veillard01fa6152004-06-29 17:04:39 +00003146 return(prop);
3147 prop = prop->next;
3148 }
3149 return (NULL);
3150}
3151
3152static const xmlChar *
3153xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3154{
3155 xmlChar *val;
3156 const xmlChar *ret;
3157
3158 val = xmlNodeGetContent(node);
3159 if (val == NULL)
3160 return(NULL);
3161 ret = xmlDictLookup(ctxt->dict, val, -1);
3162 xmlFree(val);
3163 return(ret);
3164}
3165
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003166/**
3167 * xmlSchemaGetProp:
3168 * @ctxt: the parser context
3169 * @node: the node
3170 * @name: the property name
3171 *
3172 * Read a attribute value and internalize the string
3173 *
3174 * Returns the string or NULL if not present.
3175 */
3176static const xmlChar *
3177xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
3178 const char *name)
3179{
3180 xmlChar *val;
3181 const xmlChar *ret;
3182
3183 val = xmlGetProp(node, BAD_CAST name);
3184 if (val == NULL)
3185 return(NULL);
3186 ret = xmlDictLookup(ctxt->dict, val, -1);
3187 xmlFree(val);
3188 return(ret);
3189}
3190
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003191/************************************************************************
Daniel Veillard4255d502002-04-16 15:50:10 +00003192 * *
3193 * Parsing functions *
3194 * *
3195 ************************************************************************/
3196
3197/**
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003198 * xmlSchemaGetElem:
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003199 * @schema: the schema context
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003200 * @name: the element name
3201 * @ns: the element namespace
3202 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003203 * Lookup a global element declaration in the schema.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003204 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003205 * Returns the element declaration or NULL if not found.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003206 */
3207static xmlSchemaElementPtr
3208xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003209 const xmlChar * namespace)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003210{
3211 xmlSchemaElementPtr ret;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003212
3213 if ((name == NULL) || (schema == NULL))
3214 return (NULL);
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003215
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003216 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003217 if ((ret != NULL) &&
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003218 (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003219 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00003220 } else
3221 ret = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00003222 /*
3223 * This one was removed, since top level element declarations have
3224 * the target namespace specified in targetNamespace of the <schema>
3225 * information element, even if elementFormDefault is "unqualified".
3226 */
3227
3228 /* else if ((schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003229 if (xmlStrEqual(namespace, schema->targetNamespace))
3230 ret = xmlHashLookup2(schema->elemDecl, name, NULL);
3231 else
3232 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003233 if ((ret != NULL) &&
3234 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003235 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003236 }
William M. Bracke7091952004-05-11 15:09:58 +00003237 */
Daniel Veillard3646d642004-06-02 19:19:14 +00003238
William M. Brack2f2a6632004-08-20 23:09:47 +00003239 /*
3240 * Removed since imported components will be hold by the main schema only.
3241 *
Daniel Veillard3646d642004-06-02 19:19:14 +00003242 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003243 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003244 else
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003245 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003246 if (import != NULL) {
Daniel Veillardf2a12832003-11-24 13:04:35 +00003247 ret = xmlSchemaGetElem(import->schema, name, namespace, level + 1);
Daniel Veillard3646d642004-06-02 19:19:14 +00003248 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
3249 return (ret);
3250 } else
3251 ret = NULL;
3252 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003253 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003254#ifdef DEBUG
3255 if (ret == NULL) {
3256 if (namespace == NULL)
3257 fprintf(stderr, "Unable to lookup type %s", name);
3258 else
3259 fprintf(stderr, "Unable to lookup type %s:%s", name,
3260 namespace);
3261 }
3262#endif
3263 return (ret);
3264}
3265
3266/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003267 * xmlSchemaGetType:
3268 * @schema: the schemas context
3269 * @name: the type name
3270 * @ns: the type namespace
3271 *
3272 * Lookup a type in the schemas or the predefined types
3273 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003274 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +00003275 */
3276static xmlSchemaTypePtr
3277xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003278 const xmlChar * namespace)
3279{
Daniel Veillard4255d502002-04-16 15:50:10 +00003280 xmlSchemaTypePtr ret;
3281
3282 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003283 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003284 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003285 ret = xmlHashLookup2(schema->typeDecl, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003286 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003287 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003288 }
3289 ret = xmlSchemaGetPredefinedType(name, namespace);
Daniel Veillard1d913862003-11-21 00:28:39 +00003290 if (ret != NULL)
3291 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00003292 /*
3293 * Removed, since the imported components will be grafted on the
3294 * main schema only.
Daniel Veillard3646d642004-06-02 19:19:14 +00003295 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003296 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003297 else
Daniel Veillard1d913862003-11-21 00:28:39 +00003298 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003299 if (import != NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00003300 ret = xmlSchemaGetType(import->schema, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003301 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
3302 return (ret);
3303 } else
3304 ret = NULL;
3305 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003306 */
Daniel Veillard4255d502002-04-16 15:50:10 +00003307#ifdef DEBUG
3308 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003309 if (namespace == NULL)
3310 fprintf(stderr, "Unable to lookup type %s", name);
3311 else
3312 fprintf(stderr, "Unable to lookup type %s:%s", name,
3313 namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003314 }
3315#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003316 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003317}
3318
Daniel Veillard3646d642004-06-02 19:19:14 +00003319/**
3320 * xmlSchemaGetAttribute:
3321 * @schema: the context of the schema
3322 * @name: the name of the attribute
3323 * @ns: the target namespace of the attribute
3324 *
3325 * Lookup a an attribute in the schema or imported schemas
3326 *
3327 * Returns the attribute declaration or NULL if not found.
3328 */
3329static xmlSchemaAttributePtr
3330xmlSchemaGetAttribute(xmlSchemaPtr schema, const xmlChar * name,
3331 const xmlChar * namespace)
3332{
3333 xmlSchemaAttributePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00003334
3335 if ((name == NULL) || (schema == NULL))
3336 return (NULL);
3337
3338
3339 ret = xmlHashLookup2(schema->attrDecl, name, namespace);
3340 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL))
3341 return (ret);
3342 else
3343 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00003344 /*
3345 * Removed, since imported components will be hold by the main schema only.
3346 *
Daniel Veillard3646d642004-06-02 19:19:14 +00003347 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003348 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003349 else
3350 import = xmlHashLookup(schema->schemasImports, namespace);
3351 if (import != NULL) {
3352 ret = xmlSchemaGetAttribute(import->schema, name, namespace);
3353 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL)) {
3354 return (ret);
3355 } else
3356 ret = NULL;
3357 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003358 */
Daniel Veillard3646d642004-06-02 19:19:14 +00003359#ifdef DEBUG
3360 if (ret == NULL) {
3361 if (namespace == NULL)
3362 fprintf(stderr, "Unable to lookup attribute %s", name);
3363 else
3364 fprintf(stderr, "Unable to lookup attribute %s:%s", name,
3365 namespace);
3366 }
3367#endif
3368 return (ret);
3369}
3370
3371/**
3372 * xmlSchemaGetAttributeGroup:
3373 * @schema: the context of the schema
3374 * @name: the name of the attribute group
3375 * @ns: the target namespace of the attribute group
3376 *
3377 * Lookup a an attribute group in the schema or imported schemas
3378 *
3379 * Returns the attribute group definition or NULL if not found.
3380 */
3381static xmlSchemaAttributeGroupPtr
3382xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
3383 const xmlChar * namespace)
3384{
3385 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00003386
3387 if ((name == NULL) || (schema == NULL))
3388 return (NULL);
3389
3390
3391 ret = xmlHashLookup2(schema->attrgrpDecl, name, namespace);
3392 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
3393 return (ret);
3394 else
3395 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00003396 /*
3397 * Removed since imported components will be hold by the main schema only.
3398 *
Daniel Veillard3646d642004-06-02 19:19:14 +00003399 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003400 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003401 else
3402 import = xmlHashLookup(schema->schemasImports, namespace);
3403 if (import != NULL) {
3404 ret = xmlSchemaGetAttributeGroup(import->schema, name, namespace);
3405 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
3406 return (ret);
3407 else
3408 ret = NULL;
3409 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003410 */
Daniel Veillard3646d642004-06-02 19:19:14 +00003411#ifdef DEBUG
3412 if (ret == NULL) {
3413 if (namespace == NULL)
3414 fprintf(stderr, "Unable to lookup attribute group %s", name);
3415 else
3416 fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
3417 namespace);
3418 }
3419#endif
3420 return (ret);
3421}
3422
3423/**
3424 * xmlSchemaGetGroup:
3425 * @schema: the context of the schema
3426 * @name: the name of the group
3427 * @ns: the target namespace of the group
3428 *
3429 * Lookup a group in the schema or imported schemas
3430 *
3431 * Returns the group definition or NULL if not found.
3432 */
3433static xmlSchemaTypePtr
3434xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
3435 const xmlChar * namespace)
3436{
3437 xmlSchemaTypePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00003438
3439 if ((name == NULL) || (schema == NULL))
3440 return (NULL);
3441
3442
3443 ret = xmlHashLookup2(schema->groupDecl, name, namespace);
3444 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
3445 return (ret);
3446 else
3447 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00003448 /*
3449 * Removed since imported components will be hold by the main schema only.
3450 *
Daniel Veillard3646d642004-06-02 19:19:14 +00003451 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003452 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003453 else
3454 import = xmlHashLookup(schema->schemasImports, namespace);
3455 if (import != NULL) {
3456 ret = xmlSchemaGetGroup(import->schema, name, namespace);
3457 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
3458 return (ret);
3459 else
3460 ret = NULL;
3461 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003462 */
Daniel Veillard3646d642004-06-02 19:19:14 +00003463#ifdef DEBUG
3464 if (ret == NULL) {
3465 if (namespace == NULL)
3466 fprintf(stderr, "Unable to lookup group %s", name);
3467 else
3468 fprintf(stderr, "Unable to lookup group %s:%s", name,
3469 namespace);
3470 }
3471#endif
3472 return (ret);
3473}
3474
Daniel Veillard4255d502002-04-16 15:50:10 +00003475/************************************************************************
3476 * *
3477 * Parsing functions *
3478 * *
3479 ************************************************************************/
3480
3481#define IS_BLANK_NODE(n) \
3482 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content)))
3483
3484/**
3485 * xmlSchemaIsBlank:
3486 * @str: a string
3487 *
3488 * Check if a string is ignorable
3489 *
3490 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
3491 */
3492static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003493xmlSchemaIsBlank(xmlChar * str)
3494{
Daniel Veillard4255d502002-04-16 15:50:10 +00003495 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003496 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003497 while (*str != 0) {
William M. Brack76e95df2003-10-18 16:20:14 +00003498 if (!(IS_BLANK_CH(*str)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003499 return (0);
3500 str++;
Daniel Veillard4255d502002-04-16 15:50:10 +00003501 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003502 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003503}
3504
3505/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003506 * xmlSchemaAddAssembledItem:
3507 * @ctxt: a schema parser context
3508 * @schema: the schema being built
3509 * @item: the item
3510 *
3511 * Add a item to the schema's list of current items.
3512 * This is used if the schema was already constructed and
3513 * new schemata need to be added to it.
3514 * *WARNING* this interface is highly subject to change.
3515 *
3516 * Returns 0 if suceeds and -1 if an internal error occurs.
3517 */
3518static int
3519xmlSchemaAddAssembledItem(xmlSchemaParserCtxtPtr ctxt,
3520 xmlSchemaTypePtr item)
3521{
3522 static int growSize = 100;
3523 xmlSchemaAssemblePtr ass;
3524
3525 ass = ctxt->assemble;
3526 if (ass->sizeItems < 0) {
3527 /* If disabled. */
3528 return (0);
3529 }
3530 if (ass->sizeItems <= 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003531 ass->items = (void **) xmlMalloc(growSize * sizeof(xmlSchemaTypePtr));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003532 if (ass->items == NULL) {
3533 xmlSchemaPErrMemory(ctxt,
3534 "allocating new item buffer", NULL);
3535 return (-1);
3536 }
3537 ass->sizeItems = growSize;
3538 } else if (ass->sizeItems <= ass->nbItems) {
3539 ass->sizeItems *= 2;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003540 ass->items = (void **) xmlRealloc(ass->items,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003541 ass->sizeItems * sizeof(xmlSchemaTypePtr));
3542 if (ass->items == NULL) {
3543 xmlSchemaPErrMemory(ctxt,
3544 "growing item buffer", NULL);
3545 ass->sizeItems = 0;
3546 return (-1);
3547 }
3548 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003549 /* ass->items[ass->nbItems++] = (void *) item; */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003550 ((xmlSchemaTypePtr *) ass->items)[ass->nbItems++] = (void *) item;
3551 return (0);
3552}
3553
3554/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003555 * xmlSchemaAddNotation:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003556 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003557 * @schema: the schema being built
3558 * @name: the item name
3559 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00003560 * Add an XML schema annotation declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00003561 * *WARNING* this interface is highly subject to change
3562 *
3563 * Returns the new struture or NULL in case of error
3564 */
3565static xmlSchemaNotationPtr
3566xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00003567 const xmlChar *name)
Daniel Veillard4255d502002-04-16 15:50:10 +00003568{
3569 xmlSchemaNotationPtr ret = NULL;
3570 int val;
3571
3572 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3573 return (NULL);
3574
3575 if (schema->notaDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003576 schema->notaDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003577 if (schema->notaDecl == NULL)
3578 return (NULL);
3579
3580 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
3581 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003582 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003583 return (NULL);
3584 }
3585 memset(ret, 0, sizeof(xmlSchemaNotation));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003586 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003587 val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
3588 ret);
3589 if (val != 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00003590 /*
3591 * TODO: This should never happen, since a unique name will be computed.
3592 * If it fails, then an other internal error must have occured.
3593 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003594 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
3595 XML_SCHEMAP_REDEFINED_NOTATION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003596 "Annotation declaration '%s' is already declared.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003597 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003598 xmlFree(ret);
3599 return (NULL);
3600 }
3601 return (ret);
3602}
3603
3604
3605/**
3606 * xmlSchemaAddAttribute:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003607 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003608 * @schema: the schema being built
3609 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003610 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00003611 *
3612 * Add an XML schema Attrribute declaration
3613 * *WARNING* this interface is highly subject to change
3614 *
3615 * Returns the new struture or NULL in case of error
3616 */
3617static xmlSchemaAttributePtr
3618xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003619 const xmlChar * name, const xmlChar * namespace,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003620 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00003621{
3622 xmlSchemaAttributePtr ret = NULL;
3623 int val;
3624
3625 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3626 return (NULL);
3627
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003628#ifdef DEBUG
3629 fprintf(stderr, "Adding attribute %s\n", name);
3630 if (namespace != NULL)
3631 fprintf(stderr, " target namespace %s\n", namespace);
3632#endif
3633
Daniel Veillard4255d502002-04-16 15:50:10 +00003634 if (schema->attrDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003635 schema->attrDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003636 if (schema->attrDecl == NULL)
3637 return (NULL);
3638
3639 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
3640 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003641 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003642 return (NULL);
3643 }
3644 memset(ret, 0, sizeof(xmlSchemaAttribute));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003645 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00003646 ret->targetNamespace = namespace;
Daniel Veillard4255d502002-04-16 15:50:10 +00003647 val = xmlHashAddEntry3(schema->attrDecl, name,
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00003648 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003649 if (val != 0) {
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003650 if (topLevel) {
3651 xmlSchemaPCustomErr(ctxt,
3652 XML_SCHEMAP_REDEFINED_ATTR,
3653 NULL, NULL, node,
3654 "A global attribute declaration with the name '%s' does "
3655 "already exist", name);
3656 xmlFree(ret);
3657 return (NULL);
3658 } else {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003659 char buf[30];
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003660 /*
3661 * Using the ctxt->container for xmlHashAddEntry3 is ambigious
3662 * in the scenario:
3663 * 1. multiple top-level complex types have different target
3664 * namespaces but have the SAME NAME; this can happen if
3665 * schemata are imported
3666 * 2. those complex types contain attributes with an equal name
3667 * 3. those attributes are in no namespace
3668 * We will compute a new context string.
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003669 */
3670 snprintf(buf, 29, "#aCont%d", ctxt->counter++ + 1);
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003671 val = xmlHashAddEntry3(schema->attrDecl, name,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00003672 namespace, xmlDictLookup(ctxt->dict, BAD_CAST buf, -1), ret);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003673
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003674 if (val != 0) {
3675 xmlSchemaPCustomErr(ctxt,
3676 XML_SCHEMAP_INTERNAL,
3677 NULL, NULL, node,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003678 "Internal error: xmlSchemaAddAttribute, "
3679 "a dublicate attribute declaration with the name '%s' "
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003680 "could not be added to the hash.", name);
3681 xmlFree(ret);
3682 return (NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003683 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003684 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003685 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003686 if (ctxt->assemble != NULL)
3687 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003688 return (ret);
3689}
3690
3691/**
3692 * xmlSchemaAddAttributeGroup:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003693 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003694 * @schema: the schema being built
3695 * @name: the item name
3696 *
3697 * Add an XML schema Attrribute Group declaration
3698 *
3699 * Returns the new struture or NULL in case of error
3700 */
3701static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003702xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00003703 xmlSchemaPtr schema, const xmlChar * name,
3704 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003705{
3706 xmlSchemaAttributeGroupPtr ret = NULL;
3707 int val;
3708
3709 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3710 return (NULL);
3711
3712 if (schema->attrgrpDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003713 schema->attrgrpDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003714 if (schema->attrgrpDecl == NULL)
3715 return (NULL);
3716
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003717 ret =
3718 (xmlSchemaAttributeGroupPtr)
3719 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00003720 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003721 xmlSchemaPErrMemory(ctxt, "allocating attribute group", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003722 return (NULL);
3723 }
3724 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003725 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003726 val = xmlHashAddEntry3(schema->attrgrpDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003727 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003728 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003729 xmlSchemaPCustomErr(ctxt,
3730 XML_SCHEMAP_REDEFINED_ATTRGROUP,
3731 NULL, NULL, node,
3732 "A global attribute group definition with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003733 xmlFree(ret);
3734 return (NULL);
3735 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003736 if (ctxt->assemble != NULL)
3737 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003738 return (ret);
3739}
3740
3741/**
3742 * xmlSchemaAddElement:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003743 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003744 * @schema: the schema being built
3745 * @name: the type name
3746 * @namespace: the type namespace
3747 *
3748 * Add an XML schema Element declaration
3749 * *WARNING* this interface is highly subject to change
3750 *
3751 * Returns the new struture or NULL in case of error
3752 */
3753static xmlSchemaElementPtr
3754xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003755 const xmlChar * name, const xmlChar * namespace,
3756 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00003757{
3758 xmlSchemaElementPtr ret = NULL;
3759 int val;
3760
3761 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3762 return (NULL);
3763
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003764#ifdef DEBUG
3765 fprintf(stderr, "Adding element %s\n", name);
3766 if (namespace != NULL)
3767 fprintf(stderr, " target namespace %s\n", namespace);
3768#endif
3769
Daniel Veillard4255d502002-04-16 15:50:10 +00003770 if (schema->elemDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003771 schema->elemDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003772 if (schema->elemDecl == NULL)
3773 return (NULL);
3774
3775 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
3776 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003777 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003778 return (NULL);
3779 }
3780 memset(ret, 0, sizeof(xmlSchemaElement));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003781 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003782 val = xmlHashAddEntry3(schema->elemDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003783 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003784 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003785 if (topLevel) {
3786 xmlSchemaPCustomErr(ctxt,
3787 XML_SCHEMAP_REDEFINED_ELEMENT,
3788 NULL, NULL, node,
3789 "A global element declaration with the name '%s' does "
3790 "already exist", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003791 xmlFree(ret);
3792 return (NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00003793 } else {
3794 char buf[30];
3795
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003796 snprintf(buf, 29, "#eCont%d", ctxt->counter++ + 1);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003797 val = xmlHashAddEntry3(schema->elemDecl, name,
3798 namespace, (xmlChar *) buf, ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00003799 if (val != 0) {
3800 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003801 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00003802 NULL, NULL, node,
3803 "Internal error: xmlSchemaAddElement, "
3804 "a dublicate element declaration with the name '%s' "
3805 "could not be added to the hash.", name);
3806 xmlFree(ret);
3807 return (NULL);
3808 }
3809 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00003810
Daniel Veillard4255d502002-04-16 15:50:10 +00003811 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003812 if (ctxt->assemble != NULL)
3813 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003814 return (ret);
3815}
3816
3817/**
3818 * xmlSchemaAddType:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003819 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003820 * @schema: the schema being built
3821 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003822 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00003823 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00003824 * Add an XML schema item
Daniel Veillard4255d502002-04-16 15:50:10 +00003825 * *WARNING* this interface is highly subject to change
3826 *
3827 * Returns the new struture or NULL in case of error
3828 */
3829static xmlSchemaTypePtr
3830xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003831 const xmlChar * name, const xmlChar * namespace,
3832 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003833{
3834 xmlSchemaTypePtr ret = NULL;
3835 int val;
3836
3837 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3838 return (NULL);
3839
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003840#ifdef DEBUG
3841 fprintf(stderr, "Adding type %s\n", name);
3842 if (namespace != NULL)
3843 fprintf(stderr, " target namespace %s\n", namespace);
3844#endif
3845
Daniel Veillard4255d502002-04-16 15:50:10 +00003846 if (schema->typeDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003847 schema->typeDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003848 if (schema->typeDecl == NULL)
3849 return (NULL);
3850
3851 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
3852 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003853 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003854 return (NULL);
3855 }
3856 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003857 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003858 ret->redef = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003859 val = xmlHashAddEntry2(schema->typeDecl, name, namespace, ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00003860 if (val != 0) {
3861 if (ctxt->includes == 0) {
3862 xmlSchemaPCustomErr(ctxt,
3863 XML_SCHEMAP_REDEFINED_TYPE,
3864 NULL, NULL, node,
3865 "A global type definition with the name '%s' does already exist", name);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003866 xmlFree(ret);
3867 return (NULL);
3868 } else {
3869 xmlSchemaTypePtr prev;
3870
3871 prev = xmlHashLookup2(schema->typeDecl, name, namespace);
3872 if (prev == NULL) {
3873 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003874 XML_ERR_INTERNAL_ERROR,
3875 "Internal error: xmlSchemaAddType, on type "
3876 "'%s'.\n",
3877 name, NULL);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003878 xmlFree(ret);
3879 return (NULL);
3880 }
3881 ret->redef = prev->redef;
3882 prev->redef = ret;
3883 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003884 }
3885 ret->minOccurs = 1;
3886 ret->maxOccurs = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +00003887 ret->attributeUses = NULL;
3888 ret->attributeWildcard = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003889 if (ctxt->assemble != NULL)
3890 xmlSchemaAddAssembledItem(ctxt,ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003891 return (ret);
3892}
3893
3894/**
3895 * xmlSchemaAddGroup:
3896 * @ctxt: a schema validation context
3897 * @schema: the schema being built
3898 * @name: the group name
3899 *
3900 * Add an XML schema Group definition
3901 *
3902 * Returns the new struture or NULL in case of error
3903 */
3904static xmlSchemaTypePtr
3905xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00003906 const xmlChar *name, const xmlChar *namespaceName,
3907 xmlNodePtr node)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003908{
3909 xmlSchemaTypePtr ret = NULL;
3910 int val;
3911
3912 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3913 return (NULL);
3914
3915 if (schema->groupDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003916 schema->groupDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003917 if (schema->groupDecl == NULL)
3918 return (NULL);
3919
3920 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
3921 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003922 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003923 return (NULL);
3924 }
3925 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003926 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003927 val =
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00003928 xmlHashAddEntry2(schema->groupDecl, name, namespaceName,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003929 ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003930 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003931 xmlSchemaPCustomErr(ctxt,
3932 XML_SCHEMAP_REDEFINED_GROUP,
3933 NULL, NULL, node,
3934 "A global model group definition with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003935 xmlFree(ret);
3936 return (NULL);
3937 }
3938 ret->minOccurs = 1;
3939 ret->maxOccurs = 1;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003940 if (ctxt->assemble != NULL)
3941 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003942 return (ret);
3943}
3944
Daniel Veillard3646d642004-06-02 19:19:14 +00003945/**
3946 * xmlSchemaNewWildcardNs:
3947 * @ctxt: a schema validation context
3948 *
3949 * Creates a new wildcard namespace constraint.
3950 *
3951 * Returns the new struture or NULL in case of error
3952 */
3953static xmlSchemaWildcardNsPtr
3954xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
3955{
3956 xmlSchemaWildcardNsPtr ret;
3957
3958 ret = (xmlSchemaWildcardNsPtr)
3959 xmlMalloc(sizeof(xmlSchemaWildcardNs));
3960 if (ret == NULL) {
3961 xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
3962 return (NULL);
3963 }
3964 ret->value = NULL;
3965 ret->next = NULL;
3966 return (ret);
3967}
3968
3969/**
3970 * xmlSchemaAddWildcard:
3971 * @ctxt: a schema validation context
Daniel Veillardc0826a72004-08-10 14:17:33 +00003972 * Adds a wildcard. It corresponds to a
3973 * xsd:anyAttribute and is used as storage for namespace
3974 * constraints on a xsd:any.
Daniel Veillard3646d642004-06-02 19:19:14 +00003975 *
3976 * Returns the new struture or NULL in case of error
3977 */
3978static xmlSchemaWildcardPtr
3979xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt)
3980{
3981 xmlSchemaWildcardPtr ret = NULL;
3982
3983 if (ctxt == NULL)
3984 return (NULL);
3985
3986 ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
3987 if (ret == NULL) {
3988 xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
3989 return (NULL);
3990 }
3991 memset(ret, 0, sizeof(xmlSchemaWildcard));
3992 ret->minOccurs = 1;
3993 ret->maxOccurs = 1;
3994
3995 return (ret);
3996}
3997
Daniel Veillard4255d502002-04-16 15:50:10 +00003998/************************************************************************
3999 * *
4000 * Utilities for parsing *
4001 * *
4002 ************************************************************************/
4003
4004/**
4005 * xmlGetQNameProp:
4006 * @ctxt: a schema validation context
4007 * @node: a subtree containing XML Schema informations
4008 * @name: the attribute name
4009 * @namespace: the result namespace if any
4010 *
4011 * Extract a QName Attribute value
4012 *
4013 * Returns the NCName or NULL if not found, and also update @namespace
4014 * with the namespace URI
4015 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004016static const xmlChar *
Daniel Veillard4255d502002-04-16 15:50:10 +00004017xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004018 const char *name, const xmlChar ** namespace)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004019{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004020 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00004021 xmlNsPtr ns;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004022 const xmlChar *ret, *prefix;
4023 int len;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004024 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00004025
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004026 *namespace = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004027 attr = xmlSchemaGetPropNode(node, name);
4028 if (attr == NULL)
4029 return (NULL);
4030 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004031
Daniel Veillard4255d502002-04-16 15:50:10 +00004032 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004033 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004034
Daniel Veillardba0153a2004-04-01 10:42:31 +00004035 if (!strchr((char *) val, ':')) {
Daniel Veillardebcdebd2004-03-05 00:15:50 +00004036 ns = xmlSearchNs(node->doc, node, 0);
4037 if (ns) {
4038 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
4039 return (val);
4040 }
4041 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004042 ret = xmlSplitQName3(val, &len);
4043 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004044 return (val);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004045 }
4046 ret = xmlDictLookup(ctxt->dict, ret, -1);
4047 prefix = xmlDictLookup(ctxt->dict, val, len);
Daniel Veillard4255d502002-04-16 15:50:10 +00004048
4049 ns = xmlSearchNs(node->doc, node, prefix);
4050 if (ns == NULL) {
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004051 xmlSchemaPSimpleTypeErr(ctxt, XML_SCHEMAP_PREFIX_UNDEFINED,
4052 NULL, NULL, (xmlNodePtr) attr,
4053 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, val,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004054 "The QName value '%s' has no corresponding namespace "
4055 "declaration in scope", val, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004056 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004057 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004058 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004059 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004060}
4061
4062/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00004063 * xmlSchemaPValAttrNodeQNameValue:
4064 * @ctxt: a schema parser context
4065 * @schema: the schema context
4066 * @ownerDes: the designation of the parent element
4067 * @ownerItem: the parent as a schema object
4068 * @value: the QName value
4069 * @local: the resulting local part if found, the attribute value otherwise
4070 * @uri: the resulting namespace URI if found
4071 *
4072 * Extracts the local name and the URI of a QName value and validates it.
4073 * This one is intended to be used on attribute values that
4074 * should resolve to schema components.
4075 *
4076 * Returns 0, in case the QName is valid, a positive error code
4077 * if not valid and -1 if an internal error occurs.
4078 */
4079static int
4080xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
4081 xmlSchemaPtr schema,
4082 xmlChar **ownerDes,
4083 xmlSchemaTypePtr ownerItem,
4084 xmlAttrPtr attr,
4085 const xmlChar *value,
4086 const xmlChar **uri,
4087 const xmlChar **prefix,
4088 const xmlChar **local)
4089{
4090 const xmlChar *pref;
4091 xmlNsPtr ns;
4092 int len, ret;
4093
4094 *uri = NULL;
4095 *local = NULL;
4096 if (prefix != 0)
4097 *prefix = NULL;
4098 ret = xmlValidateQName(value, 1);
4099 if (ret > 0) {
4100 xmlSchemaPSimpleTypeErr(ctxt,
4101 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4102 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004103 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
4104 "QName", value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004105 NULL, NULL, NULL);
4106 *local = value;
4107 return (ctxt->err);
4108 } else if (ret < 0)
4109 return (-1);
4110
4111 if (!strchr((char *) value, ':')) {
4112 ns = xmlSearchNs(attr->doc, attr->parent, 0);
4113 if (ns)
4114 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
4115 else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
4116 /*
4117 * This one takes care of included schemas with no
4118 * target namespace.
4119 */
4120 *uri = schema->targetNamespace;
4121 }
4122 *local = value;
4123 return (0);
4124 }
4125 /*
4126 * At this point xmlSplitQName3 has to return a local name.
4127 */
4128 *local = xmlSplitQName3(value, &len);
4129 *local = xmlDictLookup(ctxt->dict, *local, -1);
4130 pref = xmlDictLookup(ctxt->dict, value, len);
4131 if (prefix != 0)
4132 *prefix = pref;
4133 ns = xmlSearchNs(attr->doc, attr->parent, pref);
4134 if (ns == NULL) {
4135 xmlSchemaPSimpleTypeErr(ctxt,
4136 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4137 ownerDes, ownerItem, (xmlNodePtr) attr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004138 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), "QName", value,
4139 "The QName value '%s' has no corresponding namespace "
4140 "declaration in scope", value, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004141 return (ctxt->err);
4142 } else {
4143 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
4144 }
4145 return (0);
4146}
4147
4148/**
4149 * xmlSchemaPValAttrNodeQName:
4150 * @ctxt: a schema parser context
4151 * @schema: the schema context
4152 * @ownerDes: the designation of the owner element
4153 * @ownerItem: the owner as a schema object
4154 * @attr: the attribute node
4155 * @local: the resulting local part if found, the attribute value otherwise
4156 * @uri: the resulting namespace URI if found
4157 *
4158 * Extracts and validates the QName of an attribute value.
4159 * This one is intended to be used on attribute values that
4160 * should resolve to schema components.
4161 *
4162 * Returns 0, in case the QName is valid, a positive error code
4163 * if not valid and -1 if an internal error occurs.
4164 */
4165static int
4166xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
4167 xmlSchemaPtr schema,
4168 xmlChar **ownerDes,
4169 xmlSchemaTypePtr ownerItem,
4170 xmlAttrPtr attr,
4171 const xmlChar **uri,
4172 const xmlChar **prefix,
4173 const xmlChar **local)
4174{
4175 const xmlChar *value;
4176
4177 value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4178 return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
4179 ownerDes, ownerItem, attr, value, uri, prefix, local));
4180}
4181
4182/**
4183 * xmlSchemaPValAttrQName:
4184 * @ctxt: a schema parser context
4185 * @schema: the schema context
4186 * @ownerDes: the designation of the parent element
4187 * @ownerItem: the owner as a schema object
4188 * @ownerElem: the parent node of the attribute
4189 * @name: the name of the attribute
4190 * @local: the resulting local part if found, the attribute value otherwise
4191 * @uri: the resulting namespace URI if found
4192 *
4193 * Extracts and validates the QName of an attribute value.
4194 *
4195 * Returns 0, in case the QName is valid, a positive error code
4196 * if not valid and -1 if an internal error occurs.
4197 */
4198static int
4199xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
4200 xmlSchemaPtr schema,
4201 xmlChar **ownerDes,
4202 xmlSchemaTypePtr ownerItem,
4203 xmlNodePtr ownerElem,
4204 const char *name,
4205 const xmlChar **uri,
4206 const xmlChar **prefix,
4207 const xmlChar **local)
4208{
4209 xmlAttrPtr attr;
4210
4211 attr = xmlSchemaGetPropNode(ownerElem, name);
4212 if (attr == NULL) {
4213 *local = NULL;
4214 *uri = NULL;
4215 return (0);
4216 }
4217 return (xmlSchemaPValAttrNodeQName(ctxt, schema,
4218 ownerDes, ownerItem, attr, uri, prefix, local));
4219}
4220
4221/**
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00004222 * xmlSchemaPValAttrID:
4223 * @ctxt: a schema parser context
4224 * @schema: the schema context
4225 * @ownerDes: the designation of the parent element
4226 * @ownerItem: the owner as a schema object
4227 * @ownerElem: the parent node of the attribute
4228 * @name: the name of the attribute
4229 *
4230 * Extracts and validates the ID of an attribute value.
4231 *
4232 * Returns 0, in case the ID is valid, a positive error code
4233 * if not valid and -1 if an internal error occurs.
4234 */
4235static int
4236xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,
4237 xmlChar **ownerDes,
4238 xmlSchemaTypePtr ownerItem,
4239 xmlNodePtr ownerElem,
4240 const xmlChar *name)
4241{
4242 int ret;
4243 xmlChar *value;
4244 xmlAttrPtr attr;
4245
4246 value = xmlGetNoNsProp(ownerElem, name);
4247 if (value == NULL)
4248 return (0);
4249
4250 attr = xmlSchemaGetPropNode(ownerElem, (const char *) name);
4251 if (attr == NULL)
4252 return (-1);
4253
4254 ret = xmlValidateNCName(BAD_CAST value, 1);
4255 if (ret == 0) {
4256 /*
4257 * NOTE: the IDness might have already be declared in the DTD
4258 */
4259 if (attr->atype != XML_ATTRIBUTE_ID) {
4260 xmlIDPtr res;
4261 xmlChar *strip;
4262
4263 /*
4264 * TODO: Use xmlSchemaStrip here; it's not exported at this
4265 * moment.
4266 */
4267 strip = xmlSchemaCollapseString(BAD_CAST value);
4268 if (strip != NULL)
4269 value = strip;
4270 res = xmlAddID(NULL, ownerElem->doc, BAD_CAST value, attr);
4271 if (res == NULL) {
4272 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
4273 xmlSchemaPSimpleTypeErr(ctxt,
4274 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4275 ownerDes, ownerItem, (xmlNodePtr) attr,
4276 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00004277 NULL, NULL, "The ID '%s' is already defined",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00004278 BAD_CAST value, NULL);
4279 } else
4280 attr->atype = XML_ATTRIBUTE_ID;
4281 if (strip != NULL)
4282 xmlFree(strip);
4283 }
4284 } else if (ret > 0) {
4285 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
4286 xmlSchemaPSimpleTypeErr(ctxt,
4287 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4288 ownerDes, ownerItem, (xmlNodePtr) attr,
4289 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
4290 NULL, BAD_CAST value, NULL, NULL, NULL);
4291 }
4292 xmlFree(value);
4293
4294 return (ret);
4295}
4296
4297/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004298 * xmlGetMaxOccurs:
4299 * @ctxt: a schema validation context
4300 * @node: a subtree containing XML Schema informations
4301 *
4302 * Get the maxOccurs property
4303 *
4304 * Returns the default if not found, or the value
4305 */
4306static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004307xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
4308 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004309{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004310 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00004311 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004312 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00004313
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004314 attr = xmlSchemaGetPropNode(node, "maxOccurs");
4315 if (attr == NULL)
4316 return (def);
4317 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00004318
4319 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004320 if (max != UNBOUNDED) {
4321 xmlSchemaPSimpleTypeErr(ctxt,
4322 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4323 /* XML_SCHEMAP_INVALID_MINOCCURS, */
4324 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
4325 val, NULL, NULL, NULL);
4326 return (def);
4327 } else
4328 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00004329 }
4330
4331 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00004332 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004333 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004334 if (*cur == 0) {
4335 xmlSchemaPSimpleTypeErr(ctxt,
4336 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4337 /* XML_SCHEMAP_INVALID_MINOCCURS, */
4338 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
4339 val, NULL, NULL, NULL);
4340 return (def);
4341 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004342 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004343 ret = ret * 10 + (*cur - '0');
4344 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00004345 }
William M. Brack76e95df2003-10-18 16:20:14 +00004346 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004347 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004348 /*
4349 * TODO: Restrict the maximal value to Integer.
4350 */
4351 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
4352 xmlSchemaPSimpleTypeErr(ctxt,
4353 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4354 /* XML_SCHEMAP_INVALID_MINOCCURS, */
4355 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
4356 val, NULL, NULL, NULL);
4357 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00004358 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004359 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004360}
4361
4362/**
4363 * xmlGetMinOccurs:
4364 * @ctxt: a schema validation context
4365 * @node: a subtree containing XML Schema informations
4366 *
4367 * Get the minOccurs property
4368 *
4369 * Returns the default if not found, or the value
4370 */
4371static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004372xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
4373 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004374{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004375 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00004376 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004377 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00004378
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004379 attr = xmlSchemaGetPropNode(node, "minOccurs");
4380 if (attr == NULL)
4381 return (def);
4382 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00004383 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00004384 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004385 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004386 if (*cur == 0) {
4387 xmlSchemaPSimpleTypeErr(ctxt,
4388 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4389 /* XML_SCHEMAP_INVALID_MINOCCURS, */
4390 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
4391 val, NULL, NULL, NULL);
4392 return (def);
4393 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004394 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004395 ret = ret * 10 + (*cur - '0');
4396 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00004397 }
William M. Brack76e95df2003-10-18 16:20:14 +00004398 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004399 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004400 /*
4401 * TODO: Restrict the maximal value to Integer.
4402 */
4403 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
4404 xmlSchemaPSimpleTypeErr(ctxt,
4405 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4406 /* XML_SCHEMAP_INVALID_MINOCCURS, */
4407 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
4408 val, NULL, NULL, NULL);
4409 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00004410 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004411 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004412}
4413
4414/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004415 * xmlSchemaPGetBoolNodeValue:
4416 * @ctxt: a schema validation context
4417 * @ownerDes: owner designation
4418 * @ownerItem: the owner as a schema item
4419 * @node: the node holding the value
4420 *
4421 * Converts a boolean string value into 1 or 0.
4422 *
4423 * Returns 0 or 1.
4424 */
4425static int
4426xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
4427 xmlChar **ownerDes,
4428 xmlSchemaTypePtr ownerItem,
4429 xmlNodePtr node)
4430{
4431 xmlChar *value = NULL;
4432 int res = 0;
4433
4434 value = xmlNodeGetContent(node);
4435 /*
4436 * 3.2.2.1 Lexical representation
4437 * An instance of a datatype that is defined as ·boolean·
4438 * can have the following legal literals {true, false, 1, 0}.
4439 */
4440 if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
4441 res = 1;
4442 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
4443 res = 0;
4444 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
4445 res = 1;
4446 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
4447 res = 0;
4448 else {
4449 xmlSchemaPSimpleTypeErr(ctxt,
4450 XML_SCHEMAP_INVALID_BOOLEAN,
4451 ownerDes, ownerItem, node,
4452 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
4453 "(1 | 0 | true | false)", BAD_CAST value,
4454 NULL, NULL, NULL);
4455 }
4456 if (value != NULL)
4457 xmlFree(value);
4458 return (res);
4459}
4460
4461/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004462 * xmlGetBooleanProp:
4463 * @ctxt: a schema validation context
4464 * @node: a subtree containing XML Schema informations
4465 * @name: the attribute name
4466 * @def: the default value
4467 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00004468 * Evaluate if a boolean property is set
Daniel Veillard4255d502002-04-16 15:50:10 +00004469 *
4470 * Returns the default if not found, 0 if found to be false,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004471 * 1 if found to be true
Daniel Veillard4255d502002-04-16 15:50:10 +00004472 */
4473static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00004474xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
4475 xmlChar **ownerDes,
4476 xmlSchemaTypePtr ownerItem,
4477 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004478 const char *name, int def)
4479{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004480 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00004481
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004482 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004483 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004484 return (def);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004485 /*
4486 * 3.2.2.1 Lexical representation
4487 * An instance of a datatype that is defined as ·boolean·
4488 * can have the following legal literals {true, false, 1, 0}.
4489 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004490 if (xmlStrEqual(val, BAD_CAST "true"))
4491 def = 1;
4492 else if (xmlStrEqual(val, BAD_CAST "false"))
4493 def = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004494 else if (xmlStrEqual(val, BAD_CAST "1"))
4495 def = 1;
4496 else if (xmlStrEqual(val, BAD_CAST "0"))
4497 def = 0;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00004498 else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004499 xmlSchemaPSimpleTypeErr(ctxt,
4500 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00004501 ownerDes, ownerItem,
4502 (xmlNodePtr) xmlSchemaGetPropNode(node, name),
William M. Brack2f2a6632004-08-20 23:09:47 +00004503 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
4504 "(1 | 0 | true | false)", val, NULL, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004505 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004506 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00004507}
4508
4509/************************************************************************
4510 * *
4511 * Shema extraction from an Infoset *
4512 * *
4513 ************************************************************************/
4514static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
4515 ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00004516 xmlNodePtr node,
4517 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004518static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
4519 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00004520 xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00004521 xmlNodePtr node,
4522 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004523static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
4524 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00004525 xmlSchemaPtr schema,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00004526 xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00004527static xmlSchemaTypePtr xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt,
4528 xmlSchemaPtr schema,
4529 xmlNodePtr node);
4530static xmlSchemaTypePtr xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt,
4531 xmlSchemaPtr schema,
4532 xmlNodePtr node);
4533static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
4534 ctxt,
4535 xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00004536 xmlNodePtr node,
4537 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00004538static xmlSchemaAttributeGroupPtr
4539xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00004540 xmlSchemaPtr schema, xmlNodePtr node,
4541 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00004542static xmlSchemaTypePtr xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt,
4543 xmlSchemaPtr schema,
4544 xmlNodePtr node);
4545static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
4546 xmlSchemaPtr schema,
4547 xmlNodePtr node);
Daniel Veillard3646d642004-06-02 19:19:14 +00004548static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004549xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
4550 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00004551
4552/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004553 * xmlSchemaPValAttrNodeValue:
Daniel Veillard01fa6152004-06-29 17:04:39 +00004554 *
4555 * @ctxt: a schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00004556 * @ownerDes: the designation of the parent element
4557 * @ownerItem: the schema object owner if existent
4558 * @attr: the schema attribute node being validated
4559 * @value: the value
4560 * @type: the built-in type to be validated against
Daniel Veillard01fa6152004-06-29 17:04:39 +00004561 *
4562 * Validates a value against the given built-in type.
4563 * This one is intended to be used internally for validation
4564 * of schema attribute values during parsing of the schema.
4565 *
4566 * Returns 0 if the value is valid, a positive error code
4567 * number otherwise and -1 in case of an internal or API error.
4568 */
4569static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00004570xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr ctxt,
4571 xmlChar **ownerDes,
4572 xmlSchemaTypePtr ownerItem,
4573 xmlAttrPtr attr,
4574 const xmlChar *value,
4575 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +00004576{
Daniel Veillard01fa6152004-06-29 17:04:39 +00004577
Daniel Veillardc0826a72004-08-10 14:17:33 +00004578 int ret = 0;
4579
4580 /*
4581 * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
4582 * one is really meant to be used internally, so better not.
4583 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00004584 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00004585 return (-1);
4586 if (type->type != XML_SCHEMA_TYPE_BASIC) {
4587 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004588 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004589 "Internal error: xmlSchemaPValAttrNodeValue, the given "
Daniel Veillardc0826a72004-08-10 14:17:33 +00004590 "type '%s' is not a built-in type.\n",
4591 type->name, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00004592 return (-1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004593 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00004594 switch (type->builtInType) {
4595 case XML_SCHEMAS_NCNAME:
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004596 case XML_SCHEMAS_QNAME:
4597 case XML_SCHEMAS_ANYURI:
4598 case XML_SCHEMAS_TOKEN:
4599 case XML_SCHEMAS_LANGUAGE:
4600 ret = xmlSchemaValPredefTypeNode(type, value, NULL, (xmlNodePtr) attr);
4601 break;
4602
4603 /*
4604 case XML_SCHEMAS_NCNAME:
Daniel Veillard01fa6152004-06-29 17:04:39 +00004605 ret = xmlValidateNCName(value, 1);
4606 break;
4607 case XML_SCHEMAS_QNAME:
Daniel Veillardc0826a72004-08-10 14:17:33 +00004608 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004609 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004610 "Internal error: xmlSchemaPvalueAttrNode, use "
4611 "the function xmlSchemaExtractSchemaQNamePropvalueidated "
4612 "for extracting QName valueues instead.\n",
4613 NULL, NULL);
4614 return (-1);
4615 case XML_SCHEMAS_ANYURI:
4616 if (value != NULL) {
4617 xmlURIPtr uri = xmlParseURI((const char *) value);
4618 if (uri == NULL)
4619 ret = 1;
4620 else
4621 xmlFreeURI(uri);
Daniel Veillard01fa6152004-06-29 17:04:39 +00004622 }
4623 break;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004624 case XML_SCHEMAS_TOKEN: {
4625 const xmlChar *cur = value;
4626
4627 if (IS_BLANK_CH(*cur)) {
4628 ret = 1;
4629 } else while (*cur != 0) {
4630 if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) {
4631 ret = 1;
4632 break;
4633 } else if (*cur == ' ') {
4634 cur++;
4635 if ((*cur == 0) || (*cur == ' ')) {
4636 ret = 1;
4637 break;
4638 }
4639 } else {
4640 cur++;
4641 }
4642 }
4643 }
4644 break;
4645 case XML_SCHEMAS_LANGUAGE:
4646 if (xmlCheckLanguageID(value) != 1)
4647 ret = 1;
4648 break;
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004649 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00004650 default: {
4651 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004652 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004653 "Internal error: xmlSchemaPValAttrNodeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +00004654 "valueidation using the type '%s' is not implemented "
4655 "yet.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +00004656 type->name, NULL);
4657 return (-1);
4658 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004659 }
4660 /*
4661 * TODO: Should we use the S4S error codes instead?
4662 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004663 if (ret < 0) {
4664 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
4665 XML_SCHEMAP_INTERNAL,
4666 "Internal error: xmlSchemaPValAttrNodeValue, "
4667 "failed to validate a schema attribute value.\n",
4668 NULL, NULL);
4669 return (-1);
4670 } else if (ret > 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004671 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
4672 xmlSchemaPSimpleTypeErr(ctxt,
4673 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2,
4674 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004675 type, NULL, value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004676 NULL, NULL, NULL);
4677 return(XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2);
4678 } else {
4679 xmlSchemaPSimpleTypeErr(ctxt,
4680 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
4681 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004682 type, NULL, value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004683 NULL, NULL, NULL);
4684 return(XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
4685 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00004686 }
4687 return (ret);
4688}
4689
4690/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00004691 * xmlSchemaPValAttrNode:
4692 *
4693 * @ctxt: a schema parser context
4694 * @ownerDes: the designation of the parent element
4695 * @ownerItem: the schema object owner if existent
4696 * @attr: the schema attribute node being validated
4697 * @type: the built-in type to be validated against
4698 * @value: the resulting value if any
4699 *
4700 * Extracts and validates a value against the given built-in type.
4701 * This one is intended to be used internally for validation
4702 * of schema attribute values during parsing of the schema.
4703 *
4704 * Returns 0 if the value is valid, a positive error code
4705 * number otherwise and -1 in case of an internal or API error.
4706 */
4707static int
4708xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
4709 xmlChar **ownerDes,
4710 xmlSchemaTypePtr ownerItem,
4711 xmlAttrPtr attr,
4712 xmlSchemaTypePtr type,
4713 const xmlChar **value)
4714{
4715 const xmlChar *val;
4716
4717 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
4718 return (-1);
4719
4720 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4721 if (value != NULL)
4722 *value = val;
4723
4724 return (xmlSchemaPValAttrNodeValue(ctxt, ownerDes, ownerItem, attr,
4725 val, type));
4726}
4727
4728/**
4729 * xmlSchemaPValAttr:
4730 *
4731 * @ctxt: a schema parser context
4732 * @node: the element node of the attribute
4733 * @ownerDes: the designation of the parent element
4734 * @ownerItem: the schema object owner if existent
4735 * @ownerElem: the owner element node
4736 * @name: the name of the schema attribute node
4737 * @type: the built-in type to be validated against
4738 * @value: the resulting value if any
4739 *
4740 * Extracts and validates a value against the given built-in type.
4741 * This one is intended to be used internally for validation
4742 * of schema attribute values during parsing of the schema.
4743 *
4744 * Returns 0 if the value is valid, a positive error code
4745 * number otherwise and -1 in case of an internal or API error.
4746 */
4747static int
4748xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
4749 xmlChar **ownerDes,
4750 xmlSchemaTypePtr ownerItem,
4751 xmlNodePtr ownerElem,
4752 const char *name,
4753 xmlSchemaTypePtr type,
4754 const xmlChar **value)
4755{
4756 xmlAttrPtr attr;
4757
4758 if ((ctxt == NULL) || (type == NULL)) {
4759 if (value != NULL)
4760 *value = NULL;
4761 return (-1);
4762 }
4763 if (type->type != XML_SCHEMA_TYPE_BASIC) {
4764 if (value != NULL)
4765 *value = NULL;
4766 xmlSchemaPErr(ctxt, ownerElem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004767 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004768 "Internal error: xmlSchemaPValAttr, the given "
4769 "type '%s' is not a built-in type.\n",
4770 type->name, NULL);
4771 return (-1);
4772 }
4773 attr = xmlSchemaGetPropNode(ownerElem, name);
4774 if (attr == NULL) {
4775 if (value != NULL)
4776 *value = NULL;
4777 return (0);
4778 }
4779 return (xmlSchemaPValAttrNode(ctxt, ownerDes, ownerItem, attr,
4780 type, value));
4781}
4782/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004783 * xmlSchemaParseAttrDecls:
4784 * @ctxt: a schema validation context
4785 * @schema: the schema being built
4786 * @node: a subtree containing XML Schema informations
4787 * @type: the hosting type
4788 *
4789 * parse a XML schema attrDecls declaration corresponding to
4790 * <!ENTITY % attrDecls
4791 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
4792 */
4793static xmlNodePtr
4794xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4795 xmlNodePtr child, xmlSchemaTypePtr type)
4796{
4797 xmlSchemaAttributePtr lastattr, attr;
4798
4799 lastattr = NULL;
4800 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004801 (IS_SCHEMA(child, "attributeGroup"))) {
4802 attr = NULL;
4803 if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00004804 attr = xmlSchemaParseAttribute(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004805 } else if (IS_SCHEMA(child, "attributeGroup")) {
4806 attr = (xmlSchemaAttributePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00004807 xmlSchemaParseAttributeGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004808 }
4809 if (attr != NULL) {
4810 if (lastattr == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00004811 if (type->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
4812 ((xmlSchemaAttributeGroupPtr) type)->attributes = attr;
4813 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004814 type->attributes = attr;
4815 lastattr = attr;
4816 } else {
4817 lastattr->next = attr;
4818 lastattr = attr;
4819 }
4820 }
4821 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004822 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004823 return (child);
Daniel Veillard4255d502002-04-16 15:50:10 +00004824}
4825
4826/**
4827 * xmlSchemaParseAnnotation:
4828 * @ctxt: a schema validation context
4829 * @schema: the schema being built
4830 * @node: a subtree containing XML Schema informations
4831 *
4832 * parse a XML schema Attrribute declaration
4833 * *WARNING* this interface is highly subject to change
4834 *
William M. Bracke7091952004-05-11 15:09:58 +00004835 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00004836 * 1 in case of success.
4837 */
4838static xmlSchemaAnnotPtr
4839xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4840 xmlNodePtr node)
4841{
4842 xmlSchemaAnnotPtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004843 xmlNodePtr child = NULL;
4844 xmlAttrPtr attr;
4845 int barked = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00004846
Daniel Veillardc0826a72004-08-10 14:17:33 +00004847 /*
4848 * INFO: S4S completed.
4849 */
4850 /*
4851 * id = ID
4852 * {any attributes with non-schema namespace . . .}>
4853 * Content: (appinfo | documentation)*
4854 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004855 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4856 return (NULL);
4857 ret = xmlSchemaNewAnnot(ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004858 attr = node->properties;
4859 while (attr != NULL) {
4860 if (((attr->ns == NULL) &&
4861 (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
4862 ((attr->ns != NULL) &&
4863 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
4864
4865 xmlSchemaPIllegalAttrErr(ctxt,
4866 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4867 NULL, NULL, attr);
4868 }
4869 attr = attr->next;
4870 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00004871 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00004872 /*
4873 * And now for the children...
4874 */
4875 child = node->children;
4876 while (child != NULL) {
4877 if (IS_SCHEMA(child, "appinfo")) {
4878 /* TODO: make available the content of "appinfo". */
4879 /*
4880 * source = anyURI
4881 * {any attributes with non-schema namespace . . .}>
4882 * Content: ({any})*
4883 */
4884 attr = child->properties;
4885 while (attr != NULL) {
4886 if (((attr->ns == NULL) &&
4887 (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
4888 ((attr->ns != NULL) &&
4889 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004890
Daniel Veillardc0826a72004-08-10 14:17:33 +00004891 xmlSchemaPIllegalAttrErr(ctxt,
4892 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4893 NULL, NULL, attr);
4894 }
4895 attr = attr->next;
4896 }
4897 xmlSchemaPValAttr(ctxt, NULL, NULL, child, "source",
4898 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
4899 child = child->next;
4900 } else if (IS_SCHEMA(child, "documentation")) {
4901 /* TODO: make available the content of "documentation". */
4902 /*
4903 * source = anyURI
4904 * {any attributes with non-schema namespace . . .}>
4905 * Content: ({any})*
4906 */
4907 attr = child->properties;
4908 while (attr != NULL) {
4909 if (attr->ns == NULL) {
4910 if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
4911 xmlSchemaPIllegalAttrErr(ctxt,
4912 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4913 NULL, NULL, attr);
4914 }
4915 } else {
4916 if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
4917 (xmlStrEqual(attr->name, BAD_CAST "lang") &&
4918 (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
4919
4920 xmlSchemaPIllegalAttrErr(ctxt,
4921 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4922 NULL, NULL, attr);
4923 }
4924 }
4925 attr = attr->next;
4926 }
4927 /*
4928 * Attribute "xml:lang".
4929 */
4930 attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
4931 if (attr != NULL)
4932 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
4933 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
4934 child = child->next;
4935 } else {
4936 if (!barked)
4937 xmlSchemaPContentErr(ctxt,
4938 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
4939 NULL, NULL, node, child, NULL, "(appinfo | documentation)*");
4940 barked = 1;
4941 child = child->next;
4942 }
4943 }
4944
Daniel Veillard4255d502002-04-16 15:50:10 +00004945 return (ret);
4946}
4947
4948/**
4949 * xmlSchemaParseFacet:
4950 * @ctxt: a schema validation context
4951 * @schema: the schema being built
4952 * @node: a subtree containing XML Schema informations
4953 *
4954 * parse a XML schema Facet declaration
4955 * *WARNING* this interface is highly subject to change
4956 *
4957 * Returns the new type structure or NULL in case of error
4958 */
4959static xmlSchemaFacetPtr
4960xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004961 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004962{
4963 xmlSchemaFacetPtr facet;
4964 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004965 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00004966
4967 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4968 return (NULL);
4969
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004970 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004971 if (facet == NULL) {
4972 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
4973 return (NULL);
4974 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004975 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004976 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00004977 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004978 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
4979 "Facet %s has no value\n", node->name, NULL);
4980 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00004981 return (NULL);
4982 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004983 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004984 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004985 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004986 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004987 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004988 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004989 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004990 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004991 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004992 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004993 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004994 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004995 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004996 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004997 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004998 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004999 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005000 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005001 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005002 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005003 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005004 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
5005 } else if (IS_SCHEMA(node, "minLength")) {
5006 facet->type = XML_SCHEMA_FACET_MINLENGTH;
5007 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005008 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
5009 "Unknown facet type %s\n", node->name, NULL);
5010 xmlSchemaFreeFacet(facet);
5011 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005012 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005013 xmlSchemaPValAttrID(ctxt, NULL,
5014 (xmlSchemaTypePtr) facet, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00005015 facet->value = value;
Daniel Veillard01fa6152004-06-29 17:04:39 +00005016 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
5017 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
5018 const xmlChar *fixed;
5019
5020 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
5021 if (fixed != NULL) {
5022 if (xmlStrEqual(fixed, BAD_CAST "true"))
5023 facet->fixed = 1;
5024 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005025 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005026 child = node->children;
5027
5028 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005029 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5030 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005031 }
5032 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005033 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
5034 "Facet %s has unexpected child content\n",
5035 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005036 }
5037 return (facet);
5038}
5039
5040/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005041 * xmlSchemaParseWildcardNs:
5042 * @ctxt: a schema parser context
5043 * @wildc: the wildcard, already created
5044 * @node: a subtree containing XML Schema informations
5045 *
5046 * Parses the attribute "processContents" and "namespace"
5047 * of a xsd:anyAttribute and xsd:any.
5048 * *WARNING* this interface is highly subject to change
5049 *
5050 * Returns 0 if everything goes fine, a positive error code
5051 * if something is not valid and -1 if an internal error occurs.
5052 */
5053static int
5054xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
5055 xmlSchemaPtr schema,
5056 xmlSchemaWildcardPtr wildc,
5057 xmlNodePtr node)
5058{
5059 const xmlChar *pc, *ns, *dictnsItem;
5060 int ret = 0;
5061 xmlChar *nsItem;
5062 xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
5063 xmlAttrPtr attr;
5064
5065 pc = xmlSchemaGetProp(ctxt, node, "processContents");
5066 if ((pc == NULL)
5067 || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
5068 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
5069 } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
5070 wildc->processContents = XML_SCHEMAS_ANY_SKIP;
5071 } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
5072 wildc->processContents = XML_SCHEMAS_ANY_LAX;
5073 } else {
5074 xmlSchemaPSimpleTypeErr(ctxt,
5075 XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD,
5076 NULL, NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00005077 NULL, "(strict | skip | lax)", pc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005078 NULL, NULL, NULL);
5079 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
5080 ret = XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD;
5081 }
5082 /*
5083 * Build the namespace constraints.
5084 */
5085 attr = xmlSchemaGetPropNode(node, "namespace");
5086 ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5087 if ((ns == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
5088 wildc->any = 1;
5089 else if (xmlStrEqual(ns, BAD_CAST "##other")) {
5090 wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
5091 if (wildc->negNsSet == NULL) {
5092 return (-1);
5093 }
5094 wildc->negNsSet->value = schema->targetNamespace;
5095 } else {
5096 const xmlChar *end, *cur;
5097
5098 cur = ns;
5099 do {
5100 while (IS_BLANK_CH(*cur))
5101 cur++;
5102 end = cur;
5103 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
5104 end++;
5105 if (end == cur)
5106 break;
5107 nsItem = xmlStrndup(cur, end - cur);
5108 if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
5109 (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
5110 xmlSchemaPSimpleTypeErr(ctxt,
5111 XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
5112 NULL, NULL, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005113 NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005114 "((##any | ##other) | List of (anyURI | "
5115 "(##targetNamespace | ##local)))",
5116 nsItem, NULL, NULL, NULL);
5117 ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
5118 } else {
5119 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
5120 dictnsItem = schema->targetNamespace;
5121 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
5122 dictnsItem = NULL;
5123 } else {
5124 /*
5125 * Validate the item (anyURI).
5126 */
5127 xmlSchemaPValAttrNodeValue(ctxt, NULL, NULL, attr,
5128 nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
5129 dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
5130 }
5131 /*
5132 * Avoid dublicate namespaces.
5133 */
5134 tmp = wildc->nsSet;
5135 while (tmp != NULL) {
5136 if (dictnsItem == tmp->value)
5137 break;
5138 tmp = tmp->next;
5139 }
5140 if (tmp == NULL) {
5141 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
5142 if (tmp == NULL) {
5143 xmlFree(nsItem);
5144 return (-1);
5145 }
5146 tmp->value = dictnsItem;
5147 tmp->next = NULL;
5148 if (wildc->nsSet == NULL)
5149 wildc->nsSet = tmp;
5150 else
5151 lastNs->next = tmp;
5152 lastNs = tmp;
5153 }
5154
5155 }
5156 xmlFree(nsItem);
5157 cur = end;
5158 } while (*cur != 0);
5159 }
5160 return (ret);
5161}
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005162
5163static int
5164xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
5165 xmlSchemaTypePtr item,
5166 xmlNodePtr node,
5167 int minOccurs,
5168 int maxOccurs) {
5169
5170 if (maxOccurs != UNBOUNDED) {
5171 /*
5172 * TODO: Maby we should better not create the particle,
5173 * if min/max is invalid, since it could confuse the build of the
5174 * content model.
5175 */
5176 /*
5177 * 3.9.6 Schema Component Constraint: Particle Correct
5178 *
5179 */
5180 if (maxOccurs < 1) {
5181 /*
5182 * 2.2 {max occurs} must be greater than or equal to 1.
5183 */
5184 xmlSchemaPCustomAttrErr(ctxt,
5185 XML_SCHEMAP_P_PROPS_CORRECT_2_2,
5186 NULL, item, xmlSchemaGetPropNode(node, "maxOccurs"),
5187 "The value must be greater than or equal to 1");
5188 return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
5189 } else if (minOccurs > maxOccurs) {
5190 /*
5191 * 2.1 {min occurs} must not be greater than {max occurs}.
5192 */
5193 xmlSchemaPCustomAttrErr(ctxt,
5194 XML_SCHEMAP_P_PROPS_CORRECT_2_1,
5195 NULL, item, xmlSchemaGetPropNode(node, "minOccurs"),
5196 "The value must not be greater than the value of 'maxOccurs'");
5197 return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
5198 }
5199 }
5200 return (0);
5201}
5202
Daniel Veillardc0826a72004-08-10 14:17:33 +00005203/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005204 * xmlSchemaParseAny:
5205 * @ctxt: a schema validation context
5206 * @schema: the schema being built
5207 * @node: a subtree containing XML Schema informations
5208 *
5209 * parse a XML schema Any declaration
5210 * *WARNING* this interface is highly subject to change
5211 *
5212 * Returns the new type structure or NULL in case of error
5213 */
5214static xmlSchemaTypePtr
5215xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5216 xmlNodePtr node)
5217{
5218 xmlSchemaTypePtr type;
5219 xmlNodePtr child = NULL;
5220 xmlChar name[30];
Daniel Veillardc0826a72004-08-10 14:17:33 +00005221 xmlSchemaWildcardPtr wildc;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005222 int minOccurs, maxOccurs;
Daniel Veillard4255d502002-04-16 15:50:10 +00005223
5224 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5225 return (NULL);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005226 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
5227 "(nonNegativeInteger | unbounded)");
5228 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
5229 "nonNegativeInteger");
5230 if ((minOccurs == 0) && (maxOccurs == 0))
5231 return (NULL);
5232
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005233 snprintf((char *) name, 30, "#any%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00005234 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005235 if (type == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005236 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005237 type->node = node;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005238 type->type = XML_SCHEMA_TYPE_ANY;
5239
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005240 /*
5241 * TODO: Use a particle component here.
5242 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00005243 wildc = xmlSchemaAddWildcard(ctxt);
5244 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005245 * Check min/max sanity.
5246 */
5247 type->maxOccurs = maxOccurs;
5248 type->minOccurs = minOccurs;
5249 xmlSchemaPCheckParticleCorrect_2(ctxt, type,
5250 node, type->minOccurs, type->maxOccurs);
5251 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005252 * This is not nice, since it is won't be used as a attribute wildcard,
5253 * but better than adding a field to the structure.
5254 */
5255 type->attributeWildcard = wildc;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005256 xmlSchemaParseWildcardNs(ctxt, schema, wildc, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005257 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00005258 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005259 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5260 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005261 }
5262 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005263 xmlSchemaPErr2(ctxt, node, child,
5264 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
5265 "Sequence %s has unexpected content\n", type->name,
5266 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005267 }
5268
5269 return (type);
5270}
5271
5272/**
5273 * xmlSchemaParseNotation:
5274 * @ctxt: a schema validation context
5275 * @schema: the schema being built
5276 * @node: a subtree containing XML Schema informations
5277 *
5278 * parse a XML schema Notation declaration
5279 *
5280 * Returns the new structure or NULL in case of error
5281 */
5282static xmlSchemaNotationPtr
5283xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005284 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005285{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005286 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00005287 xmlSchemaNotationPtr ret;
5288 xmlNodePtr child = NULL;
5289
5290 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5291 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005292 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00005293 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005294 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
5295 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005296 return (NULL);
5297 }
5298 ret = xmlSchemaAddNotation(ctxt, schema, name);
5299 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005300 return (NULL);
5301 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005302 ret->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00005303
5304 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
5305 node, BAD_CAST "id");
5306
5307 if (IS_SCHEMA(child, "annotation")) {
5308 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5309 child = child->next;
5310 }
5311
Daniel Veillard4255d502002-04-16 15:50:10 +00005312 child = node->children;
5313 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005314 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5315 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005316 }
5317 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005318 xmlSchemaPErr2(ctxt, node, child,
5319 XML_SCHEMAP_UNKNOWN_NOTATION_CHILD,
5320 "notation %s has unexpected content\n", name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005321 }
5322
5323 return (ret);
5324}
5325
5326/**
5327 * xmlSchemaParseAnyAttribute:
5328 * @ctxt: a schema validation context
5329 * @schema: the schema being built
5330 * @node: a subtree containing XML Schema informations
5331 *
5332 * parse a XML schema AnyAttrribute declaration
5333 * *WARNING* this interface is highly subject to change
5334 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005335 * Returns a wildcard or NULL.
Daniel Veillard4255d502002-04-16 15:50:10 +00005336 */
Daniel Veillard3646d642004-06-02 19:19:14 +00005337static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005338xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
5339 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005340{
Daniel Veillard3646d642004-06-02 19:19:14 +00005341 xmlSchemaWildcardPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00005342 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005343 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005344
5345 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5346 return (NULL);
5347
Daniel Veillard3646d642004-06-02 19:19:14 +00005348 ret = xmlSchemaAddWildcard(ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00005349 if (ret == NULL) {
5350 return (NULL);
5351 }
William M. Bracke7091952004-05-11 15:09:58 +00005352 ret->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005353 /*
5354 * Check for illegal attributes.
5355 */
5356 attr = node->properties;
5357 while (attr != NULL) {
5358 if (attr->ns == NULL) {
5359 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5360 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
5361 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
5362 xmlSchemaPIllegalAttrErr(ctxt,
5363 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5364 NULL, NULL, attr);
5365 }
5366 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5367 xmlSchemaPIllegalAttrErr(ctxt,
5368 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5369 NULL, NULL, attr);
5370 }
5371 attr = attr->next;
5372 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005373 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
5374 node, BAD_CAST "id");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005375 /*
5376 * Parse the namespace list.
5377 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00005378 if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0) {
5379 xmlSchemaFreeWildcard(ret);
5380 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005381 }
5382 /*
5383 * And now for the children...
5384 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005385 child = node->children;
5386 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005387 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5388 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005389 }
5390 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005391 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005392 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5393 NULL, NULL, node, child,
5394 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005395 }
5396
5397 return (ret);
5398}
5399
5400
5401/**
5402 * xmlSchemaParseAttribute:
5403 * @ctxt: a schema validation context
5404 * @schema: the schema being built
5405 * @node: a subtree containing XML Schema informations
5406 *
5407 * parse a XML schema Attrribute declaration
5408 * *WARNING* this interface is highly subject to change
5409 *
William M. Bracke7091952004-05-11 15:09:58 +00005410 * Returns the attribute declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00005411 */
5412static xmlSchemaAttributePtr
5413xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00005414 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005415{
Daniel Veillardc0826a72004-08-10 14:17:33 +00005416 const xmlChar *name, *attrValue;
5417 xmlChar *repName = NULL; /* The reported designation. */
Daniel Veillard4255d502002-04-16 15:50:10 +00005418 xmlSchemaAttributePtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005419 xmlNodePtr child = NULL;
5420 xmlAttrPtr attr, nameAttr;
5421 int isRef = 0;
William M. Bracke7091952004-05-11 15:09:58 +00005422
5423 /*
5424 * Note that the w3c spec assumes the schema to be validated with schema
5425 * for schemas beforehand.
5426 *
5427 * 3.2.3 Constraints on XML Representations of Attribute Declarations
William M. Bracke7091952004-05-11 15:09:58 +00005428 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005429
5430 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5431 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005432 attr = xmlSchemaGetPropNode(node, "ref");
5433 nameAttr = xmlSchemaGetPropNode(node, "name");
5434
5435 if ((attr == NULL) && (nameAttr == NULL)) {
5436 /*
5437 * 3.2.3 : 3.1
5438 * One of ref or name must be present, but not both
5439 */
5440 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
5441 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, node, NULL,
5442 "One of the attributes 'ref' or 'name' must be present");
5443 return (NULL);
5444 }
5445 if ((topLevel) || (attr == NULL)) {
5446 if (nameAttr == NULL) {
5447 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
5448 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, node,
5449 "name", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005450 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005451 }
5452 } else
5453 isRef = 1;
5454
5455 if (isRef) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005456 char buf[50];
Daniel Veillardc0826a72004-08-10 14:17:33 +00005457 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix = NULL;
5458
5459 /*
5460 * Parse as attribute reference.
5461 */
5462 if (xmlSchemaPValAttrNodeQName(ctxt, schema,
5463 (xmlChar **) &xmlSchemaElemDesAttrRef, NULL, attr, &refNs,
5464 &refPrefix, &ref) != 0) {
5465 return (NULL);
5466 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005467 snprintf(buf, 49, "#aRef%d", ctxt->counter++ + 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005468 name = (const xmlChar *) buf;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005469 ret = xmlSchemaAddAttribute(ctxt, schema, name, NULL, node, 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005470 if (ret == NULL) {
5471 if (repName != NULL)
5472 xmlFree(repName);
5473 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005474 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005475 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
5476 ret->node = node;
5477 ret->refNs = refNs;
5478 ret->refPrefix = refPrefix;
5479 ret->ref = ref;
5480 /*
5481 xmlSchemaFormatTypeRep(&repName, (xmlSchemaTypePtr) ret, NULL, NULL);
5482 */
5483 if (nameAttr != NULL)
5484 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
5485 &repName, (xmlSchemaTypePtr) ret, nameAttr,
5486 "ref", "name");
5487 /*
5488 * Check for illegal attributes.
5489 */
5490 attr = node->properties;
5491 while (attr != NULL) {
5492 if (attr->ns == NULL) {
5493 if (xmlStrEqual(attr->name, BAD_CAST "type") ||
5494 xmlStrEqual(attr->name, BAD_CAST "form")) {
5495 /*
5496 * 3.2.3 : 3.2
5497 * If ref is present, then all of <simpleType>,
5498 * form and type must be absent.
5499 */
5500 xmlSchemaPIllegalAttrErr(ctxt,
5501 XML_SCHEMAP_SRC_ATTRIBUTE_3_2, &repName,
5502 (xmlSchemaTypePtr) ret, attr);
5503 } else if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
5504 (!xmlStrEqual(attr->name, BAD_CAST "use")) &&
5505 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5506 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
5507 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
5508 (!xmlStrEqual(attr->name, BAD_CAST "default"))) {
5509 xmlSchemaPIllegalAttrErr(ctxt,
5510 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5511 &repName, (xmlSchemaTypePtr) ret, attr);
5512 }
5513 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5514 xmlSchemaPIllegalAttrErr(ctxt,
5515 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5516 &repName, (xmlSchemaTypePtr) ret, attr);
5517 }
5518 attr = attr->next;
5519 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005520 } else {
William M. Bracke7091952004-05-11 15:09:58 +00005521 const xmlChar *ns = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005522
5523 /*
5524 * Parse as attribute declaration.
5525 */
5526 if (xmlSchemaPValAttrNode(ctxt,
5527 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, nameAttr,
5528 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
5529 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005530 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005531 /*
5532 xmlSchemaFormatTypeRep(&repName, NULL, xmlSchemaElemDesAttrDecl, name);
5533 */
5534 /*
5535 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
5536 */
5537 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
5538 xmlSchemaPSimpleTypeErr(ctxt,
5539 XML_SCHEMAP_NO_XMLNS,
5540 &repName, NULL, (xmlNodePtr) nameAttr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005541 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), "NCName", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005542 "The value must not match 'xmlns'",
5543 NULL, NULL);
5544 if (repName != NULL)
5545 xmlFree(repName);
5546 return (NULL);
5547 }
5548 /*
5549 * Evaluate the target namespace
5550 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005551 if (topLevel) {
5552 ns = schema->targetNamespace;
5553 } else {
5554 attr = xmlSchemaGetPropNode(node, "form");
5555 if (attr != NULL) {
5556 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5557 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
5558 ns = schema->targetNamespace;
5559 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
5560 xmlSchemaPSimpleTypeErr(ctxt,
5561 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5562 &repName, NULL, (xmlNodePtr) attr,
5563 NULL, "(qualified | unqualified)",
5564 attrValue, NULL, NULL, NULL);
5565 }
5566 } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
5567 ns = schema->targetNamespace;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005568 }
5569 ret = xmlSchemaAddAttribute(ctxt, schema, name, ns, node, topLevel);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005570 if (ret == NULL) {
5571 if (repName != NULL)
5572 xmlFree(repName);
Daniel Veillard3646d642004-06-02 19:19:14 +00005573 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005574 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005575 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005576 ret->node = node;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005577 if (topLevel)
5578 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
5579 /*
5580 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
5581 */
5582 if (xmlStrEqual(ret->targetNamespace, xmlSchemaInstanceNs)) {
5583 xmlSchemaPCustomErr(ctxt,
5584 XML_SCHEMAP_NO_XSI,
5585 &repName, (xmlSchemaTypePtr) ret, node,
5586 "The target namespace must not match '%s'",
5587 xmlSchemaInstanceNs);
5588 }
5589 /*
5590 * Check for illegal attributes.
5591 */
5592 attr = node->properties;
5593 while (attr != NULL) {
5594 if (attr->ns == NULL) {
5595 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5596 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
5597 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
5598 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
5599 (!xmlStrEqual(attr->name, BAD_CAST "type"))) {
5600 if ((topLevel) ||
5601 ((!xmlStrEqual(attr->name, BAD_CAST "form")) &&
5602 (!xmlStrEqual(attr->name, BAD_CAST "use")))) {
5603 xmlSchemaPIllegalAttrErr(ctxt,
5604 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5605 &repName, (xmlSchemaTypePtr) ret, attr);
5606 }
5607 }
5608 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5609 xmlSchemaPIllegalAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5610 &repName, (xmlSchemaTypePtr) ret, attr);
5611 }
5612 attr = attr->next;
5613 }
5614 xmlSchemaPValAttrQName(ctxt, schema, &repName, (xmlSchemaTypePtr) ret,
5615 node, "type", &ret->typeNs, NULL, &ret->typeName);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005616 }
5617 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
5618 node, BAD_CAST "id");
William M. Bracke7091952004-05-11 15:09:58 +00005619 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005620 * Attribute "fixed".
William M. Bracke7091952004-05-11 15:09:58 +00005621 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00005622 ret->defValue = xmlSchemaGetProp(ctxt, node, "fixed");
5623 if (ret->defValue != NULL)
5624 ret->flags |= XML_SCHEMAS_ATTR_FIXED;
5625 /*
5626 * Attribute "default".
5627 */
5628 attr = xmlSchemaGetPropNode(node, "default");
5629 if (attr != NULL) {
5630 /*
5631 * 3.2.3 : 1
5632 * default and fixed must not both be present.
5633 */
5634 if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
5635 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
5636 &repName, (xmlSchemaTypePtr) ret, attr, "default", "fixed");
5637 } else
5638 ret->defValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5639 }
5640 if (topLevel == 0) {
5641 /*
5642 * Attribute "use".
5643 */
5644 attr = xmlSchemaGetPropNode(node, "use");
5645 if (attr != NULL) {
5646 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5647 if (xmlStrEqual(attrValue, BAD_CAST "optional"))
5648 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
5649 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
5650 ret->occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
5651 else if (xmlStrEqual(attrValue, BAD_CAST "required"))
5652 ret->occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
5653 else
5654 xmlSchemaPSimpleTypeErr(ctxt,
5655 XML_SCHEMAP_INVALID_ATTR_USE,
5656 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005657 NULL, "(optional | prohibited | required)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00005658 attrValue, NULL, NULL, NULL);
5659 } else
5660 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
5661 /*
5662 * 3.2.3 : 2
5663 * If default and use are both present, use must have
5664 * the actual value optional.
5665 */
5666 if ((ret->occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
5667 (ret->defValue != NULL) &&
5668 ((ret->flags & XML_SCHEMAS_ATTR_FIXED) == 0)) {
5669 xmlSchemaPSimpleTypeErr(ctxt,
5670 XML_SCHEMAP_SRC_ATTRIBUTE_2,
5671 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005672 NULL, "(optional | prohibited | required)", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005673 "The value must be 'optional' if the attribute "
5674 "'default' is present as well", NULL, NULL);
5675 }
5676 }
5677 /*
5678 * And now for the children...
5679 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005680 child = node->children;
5681 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005682 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5683 child = child->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005684 }
5685 if (isRef) {
5686 if (child != NULL) {
5687 if (IS_SCHEMA(child, "simpleType"))
5688 /*
5689 * 3.2.3 : 3.2
5690 * If ref is present, then all of <simpleType>,
5691 * form and type must be absent.
5692 */
5693 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
5694 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
5695 "(annotation?)");
5696 else
5697 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5698 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
5699 "(annotation?)");
5700 }
5701 } else {
5702 if (IS_SCHEMA(child, "simpleType")) {
5703 if (ret->typeName != NULL) {
5704 /*
5705 * 3.2.3 : 4
5706 * type and <simpleType> must not both be present.
5707 */
5708 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
5709 &repName, (xmlSchemaTypePtr) ret, node, child,
5710 "The attribute 'type' and the <simpleType> child "
5711 "are mutually exclusive", NULL);
5712 } else
5713 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
5714 child = child->next;
5715 }
5716 if (child != NULL)
5717 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5718 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
5719 "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005720 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005721 /*
5722 * Cleanup.
5723 */
5724 if (repName != NULL)
5725 xmlFree(repName);
Daniel Veillard4255d502002-04-16 15:50:10 +00005726 return (ret);
5727}
5728
5729/**
5730 * xmlSchemaParseAttributeGroup:
5731 * @ctxt: a schema validation context
5732 * @schema: the schema being built
5733 * @node: a subtree containing XML Schema informations
5734 *
5735 * parse a XML schema Attribute Group declaration
5736 * *WARNING* this interface is highly subject to change
5737 *
5738 * Returns the attribute group or NULL in case of error.
5739 */
5740static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005741xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00005742 xmlSchemaPtr schema, xmlNodePtr node,
5743 int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005744{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005745 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00005746 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00005747 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005748 const xmlChar *oldcontainer;
5749 xmlAttrPtr attr, nameAttr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005750
5751 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5752 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005753
5754 nameAttr = xmlSchemaGetPropNode(node, "name");
5755 attr = xmlSchemaGetPropNode(node, "ref");
5756 if ((topLevel) || (attr == NULL)) {
5757 /*
5758 * Parse as an attribute group definition.
5759 * Note that those are allowed at top level only.
5760 */
5761 if (nameAttr == NULL) {
5762 xmlSchemaPMissingAttrErr(ctxt,
5763 XML_SCHEMAP_S4S_ATTR_MISSING,
5764 NULL, NULL, node, "name", NULL);
5765 return (NULL);
5766 }
5767 name = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) nameAttr);
5768 /*
5769 * The name is crucial, exit if invalid.
5770 */
5771 if (xmlSchemaPValAttrNode(ctxt,
5772 NULL, NULL, nameAttr,
5773 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
5774 return (NULL);
5775 }
5776 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
5777 if (ret == NULL)
5778 return (NULL);
5779 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
5780 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
5781 ret->node = node;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005782 ret->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005783 } else {
5784 char buf[50];
5785 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix;
5786
5787 /*
5788 * Parse as an attribute group definition reference.
5789 */
5790 if (attr == NULL) {
5791 xmlSchemaPMissingAttrErr(ctxt,
5792 XML_SCHEMAP_S4S_ATTR_MISSING,
5793 NULL, NULL, node, "ref", NULL);
5794 }
5795 xmlSchemaPValAttrNodeQName(ctxt, schema,
5796 NULL, NULL, attr, &refNs, &refPrefix, &ref);
5797
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005798 snprintf(buf, 49, "#agRef%d", ctxt->counter++ + 1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005799 name = (const xmlChar *) buf;
5800 if (name == NULL) {
5801 xmlSchemaPErrMemory(ctxt, "creating internal name for an "
5802 "attribute group definition reference", node);
5803 return (NULL);
5804 }
5805 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
5806 if (ret == NULL)
5807 return (NULL);
5808 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
5809 ret->ref = ref;
5810 ret->refNs = refNs;
5811 /* TODO: Is @refPrefix currently used? */
5812 ret->refPrefix = refPrefix;
5813 ret->node = node;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005814 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005815 /*
5816 * Check for illegal attributes.
5817 */
5818 attr = node->properties;
5819 while (attr != NULL) {
5820 if (attr->ns == NULL) {
5821 if ((((topLevel == 0) && (!xmlStrEqual(attr->name, BAD_CAST "ref"))) ||
5822 (topLevel && (!xmlStrEqual(attr->name, BAD_CAST "name")))) &&
5823 (!xmlStrEqual(attr->name, BAD_CAST "id")))
5824 {
5825 xmlSchemaPIllegalAttrErr(ctxt,
5826 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5827 NULL, NULL, attr);
5828 }
5829 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5830 xmlSchemaPIllegalAttrErr(ctxt,
5831 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5832 NULL, NULL, attr);
5833 }
5834 attr = attr->next;
5835 }
5836 /* TODO: Validate "id" ? */
5837 /*
5838 * And now for the children...
5839 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005840 oldcontainer = ctxt->container;
Daniel Veillard4255d502002-04-16 15:50:10 +00005841 ctxt->container = name;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005842 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00005843 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005844 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5845 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005846 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005847 if (topLevel) {
5848 child = xmlSchemaParseAttrDecls(ctxt, schema, child, (xmlSchemaTypePtr) ret);
5849 if (IS_SCHEMA(child, "anyAttribute")) {
5850 ret->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
5851 child = child->next;
5852 }
5853 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005854 if (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005855 xmlSchemaPContentErr(ctxt,
5856 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5857 NULL, NULL, node, child, NULL,
5858 "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005859 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005860 ctxt->container = oldcontainer;
5861 return (ret);
5862}
5863
5864/**
William M. Brack2f2a6632004-08-20 23:09:47 +00005865 * xmlSchemaPValAttrFormDefault:
5866 * @value: the value
5867 * @flags: the flags to be modified
5868 * @flagQualified: the specific flag for "qualified"
5869 *
5870 * Returns 0 if the value is valid, 1 otherwise.
5871 */
5872static int
5873xmlSchemaPValAttrFormDefault(const xmlChar *value,
5874 int *flags,
5875 int flagQualified)
5876{
5877 if (xmlStrEqual(value, BAD_CAST "qualified")) {
5878 if ((*flags & flagQualified) == 0)
5879 *flags |= flagQualified;
5880 } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
5881 return (1);
5882
5883 return (0);
5884}
5885
5886/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005887 * xmlSchemaPValAttrBlockFinal:
5888 * @value: the value
5889 * @flags: the flags to be modified
5890 * @flagAll: the specific flag for "#all"
5891 * @flagExtension: the specific flag for "extension"
5892 * @flagRestriction: the specific flag for "restriction"
5893 * @flagSubstitution: the specific flag for "substitution"
5894 * @flagList: the specific flag for "list"
5895 * @flagUnion: the specific flag for "union"
5896 *
5897 * Validates the value of the attribute "final" and "block". The value
5898 * is converted into the specified flag values and returned in @flags.
5899 *
5900 * Returns 0 if the value is valid, 1 otherwise.
5901 */
5902
5903static int
5904xmlSchemaPValAttrBlockFinal(const xmlChar *value,
5905 int *flags,
5906 int flagAll,
5907 int flagExtension,
5908 int flagRestriction,
5909 int flagSubstitution,
5910 int flagList,
5911 int flagUnion)
5912{
5913 int ret = 0;
5914
5915 /*
5916 * TODO: This does not check for dublicate entries.
5917 */
William M. Brack2f2a6632004-08-20 23:09:47 +00005918 if (value == NULL)
5919 return (1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005920 if (xmlStrEqual(value, BAD_CAST "#all")) {
5921 if (flagAll != -1)
5922 *flags |= flagAll;
5923 else {
5924 if (flagExtension != -1)
5925 *flags |= flagExtension;
5926 if (flagRestriction != -1)
5927 *flags |= flagRestriction;
5928 if (flagSubstitution != -1)
5929 *flags |= flagSubstitution;
5930 if (flagList != -1)
5931 *flags |= flagList;
5932 if (flagUnion != -1)
5933 *flags |= flagUnion;
5934 }
5935 } else {
5936 const xmlChar *end, *cur = value;
5937 xmlChar *item;
5938
5939 do {
5940 while (IS_BLANK_CH(*cur))
5941 cur++;
5942 end = cur;
5943 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
5944 end++;
5945 if (end == cur)
5946 break;
5947 item = xmlStrndup(cur, end - cur);
5948 if (xmlStrEqual(item, BAD_CAST "extension")) {
5949 if (flagExtension != -1) {
5950 if ((*flags & flagExtension) == 0)
5951 *flags |= flagExtension;
5952 } else
5953 ret = 1;
5954 } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
5955 if (flagRestriction != -1) {
5956 if ((*flags & flagRestriction) == 0)
5957 *flags |= flagRestriction;
5958 } else
5959 ret = 1;
5960 } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
5961 if (flagSubstitution != -1) {
5962 if ((*flags & flagSubstitution) == 0)
5963 *flags |= flagSubstitution;
5964 } else
5965 ret = 1;
5966 } else if (xmlStrEqual(item, BAD_CAST "list")) {
5967 if (flagList != -1) {
5968 if ((*flags & flagList) == 0)
5969 *flags |= flagList;
5970 } else
5971 ret = 1;
5972 } else if (xmlStrEqual(item, BAD_CAST "union")) {
5973 if (flagUnion != -1) {
5974 if ((*flags & flagUnion) == 0)
5975 *flags |= flagUnion;
5976 } else
5977 ret = 1;
5978 } else
5979 ret = 1;
5980 if (item != NULL)
5981 xmlFree(item);
5982 cur = end;
5983 } while ((ret == 0) && (*cur != 0));
5984 }
5985
5986 return (ret);
5987}
5988
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005989#ifdef IDC_ENABLED
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00005990static int
5991xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00005992 xmlSchemaIDCPtr idc,
5993 xmlSchemaIDCSelectPtr selector,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00005994 xmlAttrPtr attr,
5995 int isField)
5996{
5997 xmlNodePtr node;
5998
5999 /*
6000 * c-selector-xpath:
6001 * Schema Component Constraint: Selector Value OK
6002 *
6003 * TODO: 1 The {selector} must be a valid XPath expression, as defined
6004 * in [XPath].
6005 */
6006 if (selector == NULL) {
6007 xmlSchemaPErr(ctxt, idc->node,
6008 XML_SCHEMAP_INTERNAL,
6009 "Internal error: xmlSchemaCheckCSelectorXPath, "
6010 "the selector is not specified.\n", NULL, NULL);
6011 return (-1);
6012 }
6013 if (attr == NULL)
6014 node = idc->node;
6015 else
6016 node = (xmlNodePtr) attr;
6017 if (selector->xpath == NULL) {
6018 xmlSchemaPCustomErr(ctxt,
6019 /* TODO: Adjust error code. */
6020 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6021 NULL, NULL, node,
6022 "The XPath expression of the selector is not valid", NULL);
6023 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
6024 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006025 const xmlChar **nsArray = NULL;
6026 xmlNsPtr *nsList = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006027 /*
6028 * Compile the XPath expression.
6029 */
6030 /*
6031 * TODO: We need the array of in-scope namespaces for compilation.
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006032 * TODO: Call xmlPatterncompile with different options for selector/
6033 * field.
6034 */
6035 nsList = xmlGetNsList(attr->doc, attr->parent);
6036 /*
6037 * Build an array of prefixes and namespaces.
6038 */
6039 if (nsList != NULL) {
6040 int i, count = 0;
6041 xmlNsPtr ns;
6042
6043 for (i = 0; nsList[i] != NULL; i++)
6044 count++;
6045
6046 nsArray = (const xmlChar **) xmlMalloc(
6047 (count * 2 + 1) * sizeof(const xmlChar *));
6048 if (nsArray == NULL) {
6049 xmlSchemaPErrMemory(ctxt, "allocating a namespace array",
6050 NULL);
6051 return (-1);
6052 }
6053 for (i = 0; i < count; i++) {
6054 ns = nsList[i];
6055 nsArray[2 * i] = nsList[i]->href;
6056 nsArray[2 * i + 1] = nsList[i]->prefix;
6057 }
6058 nsArray[count * 2] = NULL;
6059 xmlFree(nsList);
6060 }
6061 if (isField)
6062 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik285ebab2005-03-04 18:04:59 +00006063 NULL, 1, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006064 else
6065 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik285ebab2005-03-04 18:04:59 +00006066 NULL, 1, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006067 if (nsArray != NULL)
6068 xmlFree((xmlChar **) nsArray);
6069
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006070#ifdef IDC_XPATH_SUPPORT
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00006071 if (selector->xpathComp == NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006072 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00006073 /* TODO: Adjust error code? */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006074 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6075 NULL, NULL, node,
6076 "The XPath expression '%s' could not be "
6077 "compiled", selector->xpath);
6078 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
6079 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00006080#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006081 }
6082 return (0);
6083}
6084
6085/**
6086 * xmlSchemaAssignAnnotation:
6087 * @item: the schema component
6088 * @annot: the annotation
6089 *
6090 * Adds the annotation to the given schema component.
6091 *
6092 * Returns the given annotaion.
6093 */
6094static xmlSchemaAnnotPtr
6095xmlSchemaAssignAnnotation(xmlSchemaBasicItemPtr item,
6096 xmlSchemaAnnotPtr annot)
6097{
6098 xmlSchemaAnnotPtr cur = item->annot;
6099
6100 if (item->annot == NULL) {
6101 item->annot = annot;
6102 return (annot);
6103 }
6104 cur = item->annot;
6105 if (cur->next != NULL) {
6106 cur = cur->next;
6107 }
6108 cur->next = annot;
6109 return (annot);
6110}
6111
6112/**
6113 * xmlSchemaParseIDCSelectorAndField:
6114 * @ctxt: a schema validation context
6115 * @schema: the schema being built
6116 * @node: a subtree containing XML Schema informations
6117 *
6118 * Parses a XML Schema identity-contraint definition's
6119 * <selector> and <field> elements.
6120 *
6121 * Returns the parsed identity-constraint definition.
6122 */
6123static xmlSchemaIDCSelectPtr
6124xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
6125 xmlSchemaPtr schema,
6126 xmlSchemaIDCPtr idc,
6127 xmlNodePtr node,
6128 int isField)
6129{
6130 xmlSchemaIDCSelectPtr item;
6131 xmlNodePtr child = NULL;
6132 xmlAttrPtr attr;
6133
6134 /*
6135 * Check for illegal attributes.
6136 */
6137 attr = node->properties;
6138 while (attr != NULL) {
6139 if (attr->ns == NULL) {
6140 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6141 (!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
6142 xmlSchemaPIllegalAttrErr(ctxt,
6143 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6144 NULL, NULL, attr);
6145 }
6146 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6147 xmlSchemaPIllegalAttrErr(ctxt,
6148 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6149 NULL, NULL, attr);
6150 }
6151 attr = attr->next;
6152 }
6153 /*
6154 * Create the item.
6155 */
6156 item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
6157 if (item == NULL) {
6158 xmlSchemaPErrMemory(ctxt,
6159 "allocating a 'selector' of an identity-constraint definition",
6160 NULL);
6161 return (NULL);
6162 }
6163 memset(item, 0, sizeof(xmlSchemaIDCSelect));
6164 /*
6165 * Attribute "xpath" (mandatory).
6166 */
6167 attr = xmlSchemaGetPropNode(node, "xpath");
6168 if (attr == NULL) {
6169 xmlSchemaPMissingAttrErr(ctxt,
6170 XML_SCHEMAP_S4S_ATTR_MISSING,
6171 NULL, NULL, node,
6172 "name", NULL);
6173 } else {
6174 item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6175 /*
6176 * URGENT TODO: "field"s have an other syntax than "selector"s.
6177 */
6178
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006179 if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr,
6180 isField) == -1) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006181 xmlSchemaPErr(ctxt,
6182 (xmlNodePtr) attr,
6183 XML_SCHEMAP_INTERNAL,
6184 "Internal error: xmlSchemaParseIDCSelectorAndField, "
6185 "validating the XPath expression of a IDC selector.\n",
6186 NULL, NULL);
6187 }
6188
6189 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00006190 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006191 /*
6192 * And now for the children...
6193 */
6194 child = node->children;
6195 if (IS_SCHEMA(child, "annotation")) {
6196 /*
6197 * Add the annotation to the parent IDC.
6198 */
6199 xmlSchemaAssignAnnotation((xmlSchemaBasicItemPtr) idc,
6200 xmlSchemaParseAnnotation(ctxt, schema, child));
6201 child = child->next;
6202 }
6203 if (child != NULL) {
6204 xmlSchemaPContentErr(ctxt,
6205 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6206 NULL, NULL, node, child,
6207 NULL, "(annotation?)");
6208 }
6209
6210 return (item);
6211}
6212
6213/**
6214 * xmlSchemaParseIDC:
6215 * @ctxt: a schema validation context
6216 * @schema: the schema being built
6217 * @node: a subtree containing XML Schema informations
6218 *
6219 * Parses a XML Schema identity-contraint definition.
6220 *
6221 * Returns the parsed identity-constraint definition.
6222 */
6223static xmlSchemaIDCPtr
6224xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
6225 xmlSchemaPtr schema,
6226 xmlNodePtr node,
6227 xmlSchemaTypeType idcCategory,
6228 const xmlChar *targetNamespace)
6229{
6230 xmlSchemaIDCPtr item = NULL;
6231 xmlNodePtr child = NULL;
6232 xmlAttrPtr attr;
6233 const xmlChar *name = NULL;
6234 xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
6235 int resAdd;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00006236
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006237 /*
6238 * Check for illegal attributes.
6239 */
6240 attr = node->properties;
6241 while (attr != NULL) {
6242 if (attr->ns == NULL) {
6243 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6244 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
6245 ((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
6246 (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
6247 xmlSchemaPIllegalAttrErr(ctxt,
6248 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6249 NULL, NULL, attr);
6250 }
6251 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6252 xmlSchemaPIllegalAttrErr(ctxt,
6253 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6254 NULL, NULL, attr);
6255 }
6256 attr = attr->next;
6257 }
6258 /*
6259 * Attribute "name" (mandatory).
6260 */
6261 attr = xmlSchemaGetPropNode(node, "name");
6262 if (attr == NULL) {
6263 xmlSchemaPMissingAttrErr(ctxt,
6264 XML_SCHEMAP_S4S_ATTR_MISSING,
6265 NULL, NULL, node,
6266 "name", NULL);
6267 return (NULL);
6268 } else if (xmlSchemaPValAttrNode(ctxt,
6269 NULL, NULL, attr,
6270 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
6271 return (NULL);
6272 }
6273 /*
6274 * Create the component.
6275 */
6276 if (schema->idcDef == NULL)
6277 schema->idcDef = xmlHashCreateDict(10, ctxt->dict);
6278 if (schema->idcDef == NULL)
6279 return (NULL);
6280
6281 item = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
6282 if (item == NULL) {
6283 xmlSchemaPErrMemory(ctxt,
6284 "allocating an identity-constraint definition", NULL);
6285 return (NULL);
6286 }
6287 /*
6288 * Add the IDC to the list of IDCs on the schema component.
6289 */
6290 resAdd = xmlHashAddEntry2(schema->idcDef, name, targetNamespace, item);
6291 if (resAdd != 0) {
6292 xmlSchemaPCustomErrExt(ctxt,
6293 XML_SCHEMAP_REDEFINED_TYPE,
6294 NULL, NULL, node,
6295 "An identity-constraint definition with the name '%s' "
6296 "and targetNamespace '%s' does already exist",
6297 name, targetNamespace, NULL);
6298 xmlFree(item);
6299 return (NULL);
6300 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006301 memset(item, 0, sizeof(xmlSchemaIDC));
6302 item->name = name;
6303 item->type = idcCategory;
6304 item->node = node;
6305 /*
6306 * The target namespace of the parent element declaration.
6307 */
6308 item->targetNamespace = targetNamespace;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00006309 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) item,
6310 node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006311 if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
6312 /*
6313 * Attribute "refer" (mandatory).
6314 */
6315 attr = xmlSchemaGetPropNode(node, "refer");
6316 if (attr == NULL) {
6317 xmlSchemaPMissingAttrErr(ctxt,
6318 XML_SCHEMAP_S4S_ATTR_MISSING,
6319 NULL, NULL, node,
6320 "refer", NULL);
6321 } else {
6322 /*
6323 * Create a reference item.
6324 */
6325 item->ref = (xmlSchemaItemQNRefPtr) xmlMalloc(
6326 sizeof(xmlSchemaItemQNRef));
6327 if (item->ref == NULL) {
6328 xmlSchemaPErrMemory(ctxt,
6329 "allocating a QName reference item", NULL);
6330 return (NULL);
6331 }
6332 memset(item->ref, 0, sizeof(xmlSchemaItemQNRef));
6333 xmlSchemaPValAttrNodeQName(ctxt, schema,
6334 NULL, NULL, attr,
6335 &(item->ref->targetNamespace), 0,
6336 &(item->ref->name));
6337 }
6338 }
6339 /*
6340 * And now for the children...
6341 */
6342 child = node->children;
6343 if (IS_SCHEMA(child, "annotation")) {
6344 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6345 child = child->next;
6346 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00006347 if (child == NULL) {
6348 xmlSchemaPContentErr(ctxt,
6349 XML_SCHEMAP_S4S_ELEM_MISSING,
6350 NULL, NULL, node, child,
6351 "A child element is missing",
6352 "(annotation?, (selector, field+))");
6353 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006354 /*
6355 * Child element <selector>.
6356 */
6357 if (IS_SCHEMA(child, "selector")) {
6358 item->selector = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
6359 item, child, 0);
6360 child = child->next;
6361 /*
6362 * Child elements <field>.
6363 */
6364 if (IS_SCHEMA(child, "field")) {
6365 do {
6366 field = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
6367 item, child, 1);
6368 if (field != NULL) {
6369 field->index = item->nbFields;
6370 item->nbFields++;
6371 if (lastField != NULL)
6372 lastField->next = field;
6373 else
6374 item->fields = field;
6375 lastField = field;
6376 }
6377 child = child->next;
6378 } while (IS_SCHEMA(child, "field"));
6379 } else {
6380 xmlSchemaPContentErr(ctxt,
6381 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6382 NULL, NULL, node, child,
6383 NULL, "(annotation?, (selector, field+))");
6384 }
6385 }
6386 if (child != NULL) {
6387 xmlSchemaPContentErr(ctxt,
6388 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6389 NULL, NULL, node, child,
6390 NULL, "(annotation?, (selector, field+))");
6391 }
6392
6393 return (item);
6394}
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006395#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006396
Daniel Veillardc0826a72004-08-10 14:17:33 +00006397/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006398 * xmlSchemaParseElement:
6399 * @ctxt: a schema validation context
6400 * @schema: the schema being built
6401 * @node: a subtree containing XML Schema informations
6402 *
6403 * parse a XML schema Element declaration
6404 * *WARNING* this interface is highly subject to change
6405 *
William M. Bracke7091952004-05-11 15:09:58 +00006406 * Returns the parsed element declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00006407 */
6408static xmlSchemaElementPtr
6409xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00006410 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006411{
Daniel Veillardc0826a72004-08-10 14:17:33 +00006412 const xmlChar *name = NULL;
6413 const xmlChar *attrValue;
6414 xmlChar *repName = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00006415 xmlSchemaElementPtr ret;
6416 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006417 const xmlChar *oldcontainer;
6418 xmlAttrPtr attr, nameAttr;
6419 int minOccurs, maxOccurs;
6420 int isRef = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006421#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006422 xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006423#endif
William M. Bracke7091952004-05-11 15:09:58 +00006424
6425 /* 3.3.3 Constraints on XML Representations of Element Declarations */
6426 /* TODO: Complete implementation of 3.3.6 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006427
Daniel Veillard4255d502002-04-16 15:50:10 +00006428 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6429 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006430
Daniel Veillardc0826a72004-08-10 14:17:33 +00006431 oldcontainer = ctxt->container;
6432
6433 nameAttr = xmlSchemaGetPropNode(node, "name");
6434 attr = xmlSchemaGetPropNode(node, "ref");
6435 if ((topLevel) || (attr == NULL)) {
6436 if (nameAttr == NULL) {
6437 xmlSchemaPMissingAttrErr(ctxt,
6438 XML_SCHEMAP_S4S_ATTR_MISSING,
6439 (xmlChar **) &xmlSchemaElemDesElemDecl, NULL, node,
6440 "name", NULL);
6441 return (NULL);
6442 }
6443 name = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) nameAttr);
6444 } else {
6445 isRef = 1;
6446
6447 }
6448 /*
6449 * ... unless minOccurs=maxOccurs=0, in which case the item corresponds
6450 * to no component at all
6451 * TODO: It might be better to validate the element, even if it won't be
6452 * used.
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006453 */
6454 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
6455 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(nonNegativeInteger | unbounded)");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006456 if ((minOccurs == 0) && (maxOccurs == 0))
6457 return (NULL);
6458 /*
6459 * If we get a "ref" attribute on a local <element> we will assume it's
6460 * a reference - even if there's a "name" attribute; this seems to be more
6461 * robust.
6462 */
6463 if (isRef) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006464 char buf[50];
Daniel Veillardc0826a72004-08-10 14:17:33 +00006465 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix;
6466
6467 /*
6468 * Parse as a particle.
6469 */
6470 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006471 (xmlChar **) &xmlSchemaElemDesElemRef,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006472 NULL, attr, &refNs, &refPrefix, &ref);
6473
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006474 snprintf(buf, 49, "#eRef%d", ctxt->counter++ + 1);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006475 ret = xmlSchemaAddElement(ctxt, schema, (const xmlChar *) buf, NULL, node, 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006476 if (ret == NULL) {
6477 if (repName != NULL)
6478 xmlFree(repName);
6479 return (NULL);
6480 }
6481 ret->type = XML_SCHEMA_TYPE_ELEMENT;
6482 ret->node = node;
6483 ret->ref = ref;
6484 ret->refNs = refNs;
6485 ret->refPrefix = refPrefix;
6486 ret->flags |= XML_SCHEMAS_ELEM_REF;
6487 /*
6488 * Check for illegal attributes.
6489 */
6490 /*
6491 * 3.3.3 : 2.1
6492 * One of ref or name must be present, but not both
6493 */
6494 if (nameAttr != NULL) {
6495 xmlSchemaPMutualExclAttrErr(ctxt,
6496 XML_SCHEMAP_SRC_ELEMENT_2_1,
6497 &repName, (xmlSchemaTypePtr) ret, nameAttr,
6498 "ref", "name");
6499 }
6500 /* 3.3.3 : 2.2 */
6501 attr = node->properties;
6502 while (attr != NULL) {
6503 if (attr->ns == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006504 if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
6505 xmlStrEqual(attr->name, BAD_CAST "name") ||
6506 xmlStrEqual(attr->name, BAD_CAST "id") ||
6507 xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
6508 xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
6509 {
6510 attr = attr->next;
6511 continue;
6512 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006513 xmlSchemaPCustomAttrErr(ctxt,
6514 XML_SCHEMAP_SRC_ELEMENT_2_2,
6515 &repName, (xmlSchemaTypePtr) ret, attr,
6516 "Only the attributes 'minOccurs', 'maxOccurs' and "
6517 "'id' are allowed in addition to 'ref'");
6518 break;
6519 }
6520 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6521 xmlSchemaPIllegalAttrErr(ctxt,
6522 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6523 &repName, (xmlSchemaTypePtr) ret, attr);
6524 }
6525 attr = attr->next;
6526 }
6527 } else {
6528 const xmlChar *ns = NULL, *fixed;
6529
6530 /*
6531 * Parse as an element declaration.
6532 */
6533 if (xmlSchemaPValAttrNode(ctxt,
6534 (xmlChar **) &xmlSchemaElemDesElemDecl, NULL, nameAttr,
6535 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
6536 return (NULL);
6537 /*
6538 * Evaluate the target namespace.
6539 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006540 if (topLevel) {
6541 ns = schema->targetNamespace;
6542 } else {
6543 attr = xmlSchemaGetPropNode(node, "form");
6544 if (attr != NULL) {
6545 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6546 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
William M. Bracke7091952004-05-11 15:09:58 +00006547 ns = schema->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006548 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
6549 xmlSchemaPSimpleTypeErr(ctxt,
6550 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6551 &repName, NULL, (xmlNodePtr) attr,
6552 NULL, "(qualified | unqualified)",
6553 attrValue, NULL, NULL, NULL);
6554 }
6555 } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
6556 ns = schema->targetNamespace;
William M. Brack2f2a6632004-08-20 23:09:47 +00006557 }
6558 ret = xmlSchemaAddElement(ctxt, schema, name, ns, node, topLevel);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006559 if (ret == NULL) {
6560 if (repName != NULL)
6561 xmlFree(repName);
6562 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006563 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006564 ret->type = XML_SCHEMA_TYPE_ELEMENT;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006565 ret->node = node;
6566 ret->targetNamespace = ns;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006567 /*
6568 * Check for illegal attributes.
6569 */
William M. Bracke7091952004-05-11 15:09:58 +00006570 attr = node->properties;
6571 while (attr != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006572 if (attr->ns == NULL) {
6573 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
6574 (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
6575 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6576 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
6577 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
6578 (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006579 (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
6580 {
6581 if (topLevel == 0) {
6582 if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006583 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006584 (!xmlStrEqual(attr->name, BAD_CAST "form")))
6585 {
6586 if (xmlStrEqual(attr->name, BAD_CAST "substitutionGroup")) {
6587 /*
6588 * 3.3.6 : 3 If there is a non-·absent· {substitution
6589 * group affiliation}, then {scope} must be global.
6590 * TODO: This one is redundant, since the S4S does
6591 * prohibit this attribute on local declarations already;
6592 * so why an explicit error code? Weird spec.
6593 * TODO: Move this to the proper constraint layer.
6594 * TODO: Or better wait for spec 1.1 to come.
6595 */
6596 xmlSchemaPIllegalAttrErr(ctxt,
6597 XML_SCHEMAP_E_PROPS_CORRECT_3,
6598 &repName, (xmlSchemaTypePtr) ret, attr);
6599 } else {
6600 xmlSchemaPIllegalAttrErr(ctxt,
6601 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6602 &repName, (xmlSchemaTypePtr) ret, attr);
6603 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006604 }
6605 } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
6606 (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
6607 (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
6608
6609 xmlSchemaPIllegalAttrErr(ctxt,
6610 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6611 &repName, (xmlSchemaTypePtr) ret, attr);
6612 }
6613 }
6614 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6615
6616 xmlSchemaPIllegalAttrErr(ctxt,
6617 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6618 &repName, (xmlSchemaTypePtr) ret, attr);
William M. Bracke7091952004-05-11 15:09:58 +00006619 }
6620 attr = attr->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006621 }
William M. Bracke7091952004-05-11 15:09:58 +00006622 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006623 * Extract/validate attributes.
6624 */
6625 if (topLevel) {
6626 /*
6627 * Process top attributes of global element declarations here.
6628 */
6629 ret->flags |= XML_SCHEMAS_ELEM_GLOBAL;
6630 ret->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
6631 xmlSchemaPValAttrQName(ctxt, schema, &repName,
6632 (xmlSchemaTypePtr) ret, node, "substitutionGroup",
6633 &(ret->substGroupNs), NULL, &(ret->substGroup));
6634 if (xmlGetBooleanProp(ctxt, &repName, (xmlSchemaTypePtr) ret,
6635 node, "abstract", 0))
6636 ret->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
6637 /*
6638 * Attribute "final".
6639 */
6640 attr = xmlSchemaGetPropNode(node, "final");
6641 if (attr == NULL) {
6642 ret->flags |= XML_SCHEMAS_ELEM_FINAL_ABSENT;
6643 } else {
6644 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6645 if (xmlSchemaPValAttrBlockFinal(attrValue, &(ret->flags),
6646 -1,
6647 XML_SCHEMAS_ELEM_FINAL_EXTENSION,
6648 XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
6649 xmlSchemaPSimpleTypeErr(ctxt,
6650 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6651 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00006652 NULL, "(#all | List of (extension | restriction))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00006653 attrValue, NULL, NULL, NULL);
6654 }
6655 }
6656 }
6657 /*
6658 * Attribute "block".
6659 */
6660 attr = xmlSchemaGetPropNode(node, "block");
6661 if (attr == NULL) {
6662 ret->flags |= XML_SCHEMAS_ELEM_BLOCK_ABSENT;
6663 } else {
6664 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6665 if (xmlSchemaPValAttrBlockFinal(attrValue, &(ret->flags),
6666 -1,
6667 XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
6668 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
6669 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
6670 xmlSchemaPSimpleTypeErr(ctxt,
6671 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6672 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00006673 NULL, "(#all | List of (extension | "
Daniel Veillardc0826a72004-08-10 14:17:33 +00006674 "restriction | substitution))", attrValue,
6675 NULL, NULL, NULL);
6676 }
6677 }
6678 if (xmlGetBooleanProp(ctxt, &repName, (xmlSchemaTypePtr) ret,
6679 node, "nillable", 0))
6680 ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006681
Daniel Veillardc0826a72004-08-10 14:17:33 +00006682 xmlSchemaPValAttrQName(ctxt, schema,
6683 &repName, (xmlSchemaTypePtr) ret, node,
6684 "type", &(ret->namedTypeNs), NULL, &(ret->namedType));
Daniel Veillard4255d502002-04-16 15:50:10 +00006685
Daniel Veillardc0826a72004-08-10 14:17:33 +00006686 ret->value = xmlSchemaGetProp(ctxt, node, "default");
6687 attr = xmlSchemaGetPropNode(node, "fixed");
6688 if (attr != NULL) {
6689 fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6690 if (ret->value != NULL) {
6691 /*
6692 * 3.3.3 : 1
6693 * default and fixed must not both be present.
6694 */
6695 xmlSchemaPMutualExclAttrErr(ctxt,
6696 XML_SCHEMAP_SRC_ELEMENT_1,
6697 &repName, (xmlSchemaTypePtr) ret, attr,
6698 "default", "fixed");
6699 } else {
6700 ret->flags |= XML_SCHEMAS_ELEM_FIXED;
6701 ret->value = fixed;
6702 }
6703 }
6704 }
6705 /*
6706 * Extract/validate common attributes.
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006707 */
6708 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6709 node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006710 ret->minOccurs = minOccurs;
6711 ret->maxOccurs = maxOccurs;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006712 if (topLevel != 1)
6713 xmlSchemaPCheckParticleCorrect_2(ctxt, (xmlSchemaTypePtr) ret,
6714 node, minOccurs, maxOccurs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006715 /*
6716 * And now for the children...
6717 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006718 ctxt->container = ret->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006719 child = node->children;
6720 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006721 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6722 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006723 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006724 if (isRef) {
6725 if (child != NULL) {
6726 xmlSchemaPContentErr(ctxt,
6727 XML_SCHEMAP_SRC_ELEMENT_2_2,
6728 &repName, (xmlSchemaTypePtr) ret, node, child,
6729 NULL, "(annotation?)");
William M. Bracke7091952004-05-11 15:09:58 +00006730 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006731 } else {
William M. Bracke7091952004-05-11 15:09:58 +00006732 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006733 /*
6734 * 3.3.3 : 3
6735 * "type" and either <simpleType> or <complexType> are mutually
6736 * exclusive
6737 */
William M. Bracke7091952004-05-11 15:09:58 +00006738 if (ret->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006739 xmlSchemaPContentErr(ctxt,
6740 XML_SCHEMAP_SRC_ELEMENT_3,
6741 &repName, (xmlSchemaTypePtr) ret, node, child,
6742 "The attribute 'type' and the <complexType> child are "
6743 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006744 } else
Daniel Veillard3646d642004-06-02 19:19:14 +00006745 ret->subtypes = xmlSchemaParseComplexType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00006746 child = child->next;
6747 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006748 /*
6749 * 3.3.3 : 3
6750 * "type" and either <simpleType> or <complexType> are
6751 * mutually exclusive
6752 */
William M. Bracke7091952004-05-11 15:09:58 +00006753 if (ret->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006754 xmlSchemaPContentErr(ctxt,
6755 XML_SCHEMAP_SRC_ELEMENT_3,
6756 &repName, (xmlSchemaTypePtr) ret, node, child,
6757 "The attribute 'type' and the <simpleType> child are "
6758 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006759 } else
Daniel Veillard3646d642004-06-02 19:19:14 +00006760 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00006761 child = child->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006762 }
William M. Bracke7091952004-05-11 15:09:58 +00006763 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00006764 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006765#ifdef IDC_ENABLED
6766 if (IS_SCHEMA(child, "unique")) {
6767 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
6768 XML_SCHEMA_TYPE_IDC_UNIQUE, ret->targetNamespace);
6769 } else if (IS_SCHEMA(child, "key")) {
6770 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
6771 XML_SCHEMA_TYPE_IDC_KEY, ret->targetNamespace);
6772 } else if (IS_SCHEMA(child, "keyref")) {
6773 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
6774 XML_SCHEMA_TYPE_IDC_KEYREF, ret->targetNamespace);
6775 }
6776 if (lastIDC != NULL)
6777 lastIDC->next = curIDC;
6778 else
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006779 ret->idcs = (void *) curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006780 lastIDC = curIDC;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006781#else
6782 TODO
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006783#endif
6784 child = child->next;
William M. Bracke7091952004-05-11 15:09:58 +00006785 }
6786 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006787 xmlSchemaPContentErr(ctxt,
6788 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6789 &repName, (xmlSchemaTypePtr) ret, node, child,
6790 NULL, "(annotation?, ((simpleType | complexType)?, "
6791 "(unique | key | keyref)*))");
6792 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006793
Daniel Veillardc0826a72004-08-10 14:17:33 +00006794 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006795 ctxt->container = oldcontainer;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006796 /*
6797 * Cleanup.
6798 */
6799 if (repName != NULL)
6800 xmlFree(repName);
6801 /*
6802 * NOTE: Element Declaration Representation OK 4. will be checked at a
6803 * different layer.
6804 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006805 return (ret);
6806}
6807
6808/**
6809 * xmlSchemaParseUnion:
6810 * @ctxt: a schema validation context
6811 * @schema: the schema being built
6812 * @node: a subtree containing XML Schema informations
6813 *
6814 * parse a XML schema Union definition
6815 * *WARNING* this interface is highly subject to change
6816 *
William M. Bracke7091952004-05-11 15:09:58 +00006817 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00006818 * 1 in case of success.
6819 */
6820static xmlSchemaTypePtr
6821xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006822 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006823{
6824 xmlSchemaTypePtr type, subtype, last = NULL;
6825 xmlNodePtr child = NULL;
6826 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00006827 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006828
6829 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6830 return (NULL);
6831
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006832 snprintf((char *) name, 30, "#union%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00006833 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006834 if (type == NULL)
6835 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00006836 type->type = XML_SCHEMA_TYPE_UNION;
Daniel Veillard4255d502002-04-16 15:50:10 +00006837 type->node = node;
William M. Brack2f2a6632004-08-20 23:09:47 +00006838 /*
6839 * Check for illegal attributes.
6840 */
6841 attr = node->properties;
6842 while (attr != NULL) {
6843 if (attr->ns == NULL) {
6844 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6845 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
6846 xmlSchemaPIllegalAttrErr(ctxt,
6847 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6848 NULL, type, attr);
6849 }
6850 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6851 xmlSchemaPIllegalAttrErr(ctxt,
6852 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6853 NULL, type, attr);
6854 }
6855 attr = attr->next;
6856 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006857 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00006858 /*
6859 * Attribute "memberTypes". This is a list of QNames.
6860 * TODO: Validate the QNames.
6861 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00006862 type->base = xmlSchemaGetProp(ctxt, node, "memberTypes");
William M. Brack2f2a6632004-08-20 23:09:47 +00006863 /*
6864 * And now for the children...
6865 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006866 child = node->children;
6867 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006868 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6869 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006870 }
William M. Brack2f2a6632004-08-20 23:09:47 +00006871 while (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006872 subtype = (xmlSchemaTypePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00006873 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006874 if (subtype != NULL) {
6875 if (last == NULL) {
6876 type->subtypes = subtype;
6877 last = subtype;
6878 } else {
6879 last->next = subtype;
6880 last = subtype;
6881 }
6882 last->next = NULL;
6883 }
6884 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006885 }
6886 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006887 /* TODO: Think about the error code. */
6888 xmlSchemaPContentErr(ctxt,
6889 XML_SCHEMAP_UNKNOWN_UNION_CHILD,
6890 NULL, type, node, child, NULL, "(annotation?, simpleType*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006891 }
6892 return (type);
6893}
6894
6895/**
6896 * xmlSchemaParseList:
6897 * @ctxt: a schema validation context
6898 * @schema: the schema being built
6899 * @node: a subtree containing XML Schema informations
6900 *
6901 * parse a XML schema List definition
6902 * *WARNING* this interface is highly subject to change
6903 *
William M. Bracke7091952004-05-11 15:09:58 +00006904 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00006905 * 1 in case of success.
6906 */
6907static xmlSchemaTypePtr
6908xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006909 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006910{
6911 xmlSchemaTypePtr type, subtype;
6912 xmlNodePtr child = NULL;
6913 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00006914 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006915
6916 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6917 return (NULL);
6918
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006919 snprintf((char *) name, 30, "#list%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00006920 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006921 if (type == NULL)
6922 return (NULL);
6923 type->node = node;
6924 type->type = XML_SCHEMA_TYPE_LIST;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006925 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00006926 /*
6927 * Check for illegal attributes.
6928 */
6929 attr = node->properties;
6930 while (attr != NULL) {
6931 if (attr->ns == NULL) {
6932 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6933 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
6934 xmlSchemaPIllegalAttrErr(ctxt,
6935 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6936 NULL, type, attr);
6937 }
6938 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6939 xmlSchemaPIllegalAttrErr(ctxt,
6940 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6941 NULL, type, attr);
6942 }
6943 attr = attr->next;
6944 }
6945 /*
6946 * Attribute "itemType".
6947 */
6948 xmlSchemaPValAttrQName(ctxt, schema, NULL, NULL,
6949 node, "itemType", &(type->baseNs), NULL, &(type->base));
6950 /*
6951 * And now for the children...
6952 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006953 child = node->children;
6954 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006955 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6956 child = child->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00006957 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006958 subtype = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00006959 if (IS_SCHEMA(child, "simpleType")) {
6960 if (type->base != NULL) {
6961 xmlSchemaPCustomErr(ctxt,
6962 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
6963 NULL, type, node,
6964 "The attribute 'itemType' and the <simpleType> child "
6965 "are mutually exclusive", NULL);
6966 } else {
6967 subtype = (xmlSchemaTypePtr)
6968 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
6969 type->subtypes = subtype;
6970 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00006971 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006972 }
6973 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006974 /* TODO: Think about the error code. */
6975 xmlSchemaPContentErr(ctxt,
6976 XML_SCHEMAP_UNKNOWN_LIST_CHILD,
6977 NULL, type, node, child, NULL, "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006978 }
6979 return (type);
6980}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006981
Daniel Veillard4255d502002-04-16 15:50:10 +00006982/**
6983 * xmlSchemaParseSimpleType:
6984 * @ctxt: a schema validation context
6985 * @schema: the schema being built
6986 * @node: a subtree containing XML Schema informations
6987 *
6988 * parse a XML schema Simple Type definition
6989 * *WARNING* this interface is highly subject to change
6990 *
William M. Bracke7091952004-05-11 15:09:58 +00006991 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardc0826a72004-08-10 14:17:33 +00006992 * 1 in case of success.
Daniel Veillard4255d502002-04-16 15:50:10 +00006993 */
6994static xmlSchemaTypePtr
6995xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00006996 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006997{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006998 xmlSchemaTypePtr type, subtype, oldCtxtType, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00006999 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007000 const xmlChar *attrValue = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007001 xmlChar *des = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007002 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00007003
7004 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7005 return (NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007006
Daniel Veillardc0826a72004-08-10 14:17:33 +00007007 if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007008 attr = xmlSchemaGetPropNode(node, "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007009 if (attr == NULL) {
7010 xmlSchemaPMissingAttrErr(ctxt,
7011 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007012 (xmlChar **) &xmlSchemaElemDesST, NULL, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007013 "name", NULL);
7014 return (NULL);
7015 } else if (xmlSchemaPValAttrNode(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007016 (xmlChar **) &xmlSchemaElemDesST, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007017 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00007018 return (NULL);
7019 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007020 }
7021
7022 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007023 char buf[40];
Daniel Veillardc0826a72004-08-10 14:17:33 +00007024
Daniel Veillard01fa6152004-06-29 17:04:39 +00007025 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007026 * Parse as local simple type definition.
Daniel Veillard01fa6152004-06-29 17:04:39 +00007027 */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00007028 snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007029 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007030 if (type == NULL)
7031 return (NULL);
7032 type->node = node;
7033 type->type = XML_SCHEMA_TYPE_SIMPLE;
7034 /*
7035 * Check for illegal attributes.
7036 */
7037 attr = node->properties;
7038 while (attr != NULL) {
7039 if (attr->ns == NULL) {
7040 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
7041 xmlSchemaPIllegalAttrErr(ctxt,
7042 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007043 &des, type, attr);
Daniel Veillard01fa6152004-06-29 17:04:39 +00007044 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007045 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7046 xmlSchemaPIllegalAttrErr(ctxt,
7047 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007048 &des, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007049 }
7050 attr = attr->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +00007051 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007052 } else {
7053 /*
7054 * Parse as global simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007055 *
7056 * Note that attrValue is the value of the attribute "name" here.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007057 */
William M. Brack2f2a6632004-08-20 23:09:47 +00007058 type = xmlSchemaAddType(ctxt, schema, attrValue, schema->targetNamespace, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007059 if (type == NULL)
7060 return (NULL);
7061 type->node = node;
7062 type->type = XML_SCHEMA_TYPE_SIMPLE;
7063 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
7064 /*
7065 * Check for illegal attributes.
7066 */
7067 attr = node->properties;
7068 while (attr != NULL) {
7069 if (attr->ns == NULL) {
7070 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7071 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007072 (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007073 xmlSchemaPIllegalAttrErr(ctxt,
7074 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007075 &des, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007076 }
7077 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7078 xmlSchemaPIllegalAttrErr(ctxt,
7079 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007080 &des, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007081 }
7082 attr = attr->next;
7083 }
7084 /*
7085 * Attribute "final".
7086 */
7087 attr = xmlSchemaGetPropNode(node, "final");
7088 if (attr == NULL) {
7089 type->flags |= XML_SCHEMAS_TYPE_FINAL_DEFAULT;
7090 } else {
7091 attrValue = xmlSchemaGetProp(ctxt, node, "final");
7092 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
7093 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
7094 XML_SCHEMAS_TYPE_FINAL_LIST,
7095 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
7096
7097 xmlSchemaPSimpleTypeErr(ctxt,
7098 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007099 &des, type, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00007100 NULL, "(#all | List of (list | union | restriction)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00007101 attrValue, NULL, NULL, NULL);
7102 }
7103 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00007104 }
7105 type->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00007106 xmlSchemaPValAttrID(ctxt, NULL, type, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007107 /*
7108 * And now for the children...
7109 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007110 oldCtxtType = ctxt->ctxtType;
7111 oldParentItem = ctxt->parentItem;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007112 ctxt->ctxtType = type;
7113 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00007114 child = node->children;
7115 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007116 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7117 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007118 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007119 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00007120 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007121 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00007122 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007123 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007124 } else if (IS_SCHEMA(child, "list")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007125 subtype = (xmlSchemaTypePtr)
7126 xmlSchemaParseList(ctxt, schema, child);
7127 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007128 } else if (IS_SCHEMA(child, "union")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007129 subtype = (xmlSchemaTypePtr)
7130 xmlSchemaParseUnion(ctxt, schema, child);
7131 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007132 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007133 type->subtypes = subtype;
7134 if ((child != NULL) || (subtype == NULL)) {
7135 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007136 &des, type, node, child, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007137 "(annotation?, (restriction | list | union))");
Daniel Veillard4255d502002-04-16 15:50:10 +00007138 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007139 ctxt->parentItem = oldParentItem;
7140 ctxt->ctxtType = oldCtxtType;
7141 FREE_AND_NULL(des)
Daniel Veillard01fa6152004-06-29 17:04:39 +00007142
Daniel Veillard4255d502002-04-16 15:50:10 +00007143 return (type);
7144}
7145
7146
7147/**
7148 * xmlSchemaParseGroup:
7149 * @ctxt: a schema validation context
7150 * @schema: the schema being built
7151 * @node: a subtree containing XML Schema informations
7152 *
7153 * parse a XML schema Group definition
7154 * *WARNING* this interface is highly subject to change
7155 *
William M. Bracke7091952004-05-11 15:09:58 +00007156 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00007157 * 1 in case of success.
7158 */
7159static xmlSchemaTypePtr
7160xmlSchemaParseGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00007161 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00007162{
7163 xmlSchemaTypePtr type, subtype;
7164 xmlNodePtr child = NULL;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00007165 const xmlChar *name, *ns = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007166 const xmlChar *ref = NULL, *refNs = NULL;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00007167 char buf[50];
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00007168 int minOccurs, maxOccurs;
Daniel Veillard4255d502002-04-16 15:50:10 +00007169
7170 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7171 return (NULL);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00007172 /*
7173 * TODO: Validate the element even if no item is created
7174 * (i.e. min/maxOccurs == 0).
7175 */
7176 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
7177 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(nonNegativeInteger | unbounded)");
7178 if ((minOccurs == 0) && (maxOccurs == 0)) {
7179 return (NULL);
7180 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00007181 if (topLevel)
7182 ns = schema->targetNamespace;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007183 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00007184 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007185 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
7186 if (ref == NULL) {
7187 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007188 XML_SCHEMAP_GROUP_NONAME_NOREF,
7189 "Group definition or particle: One of the attributes \"name\" "
7190 "or \"ref\" must be present.\n", NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007191 return (NULL);
7192 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007193 if (refNs == NULL)
7194 refNs = schema->targetNamespace;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00007195 snprintf(buf, 49, "#grRef%d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007196 name = (const xmlChar *) buf;
Daniel Veillard4255d502002-04-16 15:50:10 +00007197 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00007198 type = xmlSchemaAddGroup(ctxt, schema, name, ns, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007199 if (type == NULL)
7200 return (NULL);
7201 type->node = node;
7202 type->type = XML_SCHEMA_TYPE_GROUP;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00007203 if (topLevel)
7204 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00007205 xmlSchemaPValAttrID(ctxt, NULL, type, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00007206 type->ref = ref;
7207 type->refNs = refNs;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00007208 type->minOccurs = minOccurs;
7209 type->maxOccurs = maxOccurs;
7210 xmlSchemaPCheckParticleCorrect_2(ctxt, type,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007211 node, type->minOccurs, type->maxOccurs);
Daniel Veillard4255d502002-04-16 15:50:10 +00007212
7213 child = node->children;
7214 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007215 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7216 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007217 }
7218 subtype = NULL;
7219 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007220 subtype = (xmlSchemaTypePtr)
7221 xmlSchemaParseAll(ctxt, schema, child);
7222 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007223 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007224 subtype = xmlSchemaParseChoice(ctxt, schema, child);
7225 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007226 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007227 subtype = (xmlSchemaTypePtr)
7228 xmlSchemaParseSequence(ctxt, schema, child);
7229 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007230 }
7231 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007232 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00007233 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007234 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_GROUP_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007235 "Group definition \"%s\" has unexpected content.\n", type->name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007236 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007237 }
7238
7239 return (type);
7240}
7241
7242/**
7243 * xmlSchemaParseAll:
7244 * @ctxt: a schema validation context
7245 * @schema: the schema being built
7246 * @node: a subtree containing XML Schema informations
7247 *
7248 * parse a XML schema All definition
7249 * *WARNING* this interface is highly subject to change
7250 *
William M. Bracke7091952004-05-11 15:09:58 +00007251 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00007252 * 1 in case of success.
7253 */
7254static xmlSchemaTypePtr
7255xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007256 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007257{
7258 xmlSchemaTypePtr type, subtype, last = NULL;
7259 xmlNodePtr child = NULL;
7260 xmlChar name[30];
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00007261 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007262
7263 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7264 return (NULL);
7265
7266
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00007267 snprintf((char *) name, 30, "#all%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007268 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007269 if (type == NULL)
7270 return (NULL);
7271 type->node = node;
Daniel Veillard7646b182002-04-20 06:41:40 +00007272 type->type = XML_SCHEMA_TYPE_ALL;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00007273
7274 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007275
7276 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
7277 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00007278
7279 oldcontainer = ctxt->container;
7280 ctxt->container = (const xmlChar *) name;
Daniel Veillard4255d502002-04-16 15:50:10 +00007281 child = node->children;
7282 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007283 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7284 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007285 }
7286 while (IS_SCHEMA(child, "element")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007287 subtype = (xmlSchemaTypePtr)
7288 xmlSchemaParseElement(ctxt, schema, child, 0);
7289 if (subtype != NULL) {
William M. Brackb15351e2003-12-27 04:34:42 +00007290 if (subtype->minOccurs > 1)
7291 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MINOCCURS,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007292 "invalid value for minOccurs (must be 0 or 1).\n",
William M. Brackb15351e2003-12-27 04:34:42 +00007293 NULL, NULL);
7294 if (subtype->maxOccurs > 1)
7295 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MAXOCCURS,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007296 "invalid value for maxOccurs (must be 0 or 1).\n",
William M. Brackb15351e2003-12-27 04:34:42 +00007297 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007298 if (last == NULL) {
7299 type->subtypes = subtype;
7300 last = subtype;
7301 } else {
7302 last->next = subtype;
7303 last = subtype;
7304 }
7305 last->next = NULL;
7306 }
7307 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007308 }
7309 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007310 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ALL_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007311 "<all> has unexpected content.\n", type->name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007312 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007313 }
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00007314 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007315 return (type);
7316}
7317
7318/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007319 * xmlSchemaCleanupDoc:
7320 * @ctxt: a schema validation context
7321 * @node: the root of the document.
7322 *
7323 * removes unwanted nodes in a schemas document tree
7324 */
7325static void
7326xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
7327{
7328 xmlNodePtr delete, cur;
7329
7330 if ((ctxt == NULL) || (root == NULL)) return;
7331
7332 /*
7333 * Remove all the blank text nodes
7334 */
7335 delete = NULL;
7336 cur = root;
7337 while (cur != NULL) {
7338 if (delete != NULL) {
7339 xmlUnlinkNode(delete);
7340 xmlFreeNode(delete);
7341 delete = NULL;
7342 }
7343 if (cur->type == XML_TEXT_NODE) {
7344 if (IS_BLANK_NODE(cur)) {
7345 if (xmlNodeGetSpacePreserve(cur) != 1) {
7346 delete = cur;
7347 }
7348 }
7349 } else if ((cur->type != XML_ELEMENT_NODE) &&
7350 (cur->type != XML_CDATA_SECTION_NODE)) {
7351 delete = cur;
7352 goto skip_children;
7353 }
7354
7355 /*
7356 * Skip to next node
7357 */
7358 if (cur->children != NULL) {
7359 if ((cur->children->type != XML_ENTITY_DECL) &&
7360 (cur->children->type != XML_ENTITY_REF_NODE) &&
7361 (cur->children->type != XML_ENTITY_NODE)) {
7362 cur = cur->children;
7363 continue;
7364 }
7365 }
7366 skip_children:
7367 if (cur->next != NULL) {
7368 cur = cur->next;
7369 continue;
7370 }
7371
7372 do {
7373 cur = cur->parent;
7374 if (cur == NULL)
7375 break;
7376 if (cur == root) {
7377 cur = NULL;
7378 break;
7379 }
7380 if (cur->next != NULL) {
7381 cur = cur->next;
7382 break;
7383 }
7384 } while (cur != NULL);
7385 }
7386 if (delete != NULL) {
7387 xmlUnlinkNode(delete);
7388 xmlFreeNode(delete);
7389 delete = NULL;
7390 }
7391}
7392
William M. Brack2f2a6632004-08-20 23:09:47 +00007393
7394/**
7395 * xmlSchemaImportSchema
7396 *
7397 * @ctxt: a schema validation context
7398 * @schemaLocation: an URI defining where to find the imported schema
7399 *
7400 * import a XML schema
7401 * *WARNING* this interface is highly subject to change
7402 *
7403 * Returns -1 in case of error and 1 in case of success.
7404 */
7405#if 0
7406static xmlSchemaImportPtr
7407xmlSchemaImportSchema(xmlSchemaParserCtxtPtr ctxt,
7408 const xmlChar *schemaLocation)
7409{
7410 xmlSchemaImportPtr import;
7411 xmlSchemaParserCtxtPtr newctxt;
7412
7413 newctxt = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
7414 if (newctxt == NULL) {
7415 xmlSchemaPErrMemory(ctxt, "allocating schema parser context",
7416 NULL);
7417 return (NULL);
7418 }
7419 memset(newctxt, 0, sizeof(xmlSchemaParserCtxt));
7420 /* Keep the same dictionnary for parsing, really */
7421 xmlDictReference(ctxt->dict);
7422 newctxt->dict = ctxt->dict;
7423 newctxt->includes = 0;
7424 newctxt->URL = xmlDictLookup(newctxt->dict, schemaLocation, -1);
7425
7426 xmlSchemaSetParserErrors(newctxt, ctxt->error, ctxt->warning,
7427 ctxt->userData);
7428
7429 import = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
7430 if (import == NULL) {
7431 xmlSchemaPErrMemory(NULL, "allocating imported schema",
7432 NULL);
7433 xmlSchemaFreeParserCtxt(newctxt);
7434 return (NULL);
7435 }
7436
7437 memset(import, 0, sizeof(xmlSchemaImport));
7438 import->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
7439 import->schema = xmlSchemaParse(newctxt);
7440
7441 if (import->schema == NULL) {
7442 /* FIXME use another error enum here ? */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00007443 xmlSchemaPErr(ctxt, NULL, XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00007444 "Failed to import schema from location \"%s\".\n",
7445 schemaLocation, NULL);
7446
7447 xmlSchemaFreeParserCtxt(newctxt);
7448 /* The schemaLocation is held by the dictionary.
7449 if (import->schemaLocation != NULL)
7450 xmlFree((xmlChar *)import->schemaLocation);
7451 */
7452 xmlFree(import);
7453 return NULL;
7454 }
7455
7456 xmlSchemaFreeParserCtxt(newctxt);
7457 return import;
7458}
7459#endif
7460
7461static void
7462xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
7463{
7464 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
7465 schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
7466
7467 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
7468 schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
7469
7470 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
7471 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
7472 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
7473 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
7474 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
7475 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
7476 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
7477 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
7478
7479 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
7480 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
7481 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
7482 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
7483 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
7484 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
7485}
7486
7487static void
7488xmlSchemaParseSchemaDefaults(xmlSchemaParserCtxtPtr ctxt,
7489 xmlSchemaPtr schema,
7490 xmlNodePtr node)
7491{
7492 xmlAttrPtr attr;
7493 const xmlChar *val;
7494
7495 attr = xmlSchemaGetPropNode(node, "elementFormDefault");
7496 if (attr != NULL) {
7497 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7498 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
7499 XML_SCHEMAS_QUALIF_ELEM) != 0) {
7500 xmlSchemaPSimpleTypeErr(ctxt,
7501 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
7502 NULL, NULL, (xmlNodePtr) attr, NULL,
7503 "(qualified | unqualified)", val, NULL, NULL, NULL);
7504 }
7505 }
7506
7507 attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
7508 if (attr != NULL) {
7509 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7510 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
7511 XML_SCHEMAS_QUALIF_ATTR) != 0) {
7512 xmlSchemaPSimpleTypeErr(ctxt,
7513 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
7514 NULL, NULL, (xmlNodePtr) attr, NULL,
7515 "(qualified | unqualified)", val, NULL, NULL, NULL);
7516 }
7517 }
7518
7519 attr = xmlSchemaGetPropNode(node, "finalDefault");
7520 if (attr != NULL) {
7521 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7522 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
7523 XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
7524 XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
7525 -1,
7526 XML_SCHEMAS_FINAL_DEFAULT_LIST,
7527 XML_SCHEMAS_FINAL_DEFAULT_UNION) != 0) {
7528 xmlSchemaPSimpleTypeErr(ctxt,
7529 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7530 NULL, NULL, (xmlNodePtr) attr, NULL,
7531 "(#all | List of (extension | restriction | list | union))",
7532 val, NULL, NULL, NULL);
7533 }
7534 }
7535
7536 attr = xmlSchemaGetPropNode(node, "blockDefault");
7537 if (attr != NULL) {
7538 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7539 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
7540 XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
7541 XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
7542 XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1) != 0) {
7543 xmlSchemaPSimpleTypeErr(ctxt,
7544 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7545 NULL, NULL, (xmlNodePtr) attr, NULL,
7546 "(#all | List of (extension | restriction | substitution))",
7547 val, NULL, NULL, NULL);
7548 }
7549 }
7550}
7551
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007552/**
7553 * xmlSchemaParseSchemaTopLevel:
7554 * @ctxt: a schema validation context
7555 * @schema: the schemas
7556 * @nodes: the list of top level nodes
7557 *
7558 * Returns the internal XML Schema structure built from the resource or
7559 * NULL in case of error
7560 */
7561static void
7562xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
7563 xmlSchemaPtr schema, xmlNodePtr nodes)
7564{
7565 xmlNodePtr child;
7566 xmlSchemaAnnotPtr annot;
7567
7568 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
7569 return;
7570
7571 child = nodes;
7572 while ((IS_SCHEMA(child, "include")) ||
7573 (IS_SCHEMA(child, "import")) ||
7574 (IS_SCHEMA(child, "redefine")) ||
7575 (IS_SCHEMA(child, "annotation"))) {
7576 if (IS_SCHEMA(child, "annotation")) {
7577 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7578 if (schema->annot == NULL)
7579 schema->annot = annot;
7580 else
7581 xmlSchemaFreeAnnot(annot);
7582 } else if (IS_SCHEMA(child, "import")) {
7583 xmlSchemaParseImport(ctxt, schema, child);
7584 } else if (IS_SCHEMA(child, "include")) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00007585 ctxt->includes++;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007586 xmlSchemaParseInclude(ctxt, schema, child);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00007587 ctxt->includes--;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007588 } else if (IS_SCHEMA(child, "redefine")) {
7589 TODO
7590 }
7591 child = child->next;
7592 }
7593 while (child != NULL) {
7594 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007595 xmlSchemaParseComplexType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007596 child = child->next;
7597 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007598 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007599 child = child->next;
7600 } else if (IS_SCHEMA(child, "element")) {
7601 xmlSchemaParseElement(ctxt, schema, child, 1);
7602 child = child->next;
7603 } else if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00007604 xmlSchemaParseAttribute(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007605 child = child->next;
7606 } else if (IS_SCHEMA(child, "attributeGroup")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007607 xmlSchemaParseAttributeGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007608 child = child->next;
7609 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007610 xmlSchemaParseGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007611 child = child->next;
7612 } else if (IS_SCHEMA(child, "notation")) {
7613 xmlSchemaParseNotation(ctxt, schema, child);
7614 child = child->next;
7615 } else {
7616 xmlSchemaPErr2(ctxt, NULL, child,
7617 XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007618 "Unexpected element \"%s\" as child of <schema>.\n",
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007619 child->name, NULL);
7620 child = child->next;
7621 }
7622 while (IS_SCHEMA(child, "annotation")) {
7623 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7624 if (schema->annot == NULL)
7625 schema->annot = annot;
7626 else
7627 xmlSchemaFreeAnnot(annot);
7628 child = child->next;
7629 }
7630 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00007631 ctxt->parentItem = NULL;
7632 ctxt->ctxtType = NULL;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007633}
7634
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007635static xmlSchemaImportPtr
7636xmlSchemaAddImport(xmlSchemaParserCtxtPtr ctxt,
7637 xmlHashTablePtr *imports,
7638 const xmlChar *nsName)
7639{
7640 xmlSchemaImportPtr ret;
7641
7642 if (*imports == NULL) {
Daniel Veillardb9e2f262005-01-23 23:48:34 +00007643 *imports = xmlHashCreateDict(10, ctxt->dict);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007644 if (*imports == NULL) {
7645 xmlSchemaPCustomErr(ctxt,
7646 XML_SCHEMAP_FAILED_BUILD_IMPORT,
7647 NULL, NULL, (xmlNodePtr) ctxt->doc,
7648 "Internal error: failed to build the import table",
7649 NULL);
7650 return (NULL);
7651 }
7652 }
7653 ret = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
7654 if (ret == NULL) {
7655 xmlSchemaPErrMemory(NULL, "allocating import struct", NULL);
7656 return (NULL);
7657 }
7658 memset(ret, 0, sizeof(xmlSchemaImport));
7659 if (nsName == NULL)
7660 nsName = XML_SCHEMAS_NO_NAMESPACE;
7661 xmlHashAddEntry(*imports, nsName, ret);
7662
7663 return (ret);
7664}
7665
7666static int
7667xmlSchemaAcquireSchemaDoc(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007668 xmlSchemaPtr schema,
7669 xmlNodePtr node,
7670 const xmlChar *nsName,
7671 const xmlChar *location,
7672 xmlDocPtr *doc,
7673 const xmlChar **targetNamespace,
7674 int absolute)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007675{
7676 xmlParserCtxtPtr parserCtxt;
7677 xmlSchemaImportPtr import;
7678 const xmlChar *ns;
7679 xmlNodePtr root;
7680
7681 /*
7682 * NOTE: This will be used for <import>, <xsi:schemaLocation> and
7683 * <xsi:noNamespaceSchemaLocation>.
7684 */
7685 *doc = NULL;
7686 /*
7687 * Given that the schemaLocation [attribute] is only a hint, it is open
7688 * to applications to ignore all but the first <import> for a given
7689 * namespace, regardless of the ·actual value· of schemaLocation, but
7690 * such a strategy risks missing useful information when new
7691 * schemaLocations are offered.
7692 *
7693 * XSV (ver 2.5-2) does use the first <import> which resolves to a valid schema.
7694 * Xerces-J (ver 2.5.1) ignores all but the first given <import> - regardless if
7695 * valid or not.
7696 * We will follow XSV here.
7697 */
7698 if (location == NULL) {
7699 /*
7700 * Schema Document Location Strategy:
7701 *
7702 * 3 Based on the namespace name, identify an existing schema document,
7703 * either as a resource which is an XML document or a <schema> element
7704 * information item, in some local schema repository;
7705 *
7706 * 5 Attempt to resolve the namespace name to locate such a resource.
7707 *
7708 * NOTE: Those stategies are not supported, so we will skip.
7709 */
7710 return (0);
7711 }
7712 if (nsName == NULL)
7713 ns = XML_SCHEMAS_NO_NAMESPACE;
7714 else
7715 ns = nsName;
7716
7717 import = xmlHashLookup(schema->schemasImports, ns);
7718 if (import != NULL) {
7719 /*
7720 * There was a valid resource for the specified namespace already
7721 * defined, so skip.
7722 * TODO: This might be changed someday to allow import of
7723 * components from multiple documents for a single target namespace.
7724 */
7725 return (0);
7726 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007727
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007728 /*
7729 * Schema Document Location Strategy:
7730 *
7731 * 2 Based on the location URI, identify an existing schema document,
7732 * either as a resource which is an XML document or a <schema> element
7733 * information item, in some local schema repository;
7734 *
7735 * 4 Attempt to resolve the location URI, to locate a resource on the
7736 * web which is or contains or references a <schema> element;
7737 * TODO: Hmm, I don't know if the reference stuff in 4. will work.
7738 *
7739 */
7740 if ((absolute == 0) && (node != NULL)) {
7741 xmlChar *base, *URI;
7742
7743 base = xmlNodeGetBase(node->doc, node);
7744 if (base == NULL) {
7745 URI = xmlBuildURI(location, node->doc->URL);
7746 } else {
7747 URI = xmlBuildURI(location, base);
7748 xmlFree(base);
7749 }
7750 if (URI != NULL) {
7751 location = xmlDictLookup(ctxt->dict, URI, -1);
7752 xmlFree(URI);
7753 }
7754 }
7755 parserCtxt = xmlNewParserCtxt();
7756 if (parserCtxt == NULL) {
7757 xmlSchemaPErrMemory(NULL, "xmlSchemaParseImport: "
7758 "allocating a parser context", NULL);
7759 return(-1);
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00007760 }
7761
7762 if ((ctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
7763 xmlDictFree(parserCtxt->dict);
7764 parserCtxt->dict = ctxt->dict;
7765 xmlDictReference(parserCtxt->dict);
7766 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007767
7768 *doc = xmlCtxtReadFile(parserCtxt, (const char *) location,
7769 NULL, SCHEMAS_PARSE_OPTIONS);
7770
7771 /*
7772 * 2.1 The referent is (a fragment of) a resource which is an
7773 * XML document (see clause 1.1), which in turn corresponds to
7774 * a <schema> element information item in a well-formed information
7775 * set, which in turn corresponds to a valid schema.
7776 * TODO: What to do with the "fragment" stuff?
7777 *
7778 * 2.2 The referent is a <schema> element information item in
7779 * a well-formed information set, which in turn corresponds
7780 * to a valid schema.
7781 * NOTE: 2.2 won't apply, since only XML documents will be processed
7782 * here.
7783 */
7784 if (*doc == NULL) {
7785 xmlErrorPtr lerr;
7786 /*
7787 * It is *not* an error for the application schema reference
7788 * strategy to fail.
7789 *
7790 * If the doc is NULL and the parser error is an IO error we
7791 * will assume that the resource could not be located or accessed.
7792 *
7793 * TODO: Try to find specific error codes to react only on
7794 * localisation failures.
7795 *
7796 * TODO, FIXME: Check the spec: is a namespace added to the imported
7797 * namespaces, even if the schemaLocation did not provide
7798 * a resource? I guess so, since omitting the "schemaLocation"
7799 * attribute, imports a namespace as well.
7800 */
7801 lerr = xmlGetLastError();
7802 if ((lerr != NULL) && (lerr->domain == XML_FROM_IO)) {
7803 xmlFreeParserCtxt(parserCtxt);
7804 return(0);
7805 }
7806
7807 xmlSchemaPCustomErr(ctxt,
7808 XML_SCHEMAP_SRC_IMPORT_2_1,
7809 NULL, NULL, node,
7810 "Failed to parse the resource '%s' for import",
7811 location);
7812 xmlFreeParserCtxt(parserCtxt);
7813 return(XML_SCHEMAP_SRC_IMPORT_2_1);
7814 }
7815 xmlFreeParserCtxt(parserCtxt);
7816
7817 root = xmlDocGetRootElement(*doc);
7818 if (root == NULL) {
7819 xmlSchemaPCustomErr(ctxt,
7820 XML_SCHEMAP_SRC_IMPORT_2_1,
7821 NULL, NULL, node,
7822 "The XML document '%s' to be imported has no document "
7823 "element", location);
7824 xmlFreeDoc(*doc);
7825 *doc = NULL;
7826 return (XML_SCHEMAP_SRC_IMPORT_2_1);
7827 }
7828
7829 xmlSchemaCleanupDoc(ctxt, root);
7830
7831 if (!IS_SCHEMA(root, "schema")) {
7832 xmlSchemaPCustomErr(ctxt,
7833 XML_SCHEMAP_SRC_IMPORT_2_1,
7834 NULL, NULL, node,
7835 "The XML document '%s' to be imported is not a XML schema document",
7836 location);
7837 xmlFreeDoc(*doc);
7838 *doc = NULL;
7839 return (XML_SCHEMAP_SRC_IMPORT_2_1);
7840 }
7841 *targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
7842 /*
7843 * Schema Representation Constraint: Import Constraints and Semantics
7844 */
7845 if (nsName == NULL) {
7846 if (*targetNamespace != NULL) {
7847 xmlSchemaPCustomErr(ctxt,
7848 XML_SCHEMAP_SRC_IMPORT_3_2,
7849 NULL, NULL, node,
7850 "The XML schema to be imported is not expected "
7851 "to have a target namespace; this differs from "
7852 "its target namespace of '%s'", *targetNamespace);
7853 xmlFreeDoc(*doc);
7854 *doc = NULL;
7855 return (XML_SCHEMAP_SRC_IMPORT_3_2);
7856 }
7857 } else {
7858 if (*targetNamespace == NULL) {
7859 xmlSchemaPCustomErr(ctxt,
7860 XML_SCHEMAP_SRC_IMPORT_3_1,
7861 NULL, NULL, node,
7862 "The XML schema to be imported is expected to have a target "
7863 "namespace of '%s'", nsName);
7864 xmlFreeDoc(*doc);
7865 *doc = NULL;
7866 return (XML_SCHEMAP_SRC_IMPORT_3_1);
7867 } else if (!xmlStrEqual(*targetNamespace, nsName)) {
7868 xmlSchemaPCustomErrExt(ctxt,
7869 XML_SCHEMAP_SRC_IMPORT_3_1,
7870 NULL, NULL, node,
7871 "The XML schema to be imported is expected to have a "
7872 "target namespace of '%s'; this differs from "
7873 "its target namespace of '%s'",
7874 nsName, *targetNamespace, NULL);
7875 xmlFreeDoc(*doc);
7876 *doc = NULL;
7877 return (XML_SCHEMAP_SRC_IMPORT_3_1);
7878 }
7879 }
7880
7881 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports), nsName);
7882 if (import == NULL) {
7883 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT,
7884 NULL, NULL, NULL,
7885 "Internal error: xmlSchemaAcquireSchemaDoc, "
7886 "failed to build import table", NULL);
7887 xmlFreeDoc(*doc);
7888 *doc = NULL;
7889 return (-1);
7890 }
7891 import->schemaLocation = location;
7892 import->doc = *doc;
7893 return (0);
7894}
William M. Brack2f2a6632004-08-20 23:09:47 +00007895
7896/**
7897 * xmlSchemaParseImport:
7898 * @ctxt: a schema validation context
7899 * @schema: the schema being built
7900 * @node: a subtree containing XML Schema informations
7901 *
7902 * parse a XML schema Import definition
7903 * *WARNING* this interface is highly subject to change
7904 *
7905 * Returns 0 in case of success, a positive error code if
7906 * not valid and -1 in case of an internal error.
7907 */
7908static int
7909xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
7910 xmlNodePtr node)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007911{
7912 xmlNodePtr child;
7913 const xmlChar *namespace = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00007914 const xmlChar *schemaLocation = NULL;
7915 const xmlChar *targetNamespace, *oldTNS, *url;
7916 xmlAttrPtr attr;
7917 xmlDocPtr doc;
7918 xmlNodePtr root;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007919 int flags, ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00007920
7921
7922 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7923 return (-1);
7924
7925 /*
7926 * Check for illegal attributes.
7927 */
7928 attr = node->properties;
7929 while (attr != NULL) {
7930 if (attr->ns == NULL) {
7931 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7932 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
7933 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
7934 xmlSchemaPIllegalAttrErr(ctxt,
7935 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7936 NULL, NULL, attr);
7937 }
7938 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7939 xmlSchemaPIllegalAttrErr(ctxt,
7940 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7941 NULL, NULL, attr);
7942 }
7943 attr = attr->next;
7944 }
7945 /*
7946 * Extract and validate attributes.
7947 */
7948 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
7949 "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
7950 &namespace) != 0) {
7951 xmlSchemaPSimpleTypeErr(ctxt,
7952 XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI,
7953 NULL, NULL, node,
7954 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
7955 NULL, namespace, NULL, NULL, NULL);
7956 return (XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI);
7957 }
7958
7959 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
7960 "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
7961 &schemaLocation) != 0) {
7962 xmlSchemaPSimpleTypeErr(ctxt,
7963 XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI,
7964 NULL, NULL, node,
7965 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
7966 NULL, namespace, NULL, NULL, NULL);
7967 return (XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI);
7968 }
7969 /*
7970 * And now for the children...
7971 */
7972 child = node->children;
7973 if (IS_SCHEMA(child, "annotation")) {
7974 /*
7975 * the annotation here is simply discarded ...
7976 */
7977 child = child->next;
7978 }
7979 if (child != NULL) {
7980 xmlSchemaPContentErr(ctxt,
7981 XML_SCHEMAP_UNKNOWN_IMPORT_CHILD,
7982 NULL, NULL, node, child, NULL,
7983 "(annotation?)");
7984 }
7985 /*
7986 * Apply additional constraints.
7987 */
7988 if (namespace != NULL) {
7989 /*
7990 * 1.1 If the namespace [attribute] is present, then its ·actual value·
7991 * must not match the ·actual value· of the enclosing <schema>'s
7992 * targetNamespace [attribute].
7993 */
7994 if (xmlStrEqual(schema->targetNamespace, namespace)) {
7995 xmlSchemaPCustomErr(ctxt,
7996 XML_SCHEMAP_SRC_IMPORT_1_1,
7997 NULL, NULL, node,
7998 "The value of the attribute 'namespace' must not match "
7999 "the target namespace '%s' of the importing schema",
8000 schema->targetNamespace);
8001 return (XML_SCHEMAP_SRC_IMPORT_1_1);
8002 }
8003 } else {
8004 /*
8005 * 1.2 If the namespace [attribute] is not present, then the enclosing
8006 * <schema> must have a targetNamespace [attribute].
8007 */
8008 if (schema->targetNamespace == NULL) {
8009 xmlSchemaPCustomErr(ctxt,
8010 XML_SCHEMAP_SRC_IMPORT_1_2,
8011 NULL, NULL, node,
8012 "The attribute 'namespace' must be existent if "
8013 "the importing schema has no target namespace",
8014 NULL);
8015 return (XML_SCHEMAP_SRC_IMPORT_1_2);
8016 }
8017 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008018 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008019 * Locate and aquire the schema document.
William M. Brack2f2a6632004-08-20 23:09:47 +00008020 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008021 ret = xmlSchemaAcquireSchemaDoc(ctxt, schema, node, namespace,
8022 schemaLocation, &doc, &targetNamespace, 0);
8023 if (ret != 0) {
8024 if (doc != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00008025 xmlFreeDoc(doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008026 return (ret);
8027 } else if (doc != NULL) {
8028 /*
8029 * Save and reset the context & schema.
8030 */
8031 url = ctxt->URL;
8032 /* TODO: Is using the doc->URL here correct? */
8033 ctxt->URL = doc->URL;
8034 flags = schema->flags;
8035 oldTNS = schema->targetNamespace;
8036 /*
8037 * Parse the schema.
8038 */
8039 root = xmlDocGetRootElement(doc);
8040 xmlSchemaClearSchemaDefaults(schema);
8041 xmlSchemaParseSchemaDefaults(ctxt, schema, root);
8042 schema->targetNamespace = targetNamespace;
8043 xmlSchemaParseSchemaTopLevel(ctxt, schema, root->children);
8044 /*
8045 * Restore the context & schema.
8046 */
8047 schema->flags = flags;
8048 schema->targetNamespace = oldTNS;
8049 ctxt->URL = url;
William M. Brack2f2a6632004-08-20 23:09:47 +00008050 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008051
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008052 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +00008053}
8054
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008055/**
8056 * xmlSchemaParseInclude:
8057 * @ctxt: a schema validation context
8058 * @schema: the schema being built
8059 * @node: a subtree containing XML Schema informations
8060 *
8061 * parse a XML schema Include definition
8062 *
William M. Bracke7091952004-05-11 15:09:58 +00008063 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008064 * 1 in case of success.
8065 */
8066static int
8067xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
8068 xmlNodePtr node)
8069{
8070 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008071 const xmlChar *schemaLocation, *targetNamespace;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008072 xmlDocPtr doc;
8073 xmlNodePtr root;
8074 xmlSchemaIncludePtr include;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008075 int wasConvertingNs = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00008076 xmlAttrPtr attr;
8077 int saveFlags;
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00008078 xmlParserCtxtPtr parserCtxt;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008079
8080
8081 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8082 return (-1);
8083
8084 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00008085 * Check for illegal attributes.
8086 */
8087 attr = node->properties;
8088 while (attr != NULL) {
8089 if (attr->ns == NULL) {
8090 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8091 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
8092 xmlSchemaPIllegalAttrErr(ctxt,
8093 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8094 NULL, NULL, attr);
8095 }
8096 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8097 xmlSchemaPIllegalAttrErr(ctxt,
8098 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8099 NULL, NULL, attr);
8100 }
8101 attr = attr->next;
8102 }
8103 /*
8104 * Extract and validate attributes.
8105 */
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00008106 xmlSchemaPValAttrID(ctxt, NULL, NULL,
8107 node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00008108 /*
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008109 * Preliminary step, extract the URI-Reference for the include and
8110 * make an URI from the base.
8111 */
William M. Brack2f2a6632004-08-20 23:09:47 +00008112 attr = xmlSchemaGetPropNode(node, "schemaLocation");
8113 if (attr != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008114 xmlChar *base = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00008115 xmlChar *uri = NULL;
8116
8117 if (xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
8118 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &schemaLocation) != 0)
8119 return (-1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008120 base = xmlNodeGetBase(node->doc, node);
8121 if (base == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008122 uri = xmlBuildURI(schemaLocation, node->doc->URL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008123 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00008124 uri = xmlBuildURI(schemaLocation, base);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008125 xmlFree(base);
8126 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008127 if (uri != NULL) {
8128 schemaLocation = xmlDictLookup(ctxt->dict, uri, -1);
8129 xmlFree(uri);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008130 }
8131 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00008132 xmlSchemaPMissingAttrErr(ctxt,
8133 XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI,
8134 NULL, NULL, node, "schemaLocation", NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008135 return (-1);
8136 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008137 /*
8138 * And now for the children...
8139 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008140 child = node->children;
8141 while (IS_SCHEMA(child, "annotation")) {
8142 /*
8143 * the annotations here are simply discarded ...
8144 */
8145 child = child->next;
8146 }
8147 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008148 xmlSchemaPContentErr(ctxt,
8149 XML_SCHEMAP_UNKNOWN_INCLUDE_CHILD,
8150 NULL, NULL, node, child, NULL,
8151 "(annotation?)");
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008152 }
8153
8154 /*
8155 * First step is to parse the input document into an DOM/Infoset
8156 */
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00008157 /*
8158 * TODO: Use xmlCtxtReadFile to share the dictionary.
8159 */
8160 parserCtxt = xmlNewParserCtxt();
8161 if (parserCtxt == NULL) {
8162 xmlSchemaPErrMemory(NULL, "xmlSchemaParseInclude: "
8163 "allocating a parser context", NULL);
8164 return(-1);
8165 }
8166
8167 if ((ctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
8168 xmlDictFree(parserCtxt->dict);
8169 parserCtxt->dict = ctxt->dict;
8170 xmlDictReference(parserCtxt->dict);
8171 }
8172
8173 doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
8174 NULL, SCHEMAS_PARSE_OPTIONS);
8175 xmlFreeParserCtxt(parserCtxt);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008176 if (doc == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008177 /*
8178 * TODO: It is not an error for the ·actual value· of the
8179 * schemaLocation [attribute] to fail to resolve it all, in which
8180 * case no corresponding inclusion is performed.
8181 * So do we need a warning report here?
8182 */
8183 xmlSchemaPCustomErr(ctxt,
8184 XML_SCHEMAP_FAILED_LOAD,
8185 NULL, NULL, node,
8186 "Failed to load the document '%s' for inclusion", schemaLocation);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008187 return(-1);
8188 }
8189
8190 /*
8191 * Then extract the root of the schema
8192 */
8193 root = xmlDocGetRootElement(doc);
8194 if (root == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008195 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008196 XML_SCHEMAP_NOROOT,
William M. Brack2f2a6632004-08-20 23:09:47 +00008197 NULL, NULL, node,
8198 "The included document '%s' has no document "
8199 "element", schemaLocation);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008200 xmlFreeDoc(doc);
8201 return (-1);
8202 }
8203
8204 /*
8205 * Remove all the blank text nodes
8206 */
8207 xmlSchemaCleanupDoc(ctxt, root);
8208
8209 /*
8210 * Check the schemas top level element
8211 */
8212 if (!IS_SCHEMA(root, "schema")) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008213 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008214 XML_SCHEMAP_NOT_SCHEMA,
William M. Brack2f2a6632004-08-20 23:09:47 +00008215 NULL, NULL, node,
8216 "The document '%s' to be included is not a schema document",
8217 schemaLocation);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008218 xmlFreeDoc(doc);
8219 return (-1);
8220 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008221
William M. Brack2f2a6632004-08-20 23:09:47 +00008222 targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008223 /*
8224 * 2.1 SII has a targetNamespace [attribute], and its ·actual
8225 * value· is identical to the ·actual value· of the targetNamespace
8226 * [attribute] of SIIÂ’ (which must have such an [attribute]).
8227 */
8228 if (targetNamespace != NULL) {
8229 if (schema->targetNamespace == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008230 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008231 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00008232 NULL, NULL, node,
8233 "The target namespace of the included schema "
8234 "'%s' has to be absent, since the including schema "
8235 "has no target namespace",
8236 schemaLocation);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008237 xmlFreeDoc(doc);
8238 return (-1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008239 } else if (!xmlStrEqual(targetNamespace, schema->targetNamespace)) {
8240 xmlSchemaPCustomErrExt(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008241 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00008242 NULL, NULL, node,
8243 "The target namespace '%s' of the included schema '%s' "
8244 "differs from '%s' of the including schema",
8245 targetNamespace, schemaLocation, schema->targetNamespace);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008246 xmlFreeDoc(doc);
8247 return (-1);
8248 }
8249 } else if (schema->targetNamespace != NULL) {
8250 if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
8251 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
8252 } else
8253 wasConvertingNs = 1;
8254 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008255 /*
8256 * register the include
8257 */
8258 include = (xmlSchemaIncludePtr) xmlMalloc(sizeof(xmlSchemaInclude));
8259 if (include == NULL) {
8260 xmlSchemaPErrMemory(ctxt, "allocating included schema", NULL);
8261 xmlFreeDoc(doc);
8262 return (-1);
8263 }
8264
8265 memset(include, 0, sizeof(xmlSchemaInclude));
8266 include->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
8267 include->doc = doc;
8268 include->next = schema->includes;
8269 schema->includes = include;
8270
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008271 /*
8272 * parse the declarations in the included file like if they
8273 * were in the original file.
Daniel Veillardc0826a72004-08-10 14:17:33 +00008274 */
8275 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00008276 * TODO: The complete validation of the <schema> element is not done.
Daniel Veillardc0826a72004-08-10 14:17:33 +00008277 */
William M. Brack2f2a6632004-08-20 23:09:47 +00008278 /*
8279 * The default values ("blockDefault", "elementFormDefault", etc.)
8280 * are set to the values of the included schema and restored afterwards.
8281 */
8282 saveFlags = schema->flags;
8283 xmlSchemaClearSchemaDefaults(schema);
8284 xmlSchemaParseSchemaDefaults(ctxt, schema, root);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008285 xmlSchemaParseSchemaTopLevel(ctxt, schema, root->children);
William M. Brack2f2a6632004-08-20 23:09:47 +00008286 schema->flags = saveFlags;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008287 /*
8288 * Remove the converting flag.
8289 */
William M. Brack2f2a6632004-08-20 23:09:47 +00008290 if ((wasConvertingNs == 0) &&
8291 (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS))
Daniel Veillardc0826a72004-08-10 14:17:33 +00008292 schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008293 return (1);
8294}
8295
8296/**
Daniel Veillard4255d502002-04-16 15:50:10 +00008297 * xmlSchemaParseChoice:
8298 * @ctxt: a schema validation context
8299 * @schema: the schema being built
8300 * @node: a subtree containing XML Schema informations
8301 *
8302 * parse a XML schema Choice definition
8303 * *WARNING* this interface is highly subject to change
8304 *
William M. Bracke7091952004-05-11 15:09:58 +00008305 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00008306 * 1 in case of success.
8307 */
8308static xmlSchemaTypePtr
8309xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008310 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008311{
8312 xmlSchemaTypePtr type, subtype, last = NULL;
8313 xmlNodePtr child = NULL;
8314 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00008315 xmlAttrPtr attr;
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00008316 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00008317
8318 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8319 return (NULL);
8320
8321
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008322 snprintf((char *) name, 30, "#ch%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008323 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00008324 if (type == NULL)
8325 return (NULL);
8326 type->node = node;
8327 type->type = XML_SCHEMA_TYPE_CHOICE;
William M. Brack2f2a6632004-08-20 23:09:47 +00008328 /*
8329 * Check for illegal attributes.
8330 */
8331 attr = node->properties;
8332 while (attr != NULL) {
8333 if (attr->ns == NULL) {
8334 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8335 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
8336 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
8337 xmlSchemaPIllegalAttrErr(ctxt,
8338 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8339 NULL, type, attr);
8340 }
8341 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8342 xmlSchemaPIllegalAttrErr(ctxt,
8343 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8344 NULL, type, attr);
8345 }
8346 attr = attr->next;
8347 }
8348 /*
8349 * Extract and validate attributes.
8350 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00008351 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008352 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
8353 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
8354 "(nonNegativeInteger | unbounded)");
William M. Brack2f2a6632004-08-20 23:09:47 +00008355 /*
8356 * And now for the children...
8357 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00008358 oldcontainer = ctxt->container;
8359 ctxt->container = (const xmlChar *) name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008360 child = node->children;
8361 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008362 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8363 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008364 }
8365 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008366 (IS_SCHEMA(child, "group")) ||
8367 (IS_SCHEMA(child, "any")) ||
8368 (IS_SCHEMA(child, "choice")) ||
8369 (IS_SCHEMA(child, "sequence"))) {
8370 subtype = NULL;
8371 if (IS_SCHEMA(child, "element")) {
8372 subtype = (xmlSchemaTypePtr)
8373 xmlSchemaParseElement(ctxt, schema, child, 0);
8374 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008375 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008376 } else if (IS_SCHEMA(child, "any")) {
8377 subtype = xmlSchemaParseAny(ctxt, schema, child);
8378 } else if (IS_SCHEMA(child, "sequence")) {
8379 subtype = xmlSchemaParseSequence(ctxt, schema, child);
8380 } else if (IS_SCHEMA(child, "choice")) {
8381 subtype = xmlSchemaParseChoice(ctxt, schema, child);
8382 }
8383 if (subtype != NULL) {
8384 if (last == NULL) {
8385 type->subtypes = subtype;
8386 last = subtype;
8387 } else {
8388 last->next = subtype;
8389 last = subtype;
8390 }
8391 last->next = NULL;
8392 }
8393 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008394 }
8395 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008396 /* TODO: error code. */
8397 xmlSchemaPContentErr(ctxt,
8398 XML_SCHEMAP_UNKNOWN_CHOICE_CHILD,
8399 NULL, type, node, child, NULL,
8400 "(annotation?, (element | group | choice | sequence | any)*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00008401 }
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00008402 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00008403 return (type);
8404}
8405
8406/**
8407 * xmlSchemaParseSequence:
8408 * @ctxt: a schema validation context
8409 * @schema: the schema being built
8410 * @node: a subtree containing XML Schema informations
8411 *
8412 * parse a XML schema Sequence definition
8413 * *WARNING* this interface is highly subject to change
8414 *
William M. Bracke7091952004-05-11 15:09:58 +00008415 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00008416 * 1 in case of success.
8417 */
8418static xmlSchemaTypePtr
8419xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008420 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008421{
8422 xmlSchemaTypePtr type, subtype, last = NULL;
8423 xmlNodePtr child = NULL;
8424 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00008425 xmlAttrPtr attr;
8426 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00008427
8428 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8429 return (NULL);
8430
William M. Brack2f2a6632004-08-20 23:09:47 +00008431 oldcontainer = ctxt->container;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008432 snprintf((char *) name, 30, "#seq%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008433 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00008434 if (type == NULL)
8435 return (NULL);
8436 type->node = node;
8437 type->type = XML_SCHEMA_TYPE_SEQUENCE;
William M. Brack2f2a6632004-08-20 23:09:47 +00008438 /*
8439 * Check for illegal attributes.
8440 */
8441 attr = node->properties;
8442 while (attr != NULL) {
8443 if (attr->ns == NULL) {
8444 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8445 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
8446 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
8447 xmlSchemaPIllegalAttrErr(ctxt,
8448 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8449 NULL, type, attr);
8450 }
8451 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8452 xmlSchemaPIllegalAttrErr(ctxt,
8453 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8454 NULL, type, attr);
8455 }
8456 attr = attr->next;
8457 }
8458 /*
8459 * Extract and validate attributes.
8460 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00008461 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008462 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
8463 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
8464 "(nonNegativeInteger | unbounded)");
William M. Brack2f2a6632004-08-20 23:09:47 +00008465 /*
8466 * And now for the children...
8467 */
8468 ctxt->container = (const xmlChar *) name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008469 child = node->children;
8470 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008471 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8472 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008473 }
8474 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008475 (IS_SCHEMA(child, "group")) ||
8476 (IS_SCHEMA(child, "any")) ||
8477 (IS_SCHEMA(child, "choice")) ||
8478 (IS_SCHEMA(child, "sequence"))) {
8479 subtype = NULL;
8480 if (IS_SCHEMA(child, "element")) {
8481 subtype = (xmlSchemaTypePtr)
8482 xmlSchemaParseElement(ctxt, schema, child, 0);
8483 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008484 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008485 } else if (IS_SCHEMA(child, "any")) {
8486 subtype = xmlSchemaParseAny(ctxt, schema, child);
8487 } else if (IS_SCHEMA(child, "choice")) {
8488 subtype = xmlSchemaParseChoice(ctxt, schema, child);
8489 } else if (IS_SCHEMA(child, "sequence")) {
8490 subtype = xmlSchemaParseSequence(ctxt, schema, child);
8491 }
8492 if (subtype != NULL) {
8493 if (last == NULL) {
8494 type->subtypes = subtype;
8495 last = subtype;
8496 } else {
8497 last->next = subtype;
8498 last = subtype;
8499 }
8500 last->next = NULL;
8501 }
8502 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008503 }
8504 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008505 xmlSchemaPContentErr(ctxt,
8506 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
8507 NULL, type, node, child, NULL,
8508 "(annotation?, (element | group | choice | sequence | any)*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00008509 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008510 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00008511
8512 return (type);
8513}
8514
8515/**
8516 * xmlSchemaParseRestriction:
8517 * @ctxt: a schema validation context
8518 * @schema: the schema being built
8519 * @node: a subtree containing XML Schema informations
Daniel Veillard4255d502002-04-16 15:50:10 +00008520 *
8521 * parse a XML schema Restriction definition
8522 * *WARNING* this interface is highly subject to change
8523 *
8524 * Returns the type definition or NULL in case of error
8525 */
8526static xmlSchemaTypePtr
8527xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00008528 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008529{
Daniel Veillard01fa6152004-06-29 17:04:39 +00008530 xmlSchemaTypePtr type, subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00008531 xmlNodePtr child = NULL;
8532 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008533 const xmlChar *oldcontainer;
William M. Brack2f2a6632004-08-20 23:09:47 +00008534 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00008535
8536 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8537 return (NULL);
8538
8539 oldcontainer = ctxt->container;
8540
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008541 snprintf((char *) name, 30, "#restr%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008542 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00008543 if (type == NULL)
8544 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00008545 type->type = XML_SCHEMA_TYPE_RESTRICTION;
Daniel Veillard4255d502002-04-16 15:50:10 +00008546 type->node = node;
William M. Brack2f2a6632004-08-20 23:09:47 +00008547 /*
8548 * Check for illegal attributes.
8549 */
8550 attr = node->properties;
8551 while (attr != NULL) {
8552 if (attr->ns == NULL) {
8553 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8554 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
8555 xmlSchemaPIllegalAttrErr(ctxt,
8556 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8557 NULL, type, attr);
8558 }
8559 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8560 xmlSchemaPIllegalAttrErr(ctxt,
8561 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8562 NULL, type, attr);
8563 }
8564 attr = attr->next;
8565 }
8566 /*
8567 * Extract and validate attributes.
8568 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00008569 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00008570 /*
8571 * Attribute "base".
8572 */
Daniel Veillard4255d502002-04-16 15:50:10 +00008573 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
Daniel Veillard01fa6152004-06-29 17:04:39 +00008574 if ((type->base == NULL) &&
William M. Brack2f2a6632004-08-20 23:09:47 +00008575 (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX)) {
8576 /* TODO: Think about the error code. */
8577 xmlSchemaPMissingAttrErr(ctxt,
8578 XML_SCHEMAP_RESTRICTION_NONAME_NOREF,
8579 NULL, type, node, "base", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008580 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008581 /*
8582 * And now for the children...
8583 */
Daniel Veillard4255d502002-04-16 15:50:10 +00008584 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008585 child = node->children;
8586 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008587 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8588 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008589 }
8590 subtype = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008591 if (ctxt->parentItem->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
8592 if (IS_SCHEMA(child, "all")) {
8593 subtype = (xmlSchemaTypePtr)
8594 xmlSchemaParseAll(ctxt, schema, child);
8595 child = child->next;
8596 type->subtypes = subtype;
8597 } else if (IS_SCHEMA(child, "choice")) {
8598 subtype = xmlSchemaParseChoice(ctxt, schema, child);
8599 child = child->next;
8600 type->subtypes = subtype;
8601 } else if (IS_SCHEMA(child, "sequence")) {
8602 subtype = (xmlSchemaTypePtr)
8603 xmlSchemaParseSequence(ctxt, schema, child);
8604 child = child->next;
8605 type->subtypes = subtype;
8606 } else if (IS_SCHEMA(child, "group")) {
8607 subtype = (xmlSchemaTypePtr)
8608 xmlSchemaParseGroup(ctxt, schema, child, 0);
8609 child = child->next;
8610 type->subtypes = subtype;
8611 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008612 } else if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_SIMPLE) {
8613 if (IS_SCHEMA(child, "simpleType")) {
8614 if (type->base != NULL) {
8615 /*
8616 * src-restriction-base-or-simpleType
8617 * Either the base [attribute] or the simpleType [child] of the
8618 * <restriction> element must be present, but not both.
8619 */
8620 xmlSchemaPContentErr(ctxt,
8621 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
8622 NULL, NULL, type->node, child,
8623 "The attribute 'base' and the <simpleType> child are "
8624 "mutually exclusive", NULL);
8625 } else {
8626 subtype = (xmlSchemaTypePtr)
8627 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
8628 type->baseType = subtype;
8629 }
8630 child = child->next;
8631 }
8632 } else if (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00008633 if (IS_SCHEMA(child, "simpleType")) {
8634 subtype = (xmlSchemaTypePtr)
8635 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008636 type->subtypes = subtype;
8637 child = child->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00008638 }
8639 }
8640 if ((ctxt->ctxtType->type == XML_SCHEMA_TYPE_SIMPLE) ||
8641 (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
8642 xmlSchemaFacetPtr facet, lastfacet = NULL;
8643
Daniel Veillard01fa6152004-06-29 17:04:39 +00008644 /*
8645 * Add the facets to the parent simpleType/complexType.
8646 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00008647 /*
8648 * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
8649 * Simple Type Definition Schema Representation Constraint:
8650 * *Single Facet Value*
8651 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00008652 while ((IS_SCHEMA(child, "minInclusive")) ||
8653 (IS_SCHEMA(child, "minExclusive")) ||
8654 (IS_SCHEMA(child, "maxInclusive")) ||
8655 (IS_SCHEMA(child, "maxExclusive")) ||
8656 (IS_SCHEMA(child, "totalDigits")) ||
8657 (IS_SCHEMA(child, "fractionDigits")) ||
8658 (IS_SCHEMA(child, "pattern")) ||
8659 (IS_SCHEMA(child, "enumeration")) ||
8660 (IS_SCHEMA(child, "whiteSpace")) ||
8661 (IS_SCHEMA(child, "length")) ||
8662 (IS_SCHEMA(child, "maxLength")) ||
8663 (IS_SCHEMA(child, "minLength"))) {
8664 facet = xmlSchemaParseFacet(ctxt, schema, child);
8665 if (facet != NULL) {
8666 if (lastfacet == NULL)
8667 ctxt->ctxtType->facets = facet;
8668 else
8669 lastfacet->next = facet;
8670 lastfacet = facet;
8671 lastfacet->next = NULL;
8672 }
8673 child = child->next;
8674 }
8675 /*
8676 * Create links for derivation and validation.
8677 */
8678 if (lastfacet != NULL) {
8679 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
8680
8681 facet = ctxt->ctxtType->facets;
8682 do {
8683 facetLink = (xmlSchemaFacetLinkPtr) xmlMalloc(sizeof(xmlSchemaFacetLink));
8684 if (facetLink == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008685 xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008686 xmlFree(facetLink);
8687 return (NULL);
8688 }
8689 facetLink->facet = facet;
8690 facetLink->next = NULL;
8691 if (lastFacetLink == NULL)
8692 ctxt->ctxtType->facetSet = facetLink;
8693 else
8694 lastFacetLink->next = facetLink;
8695 lastFacetLink = facetLink;
8696 facet = facet->next;
8697 } while (facet != NULL);
8698 }
8699 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008700 if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX) {
8701 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
8702 if (IS_SCHEMA(child, "anyAttribute")) {
8703 ctxt->ctxtType->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
8704 child = child->next;
8705 }
8706 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008707 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008708 /* TODO: Think about the error code. */
8709 if (ctxt->parentItem->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
8710 xmlSchemaPContentErr(ctxt,
8711 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
8712 NULL, type, node, child, NULL,
8713 "annotation?, (group | all | choice | sequence)?, "
8714 "((attribute | attributeGroup)*, anyAttribute?))");
8715 } else if (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
8716 xmlSchemaPContentErr(ctxt,
8717 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
8718 NULL, type, node, child, NULL,
8719 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
8720 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
8721 "length | minLength | maxLength | enumeration | whiteSpace | "
8722 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
8723 } else {
8724 /* Simple type */
8725 xmlSchemaPContentErr(ctxt,
8726 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
8727 NULL, type, node, child, NULL,
8728 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
8729 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
8730 "length | minLength | maxLength | enumeration | whiteSpace | "
8731 "pattern)*))");
8732 }
8733 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008734 ctxt->container = oldcontainer;
8735 return (type);
8736}
8737
8738/**
8739 * xmlSchemaParseExtension:
8740 * @ctxt: a schema validation context
8741 * @schema: the schema being built
8742 * @node: a subtree containing XML Schema informations
8743 *
8744 * parse a XML schema Extension definition
8745 * *WARNING* this interface is highly subject to change
8746 *
8747 * Returns the type definition or NULL in case of error
8748 */
8749static xmlSchemaTypePtr
8750xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008751 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008752{
8753 xmlSchemaTypePtr type, subtype;
8754 xmlNodePtr child = NULL;
8755 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008756 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00008757
8758 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8759 return (NULL);
8760
8761 oldcontainer = ctxt->container;
8762
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008763 snprintf((char *) name, 30, "#ext%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008764 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00008765 if (type == NULL)
8766 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00008767 type->type = XML_SCHEMA_TYPE_EXTENSION;
Daniel Veillard4255d502002-04-16 15:50:10 +00008768 type->node = node;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00008769
8770 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
8771
Daniel Veillard4255d502002-04-16 15:50:10 +00008772 ctxt->container = name;
8773
8774 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
8775 if (type->base == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008776 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_EXTENSION_NO_BASE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008777 "<extension>: The attribute \"base\" is missing.\n",
8778 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008779 }
8780 child = node->children;
8781 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008782 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8783 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008784 }
8785 subtype = NULL;
8786
8787 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008788 subtype = xmlSchemaParseAll(ctxt, schema, child);
8789 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008790 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008791 subtype = xmlSchemaParseChoice(ctxt, schema, child);
8792 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008793 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008794 subtype = xmlSchemaParseSequence(ctxt, schema, child);
8795 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008796 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008797 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008798 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008799 }
8800 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008801 type->subtypes = subtype;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008802 if ((ctxt->ctxtType != NULL) &&
8803 (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX)) {
8804 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
8805 if (IS_SCHEMA(child, "anyAttribute")) {
8806 ctxt->ctxtType->attributeWildcard =
8807 xmlSchemaParseAnyAttribute(ctxt, schema, child);
8808 child = child->next;
8809 }
8810 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008811 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008812 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008813 XML_SCHEMAP_UNKNOWN_EXTENSION_CHILD,
8814 "<extension> has unexpected content.\n", type->name,
8815 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008816 }
8817 ctxt->container = oldcontainer;
8818 return (type);
8819}
8820
8821/**
8822 * xmlSchemaParseSimpleContent:
8823 * @ctxt: a schema validation context
8824 * @schema: the schema being built
8825 * @node: a subtree containing XML Schema informations
8826 *
8827 * parse a XML schema SimpleContent definition
8828 * *WARNING* this interface is highly subject to change
8829 *
8830 * Returns the type definition or NULL in case of error
8831 */
8832static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008833xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
8834 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008835{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008836 xmlSchemaTypePtr type, subtype, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00008837 xmlNodePtr child = NULL;
8838 xmlChar name[30];
8839
8840 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8841 return (NULL);
8842
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008843 snprintf((char *) name, 30, "#SC%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008844 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00008845 if (type == NULL)
8846 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00008847 type->type = XML_SCHEMA_TYPE_SIMPLE_CONTENT;
Daniel Veillard4255d502002-04-16 15:50:10 +00008848 type->node = node;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00008849
8850 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00008851
8852 child = node->children;
8853 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008854 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8855 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008856 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008857 oldParentItem = ctxt->parentItem;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008858 ctxt->parentItem = type;
8859 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00008860 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008861 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00008862 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008863 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008864 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008865 subtype = (xmlSchemaTypePtr)
8866 xmlSchemaParseExtension(ctxt, schema, child);
8867 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008868 }
8869 type->subtypes = subtype;
8870 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008871 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008872 XML_SCHEMAP_UNKNOWN_SIMPLECONTENT_CHILD,
8873 "<simpleContent> has unexpected content.\n",
8874 NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008875 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008876 ctxt->parentItem = oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00008877 return (type);
8878}
8879
8880/**
8881 * xmlSchemaParseComplexContent:
8882 * @ctxt: a schema validation context
8883 * @schema: the schema being built
8884 * @node: a subtree containing XML Schema informations
8885 *
8886 * parse a XML schema ComplexContent definition
8887 * *WARNING* this interface is highly subject to change
8888 *
8889 * Returns the type definition or NULL in case of error
8890 */
8891static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008892xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
8893 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008894{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008895 xmlSchemaTypePtr type, subtype, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00008896 xmlNodePtr child = NULL;
8897 xmlChar name[30];
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008898 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00008899
8900 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8901 return (NULL);
8902
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008903 snprintf((char *) name, 30, "#CC%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008904 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00008905 if (type == NULL)
8906 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00008907 type->type = XML_SCHEMA_TYPE_COMPLEX_CONTENT;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008908 type->node = node;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008909 /*
8910 * Check for illegal attributes.
8911 */
8912 attr = node->properties;
8913 while (attr != NULL) {
8914 if (attr->ns == NULL) {
8915 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8916 (!xmlStrEqual(attr->name, BAD_CAST "mixed")))
8917 {
8918 xmlSchemaPIllegalAttrErr(ctxt,
8919 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8920 NULL, NULL, attr);
8921 }
8922 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8923 xmlSchemaPIllegalAttrErr(ctxt,
8924 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8925 NULL, NULL, attr);
8926 }
8927 attr = attr->next;
8928 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00008929
8930 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
8931
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008932 /*
8933 * Handle attribute 'mixed'.
8934 */
8935 if (xmlGetBooleanProp(ctxt, NULL, type, node, "mixed", 0)) {
8936 if ((ctxt->ctxtType->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
8937 ctxt->ctxtType->flags |= XML_SCHEMAS_TYPE_MIXED;
8938 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008939 child = node->children;
8940 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008941 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8942 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008943 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008944 oldParentItem = ctxt->parentItem;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008945 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008946 subtype = NULL;
8947 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008948 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00008949 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008950 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008951 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008952 subtype = (xmlSchemaTypePtr)
8953 xmlSchemaParseExtension(ctxt, schema, child);
8954 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008955 }
8956 type->subtypes = subtype;
8957 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008958 xmlSchemaPContentErr(ctxt,
8959 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8960 NULL, NULL, node, child,
8961 NULL, "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +00008962 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008963 ctxt->parentItem = oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00008964 return (type);
8965}
8966
8967/**
8968 * xmlSchemaParseComplexType:
8969 * @ctxt: a schema validation context
8970 * @schema: the schema being built
8971 * @node: a subtree containing XML Schema informations
8972 *
8973 * parse a XML schema Complex Type definition
8974 * *WARNING* this interface is highly subject to change
8975 *
8976 * Returns the type definition or NULL in case of error
8977 */
8978static xmlSchemaTypePtr
8979xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00008980 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00008981{
Daniel Veillard01fa6152004-06-29 17:04:39 +00008982 xmlSchemaTypePtr type, subtype, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00008983 xmlNodePtr child = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008984 const xmlChar *name = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00008985 const xmlChar *oldcontainer;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008986 xmlAttrPtr attr;
8987 const xmlChar *attrValue;
8988 xmlChar *des = NULL; /* The reported designation. */
Daniel Veillard1a380b82004-10-21 16:00:06 +00008989 char buf[40];
8990
Daniel Veillard4255d502002-04-16 15:50:10 +00008991
8992 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8993 return (NULL);
8994
Daniel Veillard01fa6152004-06-29 17:04:39 +00008995 ctxtType = ctxt->ctxtType;
8996
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008997 if (topLevel) {
8998 attr = xmlSchemaGetPropNode(node, "name");
8999 if (attr == NULL) {
9000 xmlSchemaPMissingAttrErr(ctxt,
9001 XML_SCHEMAP_S4S_ATTR_MISSING,
9002 (xmlChar **) &xmlSchemaElemDesCT, NULL, node,
9003 "name", NULL);
9004 return (NULL);
9005 } else if (xmlSchemaPValAttrNode(ctxt,
9006 (xmlChar **) &xmlSchemaElemDesCT, NULL, attr,
9007 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
9008 return (NULL);
9009 }
9010 }
9011
9012 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009013 /*
9014 * Parse as local complex type definition.
9015 */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00009016 snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009017 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
9018 if (type == NULL)
9019 return (NULL);
9020 name = (const xmlChar *) buf;
9021 type->node = node;
9022 type->type = XML_SCHEMA_TYPE_COMPLEX;
9023 /*
9024 * TODO: We need the target namespace.
9025 */
9026 } else {
9027 /*
9028 * Parse as global complex type definition.
9029 */
William M. Brack2f2a6632004-08-20 23:09:47 +00009030 type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace, node);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009031 if (type == NULL)
9032 return (NULL);
9033 type->node = node;
9034 type->type = XML_SCHEMA_TYPE_COMPLEX;
9035 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
9036 /*
9037 * Set defaults.
9038 */
9039 type->flags |= XML_SCHEMAS_TYPE_FINAL_DEFAULT;
9040 type->flags |= XML_SCHEMAS_TYPE_BLOCK_DEFAULT;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00009041 }
9042 type->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009043 /*
9044 * Handle attributes.
9045 */
9046 attr = node->properties;
9047 while (attr != NULL) {
9048 if (attr->ns == NULL) {
9049 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
9050 /*
9051 * Attribute "id".
9052 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00009053 xmlSchemaPValAttrID(ctxt, NULL, type, node,
9054 BAD_CAST "id");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009055 } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
9056 /*
9057 * Attribute "mixed".
9058 */
9059 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
9060 (xmlNodePtr) attr))
9061 type->flags |= XML_SCHEMAS_TYPE_MIXED;
9062 } else if (topLevel) {
9063 /*
9064 * Attributes of global complex type definitions.
9065 */
9066 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
9067 /* Pass. */
9068 } else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
9069 /*
9070 * Attribute "abstract".
9071 */
9072 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
9073 (xmlNodePtr) attr))
9074 type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
9075 } else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
9076 /*
9077 * Attribute "final".
9078 */
9079 attrValue = xmlSchemaGetNodeContent(ctxt,
9080 (xmlNodePtr) attr);
9081 if (xmlSchemaPValAttrBlockFinal(attrValue,
9082 &(type->flags),
9083 -1,
9084 XML_SCHEMAS_TYPE_FINAL_EXTENSION,
9085 XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
9086 -1, -1, -1) != 0)
9087 {
9088 xmlSchemaPSimpleTypeErr(ctxt,
9089 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9090 &des, type, (xmlNodePtr) attr,
9091 NULL,
9092 "(#all | List of (extension | restriction))",
9093 attrValue, NULL, NULL, NULL);
9094 }
9095 } else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
9096 /*
9097 * Attribute "block".
9098 */
9099 attrValue = xmlSchemaGetNodeContent(ctxt,
9100 (xmlNodePtr) attr);
9101 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
9102 -1,
9103 XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
9104 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
9105 -1, -1, -1) != 0) {
9106 xmlSchemaPSimpleTypeErr(ctxt,
9107 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9108 &des, type, (xmlNodePtr) attr,
9109 NULL,
9110 "(#all | List of (extension | restriction)) ",
9111 attrValue, NULL, NULL, NULL);
9112 }
9113 } else {
9114 xmlSchemaPIllegalAttrErr(ctxt,
9115 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9116 &des, type, attr);
9117 }
9118 } else {
9119 xmlSchemaPIllegalAttrErr(ctxt,
9120 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9121 &des, type, attr);
9122 }
9123 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9124 xmlSchemaPIllegalAttrErr(ctxt,
9125 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9126 &des, type, attr);
9127 }
9128 attr = attr->next;
9129 }
9130 /*
9131 * Set as default for attribute wildcards.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009132 * This will be only changed if a complex type
9133 * inherits an attribute wildcard from a base type.
9134 */
9135 type->flags |= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009136 /*
9137 * And now for the children...
9138 */
9139 oldcontainer = ctxt->container;
9140 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +00009141 child = node->children;
9142 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009143 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
9144 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009145 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00009146 ctxt->ctxtType = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00009147 if (IS_SCHEMA(child, "simpleContent")) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009148 /*
9149 * 3.4.3 : 2.2
9150 * Specifying mixed='true' when the <simpleContent>
9151 * alternative is chosen has no effect
9152 */
William M. Bracke7091952004-05-11 15:09:58 +00009153 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
9154 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009155 type->subtypes = xmlSchemaParseSimpleContent(ctxt, schema, child);
9156 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009157 } else if (IS_SCHEMA(child, "complexContent")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009158 type->subtypes = xmlSchemaParseComplexContent(ctxt, schema, child);
9159 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009160 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009161 subtype = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009162 /*
9163 * Parse model groups.
9164 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009165 if (IS_SCHEMA(child, "all")) {
9166 subtype = xmlSchemaParseAll(ctxt, schema, child);
9167 child = child->next;
9168 } else if (IS_SCHEMA(child, "choice")) {
9169 subtype = xmlSchemaParseChoice(ctxt, schema, child);
9170 child = child->next;
9171 } else if (IS_SCHEMA(child, "sequence")) {
9172 subtype = xmlSchemaParseSequence(ctxt, schema, child);
9173 child = child->next;
9174 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009175 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009176 child = child->next;
9177 }
9178 if (subtype != NULL)
9179 type->subtypes = subtype;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009180 /*
9181 * Parse attribute decls/refs.
9182 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009183 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009184 /*
9185 * Parse attribute wildcard.
9186 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009187 if (IS_SCHEMA(child, "anyAttribute")) {
9188 type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
9189 child = child->next;
9190 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009191 }
9192 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009193 xmlSchemaPContentErr(ctxt,
9194 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9195 &des, type, node, child,
9196 NULL, "(annotation?, (simpleContent | complexContent | "
9197 "((group | all | choice | sequence)?, ((attribute | "
9198 "attributeGroup)*, anyAttribute?))))");
Daniel Veillard4255d502002-04-16 15:50:10 +00009199 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009200 FREE_AND_NULL(des);
Daniel Veillard4255d502002-04-16 15:50:10 +00009201 ctxt->container = oldcontainer;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009202 ctxt->ctxtType = ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00009203 return (type);
9204}
9205
Daniel Veillard4255d502002-04-16 15:50:10 +00009206/**
9207 * xmlSchemaParseSchema:
9208 * @ctxt: a schema validation context
9209 * @node: a subtree containing XML Schema informations
9210 *
9211 * parse a XML schema definition from a node set
9212 * *WARNING* this interface is highly subject to change
9213 *
9214 * Returns the internal XML Schema structure built from the resource or
9215 * NULL in case of error
9216 */
9217static xmlSchemaPtr
9218xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
9219{
9220 xmlSchemaPtr schema = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009221 const xmlChar *val;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00009222 int nberrors;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009223 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00009224
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009225 /*
9226 * This one is called by xmlSchemaParse only and is used if
9227 * the schema to be parsed was specified via the API; i.e. not
9228 * automatically by the validated instance document.
9229 */
Daniel Veillard4255d502002-04-16 15:50:10 +00009230 if ((ctxt == NULL) || (node == NULL))
9231 return (NULL);
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00009232 nberrors = ctxt->nberrors;
9233 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00009234 if (IS_SCHEMA(node, "schema")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009235 xmlSchemaImportPtr import;
9236
Daniel Veillard4255d502002-04-16 15:50:10 +00009237 schema = xmlSchemaNewSchema(ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009238 if (schema == NULL)
9239 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009240 /*
9241 * Disable build of list of items.
9242 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00009243 attr = xmlSchemaGetPropNode(node, "targetNamespace");
9244 if (attr != NULL) {
9245 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
9246 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &val);
9247 /*
9248 * TODO: Should we proceed with an invalid target namespace?
9249 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009250 schema->targetNamespace = xmlDictLookup(ctxt->dict, val, -1);
9251 } else {
9252 schema->targetNamespace = NULL;
9253 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009254 /*
9255 * Add the current ns name and location to the import table;
9256 * this is needed to have a consistent mechanism, regardless
9257 * if all schemata are constructed dynamically fired by the
9258 * instance or if the schema to be used was specified via
9259 * the API.
9260 */
9261 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports),
9262 schema->targetNamespace);
9263 if (import == NULL) {
9264 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT,
9265 NULL, NULL, (xmlNodePtr) ctxt->doc,
9266 "Internal error: xmlSchemaParseSchema, "
9267 "failed to add an import entry", NULL);
9268 xmlSchemaFree(schema);
9269 schema = NULL;
9270 return (NULL);
9271 }
9272 import->schemaLocation = ctxt->URL;
9273 /*
9274 * NOTE: We won't set the doc here, otherwise it will be freed
9275 * if the import struct is freed.
9276 * import->doc = ctxt->doc;
9277 */
9278
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00009279 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00009280 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
9281 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &(schema->version));
9282
William M. Brack2f2a6632004-08-20 23:09:47 +00009283 xmlSchemaParseSchemaDefaults(ctxt, schema, node);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009284 xmlSchemaParseSchemaTopLevel(ctxt, schema, node->children);
9285 } else {
9286 xmlDocPtr doc;
9287
9288 doc = node->doc;
9289
9290 if ((doc != NULL) && (doc->URL != NULL)) {
9291 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
9292 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009293 "The file \"%s\" is not a XML schema.\n", doc->URL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009294 } else {
9295 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
9296 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009297 "The file is not a XML schema.\n", NULL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009298 }
9299 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009300 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00009301 if (ctxt->nberrors != 0) {
9302 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009303 xmlSchemaFree(schema);
9304 schema = NULL;
9305 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00009306 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009307 if (schema != NULL)
9308 schema->counter = ctxt->counter;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00009309 ctxt->nberrors = nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00009310#ifdef DEBUG
9311 if (schema == NULL)
9312 xmlGenericError(xmlGenericErrorContext,
9313 "xmlSchemaParse() failed\n");
9314#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00009315 return (schema);
9316}
9317
9318/************************************************************************
9319 * *
9320 * Validating using Schemas *
9321 * *
9322 ************************************************************************/
9323
9324/************************************************************************
9325 * *
9326 * Reading/Writing Schemas *
9327 * *
9328 ************************************************************************/
9329
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009330#if 0 /* Will be enabled if it is clear what options are needed. */
9331/**
9332 * xmlSchemaParserCtxtSetOptions:
9333 * @ctxt: a schema parser context
9334 * @options: a combination of xmlSchemaParserOption
9335 *
9336 * Sets the options to be used during the parse.
9337 *
9338 * Returns 0 in case of success, -1 in case of an
9339 * API error.
9340 */
9341static int
9342xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
9343 int options)
9344
9345{
9346 int i;
9347
9348 if (ctxt == NULL)
9349 return (-1);
9350 /*
9351 * WARNING: Change the start value if adding to the
9352 * xmlSchemaParseOption.
9353 */
9354 for (i = 1; i < (int) sizeof(int) * 8; i++) {
9355 if (options & 1<<i) {
9356 return (-1);
9357 }
9358 }
9359 ctxt->options = options;
9360 return (0);
9361}
9362
9363/**
9364 * xmlSchemaValidCtxtGetOptions:
9365 * @ctxt: a schema parser context
9366 *
9367 * Returns the option combination of the parser context.
9368 */
9369static int
9370xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
9371
9372{
9373 if (ctxt == NULL)
9374 return (-1);
9375 else
9376 return (ctxt->options);
9377}
9378
9379 void *curItems; /* used for dynamic addition of schemata */
9380 int nbCurItems; /* used for dynamic addition of schemata */
9381 int sizeCurItems; /* used for dynamic addition of schemata */
9382
9383#endif
9384
Daniel Veillard4255d502002-04-16 15:50:10 +00009385/**
9386 * xmlSchemaNewParserCtxt:
9387 * @URL: the location of the schema
9388 *
9389 * Create an XML Schemas parse context for that file/resource expected
9390 * to contain an XML Schemas file.
9391 *
9392 * Returns the parser context or NULL in case of error
9393 */
9394xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009395xmlSchemaNewParserCtxt(const char *URL)
9396{
Daniel Veillard4255d502002-04-16 15:50:10 +00009397 xmlSchemaParserCtxtPtr ret;
9398
9399 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009400 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009401
9402 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9403 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009404 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009405 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009406 return (NULL);
9407 }
9408 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009409 ret->dict = xmlDictCreate();
9410 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00009411 ret->includes = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00009412 return (ret);
9413}
9414
9415/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009416 * xmlSchemaNewParserCtxtUseDict:
9417 * @URL: the location of the schema
9418 * @dict: the dictionary to be used
9419 *
9420 * Create an XML Schemas parse context for that file/resource expected
9421 * to contain an XML Schemas file.
9422 *
9423 * Returns the parser context or NULL in case of error
9424 */
9425static xmlSchemaParserCtxtPtr
9426xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
9427{
9428 xmlSchemaParserCtxtPtr ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009429 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009430 if (URL == NULL)
9431 return (NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009432 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009433
9434 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9435 if (ret == NULL) {
9436 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
9437 NULL);
9438 return (NULL);
9439 }
9440 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
9441 ret->dict = dict;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009442 xmlDictReference(dict);
9443 if (URL != NULL)
9444 ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009445 ret->includes = 0;
9446 return (ret);
9447}
9448
9449
9450/**
Daniel Veillard6045c902002-10-09 21:13:59 +00009451 * xmlSchemaNewMemParserCtxt:
9452 * @buffer: a pointer to a char array containing the schemas
9453 * @size: the size of the array
9454 *
9455 * Create an XML Schemas parse context for that memory buffer expected
9456 * to contain an XML Schemas file.
9457 *
9458 * Returns the parser context or NULL in case of error
9459 */
9460xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009461xmlSchemaNewMemParserCtxt(const char *buffer, int size)
9462{
Daniel Veillard6045c902002-10-09 21:13:59 +00009463 xmlSchemaParserCtxtPtr ret;
9464
9465 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009466 return (NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00009467
9468 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9469 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009470 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009471 NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00009472 return (NULL);
9473 }
9474 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
9475 ret->buffer = buffer;
9476 ret->size = size;
William M. Brackcf9eadf2003-12-25 13:24:05 +00009477 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +00009478 return (ret);
9479}
9480
9481/**
Daniel Veillard9d751502003-10-29 13:21:47 +00009482 * xmlSchemaNewDocParserCtxt:
9483 * @doc: a preparsed document tree
9484 *
9485 * Create an XML Schemas parse context for that document.
9486 * NB. The document may be modified during the parsing process.
9487 *
9488 * Returns the parser context or NULL in case of error
9489 */
9490xmlSchemaParserCtxtPtr
9491xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
9492{
9493 xmlSchemaParserCtxtPtr ret;
9494
9495 if (doc == NULL)
9496 return (NULL);
9497
9498 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9499 if (ret == NULL) {
9500 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
9501 NULL);
9502 return (NULL);
9503 }
9504 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
9505 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +00009506 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +00009507 /* The application has responsibility for the document */
9508 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +00009509
9510 return (ret);
9511}
9512
9513/**
Daniel Veillard4255d502002-04-16 15:50:10 +00009514 * xmlSchemaFreeParserCtxt:
9515 * @ctxt: the schema parser context
9516 *
9517 * Free the resources associated to the schema parser context
9518 */
9519void
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009520xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
9521{
Daniel Veillard4255d502002-04-16 15:50:10 +00009522 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009523 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +00009524 if (ctxt->doc != NULL && !ctxt->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009525 xmlFreeDoc(ctxt->doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009526 if (ctxt->assemble != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009527 xmlFree((xmlSchemaTypePtr *) ctxt->assemble->items);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009528 xmlFree(ctxt->assemble);
9529 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009530 if (ctxt->vctxt != NULL) {
9531 xmlSchemaFreeValidCtxt(ctxt->vctxt);
9532 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009533 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00009534 xmlFree(ctxt);
9535}
9536
9537/************************************************************************
9538 * *
9539 * Building the content models *
9540 * *
9541 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009542
Daniel Veillard4255d502002-04-16 15:50:10 +00009543/**
9544 * xmlSchemaBuildAContentModel:
9545 * @type: the schema type definition
9546 * @ctxt: the schema parser context
9547 * @name: the element name whose content is being built
9548 *
9549 * Generate the automata sequence needed for that type
9550 */
9551static void
9552xmlSchemaBuildAContentModel(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009553 xmlSchemaParserCtxtPtr ctxt,
9554 const xmlChar * name)
9555{
Daniel Veillard4255d502002-04-16 15:50:10 +00009556 if (type == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009557 xmlGenericError(xmlGenericErrorContext,
9558 "Found unexpected type = NULL in %s content model\n",
9559 name);
9560 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00009561 }
9562 switch (type->type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009563 case XML_SCHEMA_TYPE_ANY: {
9564 xmlAutomataStatePtr start, end;
9565 xmlSchemaWildcardPtr wild;
9566 xmlSchemaWildcardNsPtr ns;
Daniel Veillard32370232002-10-16 14:08:14 +00009567
Daniel Veillardc0826a72004-08-10 14:17:33 +00009568 wild = type->attributeWildcard;
9569
9570 if (wild == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00009571 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009572 "Internal error: xmlSchemaBuildAContentModel, "
9573 "no wildcard on xsd:any.\n", NULL, NULL);
9574 return;
9575 }
9576
9577 start = ctxt->state;
9578 end = xmlAutomataNewState(ctxt->am);
9579
9580 if (type->maxOccurs == 1) {
9581 if (wild->any == 1) {
9582 /*
9583 * We need to add both transitions:
9584 *
9585 * 1. the {"*", "*"} for elements in a namespace.
9586 */
9587 ctxt->state =
9588 xmlAutomataNewTransition2(ctxt->am,
9589 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
9590 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9591 /*
9592 * 2. the {"*"} for elements in no namespace.
9593 */
9594 ctxt->state =
9595 xmlAutomataNewTransition2(ctxt->am,
9596 start, NULL, BAD_CAST "*", NULL, type);
9597 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9598
9599 } else if (wild->nsSet != NULL) {
9600 ns = wild->nsSet;
9601 do {
9602 ctxt->state = start;
9603 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9604 ctxt->state, NULL, BAD_CAST "*", ns->value, type);
9605 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9606 ns = ns->next;
9607 } while (ns != NULL);
9608
9609 } else if (wild->negNsSet != NULL) {
9610 xmlAutomataStatePtr deadEnd;
9611
9612 deadEnd = xmlAutomataNewState(ctxt->am);
9613 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9614 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, type);
9615 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9616 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
9617 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9618 }
9619 } else {
9620 int counter;
9621 xmlAutomataStatePtr hop;
9622 int maxOccurs =
9623 type->maxOccurs == UNBOUNDED ? UNBOUNDED : type->maxOccurs - 1;
9624 int minOccurs =
9625 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
9626
9627 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
9628 hop = xmlAutomataNewState(ctxt->am);
9629 if (wild->any == 1) {
9630 ctxt->state =
9631 xmlAutomataNewTransition2(ctxt->am,
9632 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
9633 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
9634 ctxt->state =
9635 xmlAutomataNewTransition2(ctxt->am,
9636 start, NULL, BAD_CAST "*", NULL, type);
9637 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
9638 } else if (wild->nsSet != NULL) {
9639 ns = wild->nsSet;
9640 do {
9641 ctxt->state =
9642 xmlAutomataNewTransition2(ctxt->am,
9643 start, NULL, BAD_CAST "*", ns->value, type);
9644 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
9645 ns = ns->next;
9646 } while (ns != NULL);
9647
9648 } else if (wild->negNsSet != NULL) {
9649 xmlAutomataStatePtr deadEnd;
9650
9651 deadEnd = xmlAutomataNewState(ctxt->am);
9652 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9653 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, type);
9654 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9655 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
9656 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
9657 }
9658 xmlAutomataNewCountedTrans(ctxt->am, hop, start, counter);
9659 xmlAutomataNewCounterTrans(ctxt->am, hop, end, counter);
9660 }
9661 if (type->minOccurs == 0) {
9662 xmlAutomataNewEpsilon(ctxt->am, start, end);
9663 }
9664 ctxt->state = end;
9665 break;
9666 }
9667 case XML_SCHEMA_TYPE_ELEMENT:{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009668 xmlAutomataStatePtr oldstate;
9669 xmlSchemaElementPtr particle, elemDecl;
Daniel Veillard32370232002-10-16 14:08:14 +00009670
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009671 /*
9672 * IMPORTANT: This puts element declarations
9673 * (and never element decl. references) into the
9674 * automaton. This is crucial and should not be changed,
9675 * since validating functions rely now on it.
9676 */
9677 particle = (xmlSchemaElementPtr) type;
9678 if (particle->ref != NULL) {
9679 if (particle->refDecl == NULL) {
9680 /*
9681 * Skip content model creation if the reference
9682 * did not resolve to a declaration.
9683 */
9684 break;
9685 } else {
9686 /*
9687 * Referenced global element declaration.
9688 */
9689 elemDecl = particle->refDecl;
9690 }
9691 } else {
9692 /*
9693 * Anonymous element declaration.
9694 */
9695 elemDecl = particle;
9696 }
9697
9698 oldstate = ctxt->state;
9699
9700 if (particle->maxOccurs >= UNBOUNDED) {
9701 if (particle->minOccurs > 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009702 xmlAutomataStatePtr tmp;
9703 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00009704
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009705 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009706 oldstate, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009707 oldstate = ctxt->state;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009708 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009709 particle->minOccurs - 1, UNBOUNDED);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00009710 ctxt->state =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009711 xmlAutomataNewTransition2(ctxt->am,
9712 ctxt->state, NULL,
9713 elemDecl->name,
9714 elemDecl->targetNamespace,
9715 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009716 tmp = ctxt->state;
9717 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009718 counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009719 ctxt->state =
9720 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009721 counter);
Daniel Veillard32370232002-10-16 14:08:14 +00009722
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009723 } else {
9724 ctxt->state =
9725 xmlAutomataNewTransition2(ctxt->am,
9726 ctxt->state, NULL,
9727 elemDecl->name,
9728 elemDecl->targetNamespace,
9729 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009730 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
9731 oldstate);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009732 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009733 /* basically an elem* */
9734 xmlAutomataNewEpsilon(ctxt->am, oldstate,
9735 ctxt->state);
9736 }
9737 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009738 } else if ((particle->maxOccurs > 1) || (particle->minOccurs > 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009739 xmlAutomataStatePtr tmp;
9740 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00009741
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009742 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
9743 oldstate, NULL);
9744 oldstate = ctxt->state;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009745 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009746 particle->minOccurs - 1,
9747 particle->maxOccurs - 1);
9748 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9749 ctxt->state,
9750 NULL,
9751 elemDecl->name,
9752 elemDecl->targetNamespace,
9753 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009754 tmp = ctxt->state;
9755 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009756 counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009757 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, tmp,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009758 NULL, counter);
9759 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009760 /* basically an elem? */
9761 xmlAutomataNewEpsilon(ctxt->am, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009762 ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009763 }
Daniel Veillardb39bc392002-10-26 19:29:51 +00009764
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009765 } else {
9766 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9767 ctxt->state,
9768 NULL,
9769 elemDecl->name,
9770 elemDecl->targetNamespace,
9771 (xmlSchemaTypePtr) elemDecl);
9772 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009773 /* basically an elem? */
9774 xmlAutomataNewEpsilon(ctxt->am, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009775 ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009776 }
9777 }
9778 break;
9779 }
9780 case XML_SCHEMA_TYPE_SEQUENCE:{
9781 xmlSchemaTypePtr subtypes;
Daniel Veillardb39bc392002-10-26 19:29:51 +00009782
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009783 /*
9784 * If max and min occurances are default (1) then
9785 * simply iterate over the subtypes
9786 */
9787 if ((type->minOccurs == 1) && (type->maxOccurs == 1)) {
9788 subtypes = type->subtypes;
9789 while (subtypes != NULL) {
9790 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
9791 subtypes = subtypes->next;
9792 }
9793 } else {
9794 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00009795
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009796 if (type->maxOccurs >= UNBOUNDED) {
9797 if (type->minOccurs > 1) {
9798 xmlAutomataStatePtr tmp;
9799 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00009800
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009801 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
9802 oldstate,
9803 NULL);
9804 oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00009805
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009806 counter = xmlAutomataNewCounter(ctxt->am,
9807 type->
9808 minOccurs - 1,
9809 UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +00009810
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009811 subtypes = type->subtypes;
9812 while (subtypes != NULL) {
9813 xmlSchemaBuildAContentModel(subtypes, ctxt,
9814 name);
9815 subtypes = subtypes->next;
9816 }
9817 tmp = ctxt->state;
9818 xmlAutomataNewCountedTrans(ctxt->am, tmp,
9819 oldstate, counter);
9820 ctxt->state =
9821 xmlAutomataNewCounterTrans(ctxt->am, tmp,
9822 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +00009823
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009824 } else {
9825 subtypes = type->subtypes;
9826 while (subtypes != NULL) {
9827 xmlSchemaBuildAContentModel(subtypes, ctxt,
9828 name);
9829 subtypes = subtypes->next;
9830 }
9831 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
9832 oldstate);
9833 if (type->minOccurs == 0) {
9834 xmlAutomataNewEpsilon(ctxt->am, oldstate,
9835 ctxt->state);
9836 }
9837 }
9838 } else if ((type->maxOccurs > 1)
9839 || (type->minOccurs > 1)) {
9840 xmlAutomataStatePtr tmp;
9841 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00009842
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009843 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
9844 oldstate,
9845 NULL);
9846 oldstate = ctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +00009847
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009848 counter = xmlAutomataNewCounter(ctxt->am,
9849 type->minOccurs -
9850 1,
9851 type->maxOccurs -
9852 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00009853
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009854 subtypes = type->subtypes;
9855 while (subtypes != NULL) {
9856 xmlSchemaBuildAContentModel(subtypes, ctxt,
9857 name);
9858 subtypes = subtypes->next;
9859 }
9860 tmp = ctxt->state;
9861 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
9862 counter);
9863 ctxt->state =
9864 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
9865 counter);
9866 if (type->minOccurs == 0) {
9867 xmlAutomataNewEpsilon(ctxt->am, oldstate,
9868 ctxt->state);
9869 }
Daniel Veillardb509f152002-04-17 16:28:10 +00009870
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009871 } else {
9872 subtypes = type->subtypes;
9873 while (subtypes != NULL) {
9874 xmlSchemaBuildAContentModel(subtypes, ctxt,
9875 name);
9876 subtypes = subtypes->next;
9877 }
9878 if (type->minOccurs == 0) {
9879 xmlAutomataNewEpsilon(ctxt->am, oldstate,
9880 ctxt->state);
9881 }
9882 }
9883 }
9884 break;
9885 }
9886 case XML_SCHEMA_TYPE_CHOICE:{
9887 xmlSchemaTypePtr subtypes;
9888 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +00009889
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009890 start = ctxt->state;
9891 end = xmlAutomataNewState(ctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +00009892
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009893 /*
9894 * iterate over the subtypes and remerge the end with an
9895 * epsilon transition
9896 */
9897 if (type->maxOccurs == 1) {
9898 subtypes = type->subtypes;
9899 while (subtypes != NULL) {
9900 ctxt->state = start;
9901 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
9902 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9903 subtypes = subtypes->next;
9904 }
9905 } else {
9906 int counter;
9907 xmlAutomataStatePtr hop;
9908 int maxOccurs = type->maxOccurs == UNBOUNDED ?
9909 UNBOUNDED : type->maxOccurs - 1;
9910 int minOccurs =
9911 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +00009912
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009913 /*
9914 * use a counter to keep track of the number of transtions
9915 * which went through the choice.
9916 */
9917 counter =
9918 xmlAutomataNewCounter(ctxt->am, minOccurs,
9919 maxOccurs);
9920 hop = xmlAutomataNewState(ctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +00009921
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009922 subtypes = type->subtypes;
9923 while (subtypes != NULL) {
9924 ctxt->state = start;
9925 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
9926 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
9927 subtypes = subtypes->next;
9928 }
9929 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
9930 counter);
9931 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
9932 counter);
9933 }
9934 if (type->minOccurs == 0) {
9935 xmlAutomataNewEpsilon(ctxt->am, start, end);
9936 }
9937 ctxt->state = end;
9938 break;
9939 }
9940 case XML_SCHEMA_TYPE_ALL:{
9941 xmlAutomataStatePtr start;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00009942 xmlSchemaElementPtr elemDecl, particle;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009943 int lax;
9944
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00009945 particle = (xmlSchemaElementPtr) type->subtypes;
9946 if (particle == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009947 break;
9948 start = ctxt->state;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00009949 while (particle != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009950 ctxt->state = start;
William M. Brack9989c7d2004-05-12 14:39:38 +00009951 /*
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00009952 * Changed to put the element declaration and
9953 * never the element decl. reference into the
9954 * automaton. This fixes bug 139897 and bug 167754.
William M. Brack9989c7d2004-05-12 14:39:38 +00009955 */
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00009956 if (particle->ref != NULL) {
9957 if (particle->refDecl == NULL) {
9958 /*
9959 * TODO: Note that we break on missing
9960 * sub-components.
9961 */
9962 break;
9963 } else
9964 elemDecl = particle->refDecl;
9965 } else
9966 elemDecl = particle;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009967 /*
9968 * NOTE: The {max occurs} of all the particles in the
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00009969 * {particles} of the group must be 0 or 1; this is
9970 * already ensured during the parse of the content of
9971 * <all>.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009972 */
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00009973 if ((particle->minOccurs == 1) &&
9974 (particle->maxOccurs == 1)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009975 xmlAutomataNewOnceTrans2(ctxt->am, ctxt->state,
9976 ctxt->state,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00009977 elemDecl->name,
9978 elemDecl->targetNamespace,
9979 1, 1, elemDecl);
9980 } else if ((particle->minOccurs == 0) &&
9981 (particle->maxOccurs == 1)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009982
9983 xmlAutomataNewCountTrans2(ctxt->am, ctxt->state,
9984 ctxt->state,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00009985 elemDecl->name,
9986 elemDecl->targetNamespace,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009987 0,
9988 1,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00009989 elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009990 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00009991 particle = (xmlSchemaElementPtr) particle->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009992 }
9993 lax = type->minOccurs == 0;
9994 ctxt->state =
9995 xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL,
9996 lax);
9997 break;
9998 }
9999 case XML_SCHEMA_TYPE_RESTRICTION:
10000 if (type->subtypes != NULL)
10001 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
10002 break;
10003 case XML_SCHEMA_TYPE_EXTENSION:
10004 if (type->baseType != NULL) {
10005 xmlSchemaTypePtr subtypes;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010006
10007 /*
10008 * TODO: Circular definitions will be checked at the
10009 * constraint level. So remove this when the complex type
10010 * constraints are implemented.
10011 */
Daniel Veillardf7627552004-04-22 07:15:40 +000010012 if (type->recurse) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010013 /* TODO: Change the error code. */
10014 xmlSchemaPCustomErr(ctxt,
10015 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
10016 NULL, type, type->node,
10017 "This item is circular", NULL);
Daniel Veillardf7627552004-04-22 07:15:40 +000010018 return;
10019 }
10020 type->recurse = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010021 xmlSchemaBuildAContentModel(type->baseType, ctxt, name);
Daniel Veillardf7627552004-04-22 07:15:40 +000010022 type->recurse = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010023 subtypes = type->subtypes;
10024 while (subtypes != NULL) {
10025 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
10026 subtypes = subtypes->next;
10027 }
10028 } else if (type->subtypes != NULL)
10029 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
10030 break;
10031 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000010032 /*
10033 * Handle model group definition references.
10034 * NOTE: type->subtypes is the referenced model grop definition;
10035 * and type->subtypes->subtypes is the model group (i.e. <all> or
10036 * <choice> or <sequence>).
10037 */
10038 if ((type->ref != NULL) && (type->subtypes != NULL) &&
10039 (type->subtypes->subtypes != NULL)) {
10040 xmlSchemaTypePtr modelGr;
10041 xmlAutomataStatePtr start, end;
10042
10043 modelGr = type->subtypes->subtypes;
10044 start = ctxt->state;
10045 end = xmlAutomataNewState(ctxt->am);
10046 if (type->maxOccurs == 1) {
10047 ctxt->state = start;
10048 xmlSchemaBuildAContentModel(modelGr, ctxt, name);
10049 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
10050 } else {
10051 int counter;
10052 xmlAutomataStatePtr hop;
10053 int maxOccurs = type->maxOccurs == UNBOUNDED ?
10054 UNBOUNDED : type->maxOccurs - 1;
10055 int minOccurs =
10056 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
10057
10058 counter =
10059 xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
10060 hop = xmlAutomataNewState(ctxt->am);
10061 ctxt->state = start;
10062 xmlSchemaBuildAContentModel(modelGr, ctxt, name);
10063 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
10064 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
10065 counter);
10066 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
10067 counter);
10068 }
10069 if (type->minOccurs == 0) {
10070 xmlAutomataNewEpsilon(ctxt->am, start, end);
10071 }
10072 ctxt->state = end;
10073 break;
10074 }
10075 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010076 case XML_SCHEMA_TYPE_COMPLEX:
10077 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
10078 if (type->subtypes != NULL)
10079 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
10080 break;
William M. Brack2f2a6632004-08-20 23:09:47 +000010081 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
10082 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010083 default:
10084 xmlGenericError(xmlGenericErrorContext,
10085 "Found unexpected type %d in %s content model\n",
10086 type->type, name);
10087 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000010088 }
10089}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010090
Daniel Veillard4255d502002-04-16 15:50:10 +000010091/**
10092 * xmlSchemaBuildContentModel:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010093 * @type: the type definition (or reference)
Daniel Veillard4255d502002-04-16 15:50:10 +000010094 * @ctxt: the schema parser context
Daniel Veillarda84c0b32003-06-02 16:58:46 +000010095 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +000010096 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010097 * Builds the content model of the complex type.
Daniel Veillard4255d502002-04-16 15:50:10 +000010098 */
10099static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010100xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010101 xmlSchemaParserCtxtPtr ctxt,
10102 const xmlChar * name)
10103{
Daniel Veillard4255d502002-04-16 15:50:10 +000010104 xmlAutomataStatePtr start;
10105
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010106 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) || (type->ref != NULL) ||
10107 (type->contentType == XML_SCHEMA_CONTENT_BASIC) ||
10108 (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
10109 (type->contModel != NULL))
10110 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +000010111
10112#ifdef DEBUG_CONTENT
10113 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010114 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000010115#endif
10116
Daniel Veillard4255d502002-04-16 15:50:10 +000010117 ctxt->am = xmlNewAutomata();
10118 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010119 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010120 "Cannot create automata for complex tpye %s\n", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010121 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000010122 }
10123 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010124 xmlSchemaBuildAContentModel(type, ctxt, name);
Daniel Veillard4255d502002-04-16 15:50:10 +000010125 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010126 type->contModel = xmlAutomataCompile(ctxt->am);
10127 if (type->contModel == NULL) {
10128 xmlSchemaPCustomErr(ctxt,
10129 XML_SCHEMAP_INTERNAL,
10130 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010131 "Failed to compile the content model", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010132 } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010133 xmlSchemaPCustomErr(ctxt,
10134 XML_SCHEMAP_NOT_DETERMINISTIC,
10135 /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010136 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010137 "The content model is not determinist", NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +000010138 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +000010139#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010140 xmlGenericError(xmlGenericErrorContext,
10141 "Content model of %s:\n", name);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010142 xmlRegexpPrint(stderr, type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +000010143#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +000010144 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +000010145 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000010146 xmlFreeAutomata(ctxt->am);
10147 ctxt->am = NULL;
10148}
10149
10150/**
10151 * xmlSchemaRefFixupCallback:
10152 * @elem: the schema element context
10153 * @ctxt: the schema parser context
10154 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000010155 * Resolves the references of an element declaration
10156 * or particle, which has an element declaration as it's
10157 * term.
Daniel Veillard4255d502002-04-16 15:50:10 +000010158 */
10159static void
10160xmlSchemaRefFixupCallback(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010161 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010162 const xmlChar * name ATTRIBUTE_UNUSED,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010163 const xmlChar * context ATTRIBUTE_UNUSED,
10164 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000010165{
Daniel Veillardc0826a72004-08-10 14:17:33 +000010166 if ((ctxt == NULL) || (elem == NULL) ||
10167 ((elem != NULL) && (elem->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010168 return;
Daniel Veillardc0826a72004-08-10 14:17:33 +000010169 elem->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
Daniel Veillard4255d502002-04-16 15:50:10 +000010170 if (elem->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010171 xmlSchemaElementPtr elemDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +000010172
Daniel Veillardc0826a72004-08-10 14:17:33 +000010173 /*
10174 * TODO: Evaluate, what errors could occur if the declaration is not
10175 * found. It might be possible that the "typefixup" might crash if
10176 * no ref declaration was found.
10177 */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010178 elemDecl = xmlSchemaGetElem(ctxt->schema, elem->ref, elem->refNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +000010179 if (elemDecl == NULL) {
10180 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010181 XML_SCHEMAP_SRC_RESOLVE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010182 NULL, (xmlSchemaTypePtr) elem, elem->node,
10183 "ref", elem->ref, elem->refNs,
10184 XML_SCHEMA_TYPE_ELEMENT, NULL);
10185 } else
10186 elem->refDecl = elemDecl;
10187 } else {
10188 if ((elem->subtypes == NULL) && (elem->namedType != NULL)) {
10189 xmlSchemaTypePtr type;
10190
10191 /* (type definition) ... otherwise the type definition ·resolved·
10192 * to by the ·actual value· of the type [attribute] ...
10193 */
10194 type = xmlSchemaGetType(ctxt->schema, elem->namedType,
10195 elem->namedTypeNs);
10196 if (type == NULL) {
10197 xmlSchemaPResCompAttrErr(ctxt,
10198 XML_SCHEMAP_SRC_RESOLVE,
10199 NULL, (xmlSchemaTypePtr) elem, elem->node,
10200 "type", elem->namedType, elem->namedTypeNs,
10201 XML_SCHEMA_TYPE_BASIC, "type definition");
10202 } else
10203 elem->subtypes = type;
10204 }
10205 if (elem->substGroup != NULL) {
10206 xmlSchemaElementPtr substHead;
10207
10208 /*
10209 * FIXME TODO: Do we need a new field in _xmlSchemaElement for
10210 * substitutionGroup?
10211 */
10212 substHead = xmlSchemaGetElem(ctxt->schema, elem->substGroup,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010213 elem->substGroupNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +000010214 if (substHead == NULL) {
10215 xmlSchemaPResCompAttrErr(ctxt,
10216 XML_SCHEMAP_SRC_RESOLVE,
10217 NULL, (xmlSchemaTypePtr) elem, NULL,
10218 "substitutionGroup", elem->substGroup, elem->substGroupNs,
10219 XML_SCHEMA_TYPE_ELEMENT, NULL);
10220 } else {
10221 xmlSchemaRefFixupCallback(substHead, ctxt, NULL, NULL, NULL);
10222 /*
10223 * (type definition)...otherwise the {type definition} of the
10224 * element declaration ·resolved· to by the ·actual value· of
10225 * the substitutionGroup [attribute], if present
10226 */
10227 if (elem->subtypes == NULL)
10228 elem->subtypes = substHead->subtypes;
10229 }
10230 }
10231 if ((elem->subtypes == NULL) && (elem->namedType == NULL) &&
10232 (elem->substGroup == NULL))
10233 elem->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
10234 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010235}
10236
William M. Bracke7091952004-05-11 15:09:58 +000010237/**
10238 * xmlSchemaParseListRefFixup:
10239 * @type: the schema type definition
10240 * @ctxt: the schema parser context
10241 *
10242 * Fixup of the itemType reference of the list type.
10243 */
Daniel Veillard377e1a92004-04-16 16:30:05 +000010244static void
William M. Bracke7091952004-05-11 15:09:58 +000010245xmlSchemaParseListRefFixup(xmlSchemaTypePtr type, xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010246{
Daniel Veillardc0826a72004-08-10 14:17:33 +000010247
Daniel Veillard01fa6152004-06-29 17:04:39 +000010248 if (((type->base == NULL) &&
10249 (type->subtypes == NULL)) ||
10250 ((type->base != NULL) &&
10251 (type->subtypes != NULL))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010252 /*
10253 * src-list-itemType-or-simpleType
10254 * Either the itemType [attribute] or the <simpleType> [child] of
10255 * the <list> element must be present, but not both.
Daniel Veillard01fa6152004-06-29 17:04:39 +000010256 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000010257 /*
10258 * TODO: Move this to the parse function.
10259 */
10260 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010261 XML_SCHEMAP_SRC_LIST_ITEMTYPE_OR_SIMPLETYPE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010262 NULL, type, type->node,
10263 "The attribute 'itemType' and the <simpleType> child "
10264 "are mutually exclusive", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010265 } else if (type->base!= NULL) {
10266 type->subtypes = xmlSchemaGetType(ctxt->schema, type->base, type->baseNs);
10267 if (type->subtypes == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010268 xmlSchemaPResCompAttrErr(ctxt,
10269 XML_SCHEMAP_SRC_RESOLVE,
10270 NULL, type, type->node,
10271 "itemType", type->base, type->baseNs,
10272 XML_SCHEMA_TYPE_SIMPLE, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010273 }
10274 }
10275 if ((type->subtypes != NULL) &&
10276 (type->subtypes->contentType == XML_SCHEMA_CONTENT_UNKNOWN))
10277 xmlSchemaTypeFixup(type->subtypes, ctxt, NULL);
William M. Bracke7091952004-05-11 15:09:58 +000010278}
10279
10280/**
10281 * xmlSchemaParseUnionRefCheck:
10282 * @typeDecl: the schema type definition
10283 * @ctxt: the schema parser context
10284 *
Daniel Veillard01fa6152004-06-29 17:04:39 +000010285 * Checks and builds the memberTypes of the union type.
10286 * Returns -1 in case of an internal error, 0 otherwise.
William M. Bracke7091952004-05-11 15:09:58 +000010287 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010288static int
William M. Bracke7091952004-05-11 15:09:58 +000010289xmlSchemaParseUnionRefCheck(xmlSchemaTypePtr type,
Daniel Veillard377e1a92004-04-16 16:30:05 +000010290 xmlSchemaParserCtxtPtr ctxt)
10291{
Daniel Veillardc0826a72004-08-10 14:17:33 +000010292
Daniel Veillard01fa6152004-06-29 17:04:39 +000010293 xmlSchemaTypeLinkPtr link, lastLink = NULL, prevLink, subLink, newLink;
10294 xmlSchemaTypePtr memberType, ctxtType;
Daniel Veillard377e1a92004-04-16 16:30:05 +000010295
Daniel Veillard01fa6152004-06-29 17:04:39 +000010296 /* 1 If the <union> alternative is chosen, then [Definition:]
10297 * define the explicit members as the type definitions ·resolved·
10298 * to by the items in the ·actual value· of the memberTypes [attribute],
10299 * if any, followed by the type definitions corresponding to the
10300 * <simpleType>s among the [children] of <union>, if any.
10301 */
Daniel Veillard377e1a92004-04-16 16:30:05 +000010302
Daniel Veillard01fa6152004-06-29 17:04:39 +000010303 if (type->type != XML_SCHEMA_TYPE_UNION)
10304 return (-1);
10305 if (ctxt->ctxtType == NULL) {
10306 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010307 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010308 "Internal error: xmlSchemaParseUnionRefCheck, no parent type "
10309 "available", NULL, NULL);
10310 return (-1);
10311 }
10312 /*
10313 * src-union-memberTypes-or-simpleTypes
10314 * Either the memberTypes [attribute] of the <union> element must
10315 * be non-empty or there must be at least one simpleType [child].
10316 */
10317 if ((type->base == NULL) &&
10318 (type->subtypes == NULL)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010319 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010320 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010321 NULL, NULL, type->node,
10322 "Either the attribute 'memberTypes' must be non-empty "
10323 "or there must be at least one <simpleType> child", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010324 }
10325
10326 ctxtType = ctxt->ctxtType;
10327 if (type->base != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010328 xmlAttrPtr attr;
10329 const xmlChar *cur, *end;
10330 xmlChar *tmp;
10331 const xmlChar *localName, *uri;
10332
10333 attr = xmlSchemaGetPropNode(type->node, "memberTypes");
Daniel Veillard01fa6152004-06-29 17:04:39 +000010334 cur = type->base;
10335 do {
10336 while (IS_BLANK_CH(*cur))
10337 cur++;
10338 end = cur;
10339 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
10340 end++;
10341 if (end == cur)
10342 break;
10343 tmp = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +000010344 xmlSchemaPValAttrNodeQNameValue(ctxt, ctxt->schema, NULL,
10345 NULL, attr, BAD_CAST tmp, &uri, NULL, &localName);
10346 memberType = xmlSchemaGetType(ctxt->schema, localName, uri);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010347 if (memberType == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010348 xmlSchemaPResCompAttrErr(ctxt,
10349 XML_SCHEMAP_UNKNOWN_MEMBER_TYPE,
10350 NULL, NULL, type->node, "memberTypes", localName, uri,
10351 XML_SCHEMA_TYPE_SIMPLE, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010352 } else {
10353 if (memberType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
10354 xmlSchemaTypeFixup(memberType, ctxt, NULL);
10355 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
10356 if (link == NULL) {
10357 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
10358 return (-1);
10359 }
10360 link->type = memberType;
10361 link->next = NULL;
10362 if (lastLink == NULL)
10363 ctxtType->memberTypes = link;
10364 else
10365 lastLink->next = link;
10366 lastLink = link;
10367 }
10368 xmlFree(tmp);
10369 cur = end;
10370 } while (*cur != 0);
10371 }
10372 /*
10373 * Add local simple types,
10374 */
10375 memberType = type->subtypes;
10376 while (memberType != NULL) {
10377 if (memberType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
10378 xmlSchemaTypeFixup(memberType, ctxt, NULL);
10379 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
10380 if (link == NULL) {
10381 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
10382 return (-1);
10383 }
10384 link->type = memberType;
10385 link->next = NULL;
10386 if (lastLink == NULL)
10387 ctxtType->memberTypes = link;
10388 else
10389 lastLink->next = link;
10390 lastLink = link;
10391 memberType = memberType->next;
10392 }
10393 /*
10394 * The actual value is then formed by replacing any union type
10395 * definition in the ·explicit members· with the members of their
10396 * {member type definitions}, in order.
10397 */
10398 link = ctxtType->memberTypes;
10399 while (link != NULL) {
10400 if (link->type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
10401 subLink = link->type->memberTypes;
10402 if (subLink != NULL) {
10403 link->type = subLink->type;
10404 if (subLink->next != NULL) {
10405 lastLink = link->next;
10406 subLink = subLink->next;
10407 prevLink = link;
10408 while (subLink != NULL) {
10409 newLink = (xmlSchemaTypeLinkPtr)
10410 xmlMalloc(sizeof(xmlSchemaTypeLink));
10411 if (newLink == NULL) {
10412 xmlSchemaPErrMemory(ctxt, "allocating a type link",
10413 NULL);
10414 return (-1);
10415 }
10416 newLink->type = memberType;
10417 prevLink->next = newLink;
10418 prevLink = newLink;
10419 newLink->next = lastLink;
10420
10421 subLink = subLink->next;
10422 }
10423 }
10424 }
10425 }
10426 link = link->next;
10427 }
10428
10429 return (0);
Daniel Veillard377e1a92004-04-16 16:30:05 +000010430}
10431
Daniel Veillard4255d502002-04-16 15:50:10 +000010432/**
Daniel Veillard3646d642004-06-02 19:19:14 +000010433 * xmlSchemaIsDerivedFromBuiltInType:
10434 * @ctxt: the schema parser context
10435 * @type: the type definition
10436 * @valType: the value type
10437 *
10438 *
10439 * Returns 1 if the type has the given value type, or
10440 * is derived from such a type.
10441 */
William M. Brack803812b2004-06-03 02:11:24 +000010442static int
Daniel Veillard3646d642004-06-02 19:19:14 +000010443xmlSchemaIsDerivedFromBuiltInType(xmlSchemaParserCtxtPtr ctxt,
10444 xmlSchemaTypePtr type, int valType)
10445{
10446 /* TODO: Check if this works in every case. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010447 if ((type->type == XML_SCHEMA_TYPE_BASIC) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000010448 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000010449 if (type->builtInType == valType)
Daniel Veillard3646d642004-06-02 19:19:14 +000010450 return(1);
10451 } else if (type->type == XML_SCHEMA_TYPE_ATTRIBUTE) {
10452 if (((xmlSchemaAttributePtr) type)->subtypes != NULL)
10453 return(xmlSchemaIsDerivedFromBuiltInType(ctxt,
10454 ((xmlSchemaAttributePtr) type)->subtypes, valType));
10455 } else if ((type->type == XML_SCHEMA_TYPE_RESTRICTION) ||
10456 (type->type == XML_SCHEMA_TYPE_EXTENSION)) {
10457 if (type->baseType != NULL)
10458 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->baseType,
10459 valType));
10460 } else if ((type->subtypes != NULL) &&
10461 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX) ||
10462 (type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
10463 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE) ||
10464 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
10465 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->subtypes,
10466 valType));
10467 }
10468
10469 return (0);
10470}
10471
10472/**
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000010473 * xmlSchemaGetPrimitiveType:
Daniel Veillard01fa6152004-06-29 17:04:39 +000010474 * @type: the simpleType definition
10475 *
10476 * Returns the primitive type of the given type or
10477 * NULL in case of error.
10478 */
10479static xmlSchemaTypePtr
10480xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
10481{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000010482
Daniel Veillard01fa6152004-06-29 17:04:39 +000010483 while (type != NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000010484 /*
10485 * Note that anySimpleType is actually not a primitive type
10486 * but we need that here.
10487 */
10488 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
10489 (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
Daniel Veillard01fa6152004-06-29 17:04:39 +000010490 return (type);
10491 type = type->baseType;
10492 }
10493
10494 return (NULL);
10495}
10496
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000010497#if 0
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000010498/**
10499 * xmlSchemaGetBuiltInTypeAncestor:
10500 * @type: the simpleType definition
10501 *
10502 * Returns the primitive type of the given type or
10503 * NULL in case of error.
10504 */
10505static xmlSchemaTypePtr
10506xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
10507{
10508 while (type != NULL) {
10509 if (type->type == XML_SCHEMA_TYPE_BASIC)
10510 return (type);
10511 type = type->baseType;
10512 }
10513
10514 return (NULL);
10515}
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000010516#endif
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000010517
Daniel Veillard01fa6152004-06-29 17:04:39 +000010518
10519/**
Daniel Veillard3646d642004-06-02 19:19:14 +000010520 * xmlSchemaBuildAttributeUsesOwned:
10521 * @ctxt: the schema parser context
10522 * @type: the complex type definition
10523 * @cur: the attribute declaration list
10524 * @lastUse: the top of the attribute use list
10525 *
10526 * Builds the attribute uses list on the given complex type.
10527 * This one is supposed to be called by
10528 * xmlSchemaBuildAttributeValidation only.
10529 */
10530static int
10531xmlSchemaBuildAttributeUsesOwned(xmlSchemaParserCtxtPtr ctxt,
10532 xmlSchemaAttributePtr cur,
10533 xmlSchemaAttributeLinkPtr *uses,
10534 xmlSchemaAttributeLinkPtr *lastUse)
10535{
10536 xmlSchemaAttributeLinkPtr tmp;
10537 while (cur != NULL) {
10538 if (cur->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
10539 /*
10540 * W3C: "2 The {attribute uses} of the attribute groups ·resolved·
10541 * to by the ·actual value·s of the ref [attribute] of the
10542 * <attributeGroup> [children], if any."
10543 */
10544 if (xmlSchemaBuildAttributeUsesOwned(ctxt,
10545 ((xmlSchemaAttributeGroupPtr) cur)->attributes, uses,
10546 lastUse) == -1) {
10547 return (-1);
10548 }
10549 } else {
10550 /* W3C: "1 The set of attribute uses corresponding to the
10551 * <attribute> [children], if any."
10552 */
10553 tmp = (xmlSchemaAttributeLinkPtr)
10554 xmlMalloc(sizeof(xmlSchemaAttributeLink));
10555 if (tmp == NULL) {
10556 xmlSchemaPErrMemory(ctxt, "building attribute uses", NULL);
10557 return (-1);
10558 }
10559 tmp->attr = cur;
10560 tmp->next = NULL;
10561 if (*uses == NULL)
10562 *uses = tmp;
10563 else
10564 (*lastUse)->next = tmp;
10565 *lastUse = tmp;
10566 }
10567 cur = cur->next;
10568 }
10569 return (0);
10570}
10571
Daniel Veillard50355f02004-06-08 17:52:16 +000010572/**
10573 * xmlSchemaCloneWildcardNsConstraints:
10574 * @ctxt: the schema parser context
10575 * @dest: the destination wildcard
10576 * @source: the source wildcard
10577 *
10578 * Clones the namespace constraints of source
10579 * and assignes them to dest.
10580 * Returns -1 on internal error, 0 otherwise.
10581 */
Daniel Veillard3646d642004-06-02 19:19:14 +000010582static int
10583xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
10584 xmlSchemaWildcardPtr *dest,
10585 xmlSchemaWildcardPtr source)
10586{
10587 xmlSchemaWildcardNsPtr cur, tmp, last;
10588
10589 if ((source == NULL) || (*dest == NULL))
10590 return(-1);
10591 (*dest)->any = source->any;
10592 cur = source->nsSet;
10593 last = NULL;
10594 while (cur != NULL) {
10595 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
10596 if (tmp == NULL)
10597 return(-1);
10598 tmp->value = cur->value;
10599 if (last == NULL)
10600 (*dest)->nsSet = tmp;
10601 else
10602 last->next = tmp;
10603 last = tmp;
10604 cur = cur->next;
10605 }
10606 if ((*dest)->negNsSet != NULL)
10607 xmlSchemaFreeWildcardNsSet((*dest)->negNsSet);
10608 if (source->negNsSet != NULL) {
10609 (*dest)->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
10610 if ((*dest)->negNsSet == NULL)
10611 return(-1);
10612 (*dest)->negNsSet->value = source->negNsSet->value;
10613 } else
10614 (*dest)->negNsSet = NULL;
10615 return(0);
10616}
10617
Daniel Veillard50355f02004-06-08 17:52:16 +000010618/**
10619 * xmlSchemaUnionWildcards:
10620 * @ctxt: the schema parser context
10621 * @completeWild: the first wildcard
10622 * @curWild: the second wildcard
10623 *
10624 * Unions the namespace constraints of the given wildcards.
10625 * @completeWild will hold the resulting union.
10626 * Returns a positive error code on failure, -1 in case of an
10627 * internal error, 0 otherwise.
10628 */
Daniel Veillard3646d642004-06-02 19:19:14 +000010629static int
10630xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
10631 xmlSchemaWildcardPtr completeWild,
10632 xmlSchemaWildcardPtr curWild)
10633{
10634 xmlSchemaWildcardNsPtr cur, curB, tmp;
10635
10636 /*
10637 * 1 If O1 and O2 are the same value, then that value must be the
10638 * value.
10639 */
10640 if ((completeWild->any == curWild->any) &&
10641 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
10642 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
10643
10644 if ((completeWild->negNsSet == NULL) ||
10645 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
10646
10647 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000010648 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000010649
10650 /*
10651 * Check equality of sets.
10652 */
10653 cur = completeWild->nsSet;
10654 while (cur != NULL) {
10655 found = 0;
10656 curB = curWild->nsSet;
10657 while (curB != NULL) {
10658 if (cur->value == curB->value) {
10659 found = 1;
10660 break;
10661 }
10662 curB = curB->next;
10663 }
10664 if (!found)
10665 break;
10666 cur = cur->next;
10667 }
10668 if (found)
10669 return(0);
10670 } else
10671 return(0);
10672 }
10673 }
10674 /*
10675 * 2 If either O1 or O2 is any, then any must be the value
10676 */
Daniel Veillard50355f02004-06-08 17:52:16 +000010677 if (completeWild->any != curWild->any) {
Daniel Veillard3646d642004-06-02 19:19:14 +000010678 if (completeWild->any == 0) {
10679 completeWild->any = 1;
10680 if (completeWild->nsSet != NULL) {
10681 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
10682 completeWild->nsSet = NULL;
10683 }
10684 if (completeWild->negNsSet != NULL) {
10685 xmlFree(completeWild->negNsSet);
10686 completeWild->negNsSet = NULL;
10687 }
10688 }
Daniel Veillard50355f02004-06-08 17:52:16 +000010689 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000010690 }
10691 /*
10692 * 3 If both O1 and O2 are sets of (namespace names or ·absent·),
10693 * then the union of those sets must be the value.
10694 */
10695 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
10696 int found;
10697 xmlSchemaWildcardNsPtr start;
10698
10699 cur = curWild->nsSet;
10700 start = completeWild->nsSet;
10701 while (cur != NULL) {
10702 found = 0;
10703 curB = start;
10704 while (curB != NULL) {
10705 if (cur->value == curB->value) {
10706 found = 1;
10707 break;
10708 }
10709 curB = curB->next;
10710 }
10711 if (!found) {
10712 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
10713 if (tmp == NULL)
10714 return (-1);
10715 tmp->value = cur->value;
10716 tmp->next = completeWild->nsSet;
10717 completeWild->nsSet = tmp;
10718 }
10719 cur = cur->next;
10720 }
10721
10722 return(0);
10723 }
10724 /*
10725 * 4 If the two are negations of different values (namespace names
10726 * or ·absent·), then a pair of not and ·absent· must be the value.
10727 */
10728 if ((completeWild->negNsSet != NULL) &&
10729 (curWild->negNsSet != NULL) &&
10730 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
10731 completeWild->negNsSet->value = NULL;
Daniel Veillard50355f02004-06-08 17:52:16 +000010732
10733 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +000010734 }
10735 /*
10736 * 5.
10737 */
10738 if (((completeWild->negNsSet != NULL) &&
10739 (completeWild->negNsSet->value != NULL) &&
10740 (curWild->nsSet != NULL)) ||
10741 ((curWild->negNsSet != NULL) &&
10742 (curWild->negNsSet->value != NULL) &&
10743 (completeWild->nsSet != NULL))) {
10744
10745 int nsFound, absentFound = 0;
10746
10747 if (completeWild->nsSet != NULL) {
10748 cur = completeWild->nsSet;
10749 curB = curWild->negNsSet;
10750 } else {
10751 cur = curWild->nsSet;
10752 curB = completeWild->negNsSet;
10753 }
10754 nsFound = 0;
10755 while (cur != NULL) {
10756 if (cur->value == NULL)
10757 absentFound = 1;
10758 else if (cur->value == curB->value)
10759 nsFound = 1;
10760 if (nsFound && absentFound)
10761 break;
10762 cur = cur->next;
10763 }
10764
10765 if (nsFound && absentFound) {
10766 /*
10767 * 5.1 If the set S includes both the negated namespace
10768 * name and ·absent·, then any must be the value.
10769 */
10770 completeWild->any = 1;
10771 if (completeWild->nsSet != NULL) {
10772 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
10773 completeWild->nsSet = NULL;
10774 }
10775 if (completeWild->negNsSet != NULL) {
10776 xmlFree(completeWild->negNsSet);
10777 completeWild->negNsSet = NULL;
10778 }
10779 } else if (nsFound && (!absentFound)) {
10780 /*
10781 * 5.2 If the set S includes the negated namespace name
10782 * but not ·absent·, then a pair of not and ·absent· must
10783 * be the value.
10784 */
10785 if (completeWild->nsSet != NULL) {
10786 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
10787 completeWild->nsSet = NULL;
10788 }
10789 if (completeWild->negNsSet == NULL) {
10790 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
10791 if (completeWild->negNsSet == NULL)
10792 return (-1);
10793 }
10794 completeWild->negNsSet->value = NULL;
10795 } else if ((!nsFound) && absentFound) {
10796 /*
10797 * 5.3 If the set S includes ·absent· but not the negated
10798 * namespace name, then the union is not expressible.
10799 */
10800 xmlSchemaPErr(ctxt, completeWild->node,
10801 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010802 "The union of the wilcard is not expressible.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +000010803 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000010804 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +000010805 } else if ((!nsFound) && (!absentFound)) {
10806 /*
10807 * 5.4 If the set S does not include either the negated namespace
10808 * name or ·absent·, then whichever of O1 or O2 is a pair of not
10809 * and a namespace name must be the value.
10810 */
10811 if (completeWild->negNsSet == NULL) {
10812 if (completeWild->nsSet != NULL) {
10813 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
10814 completeWild->nsSet = NULL;
10815 }
10816 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
10817 if (completeWild->negNsSet == NULL)
10818 return (-1);
10819 completeWild->negNsSet->value = curWild->negNsSet->value;
10820 }
10821 }
10822 return (0);
10823 }
10824 /*
10825 * 6.
10826 */
10827 if (((completeWild->negNsSet != NULL) &&
10828 (completeWild->negNsSet->value == NULL) &&
10829 (curWild->nsSet != NULL)) ||
10830 ((curWild->negNsSet != NULL) &&
10831 (curWild->negNsSet->value == NULL) &&
10832 (completeWild->nsSet != NULL))) {
10833
10834 if (completeWild->nsSet != NULL) {
10835 cur = completeWild->nsSet;
10836 } else {
10837 cur = curWild->nsSet;
10838 }
10839 while (cur != NULL) {
10840 if (cur->value == NULL) {
10841 /*
10842 * 6.1 If the set S includes ·absent·, then any must be the
10843 * value.
10844 */
10845 completeWild->any = 1;
10846 if (completeWild->nsSet != NULL) {
10847 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
10848 completeWild->nsSet = NULL;
10849 }
10850 if (completeWild->negNsSet != NULL) {
10851 xmlFree(completeWild->negNsSet);
10852 completeWild->negNsSet = NULL;
10853 }
10854 return (0);
10855 }
10856 cur = cur->next;
10857 }
10858 if (completeWild->negNsSet == NULL) {
10859 /*
10860 * 6.2 If the set S does not include ·absent·, then a pair of not
10861 * and ·absent· must be the value.
10862 */
10863 if (completeWild->nsSet != NULL) {
10864 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
10865 completeWild->nsSet = NULL;
10866 }
10867 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
10868 if (completeWild->negNsSet == NULL)
10869 return (-1);
10870 completeWild->negNsSet->value = NULL;
10871 }
10872 return (0);
10873 }
10874 return (0);
10875
10876}
10877
Daniel Veillard50355f02004-06-08 17:52:16 +000010878/**
10879 * xmlSchemaIntersectWildcards:
10880 * @ctxt: the schema parser context
10881 * @completeWild: the first wildcard
10882 * @curWild: the second wildcard
10883 *
10884 * Intersects the namespace constraints of the given wildcards.
10885 * @completeWild will hold the resulting intersection.
10886 * Returns a positive error code on failure, -1 in case of an
10887 * internal error, 0 otherwise.
10888 */
Daniel Veillard3646d642004-06-02 19:19:14 +000010889static int
10890xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
10891 xmlSchemaWildcardPtr completeWild,
10892 xmlSchemaWildcardPtr curWild)
10893{
William M. Brack803812b2004-06-03 02:11:24 +000010894 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000010895
10896 /*
10897 * 1 If O1 and O2 are the same value, then that value must be the
10898 * value.
10899 */
10900 if ((completeWild->any == curWild->any) &&
10901 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
10902 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
10903
10904 if ((completeWild->negNsSet == NULL) ||
10905 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
10906
10907 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000010908 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000010909
10910 /*
10911 * Check equality of sets.
10912 */
10913 cur = completeWild->nsSet;
10914 while (cur != NULL) {
10915 found = 0;
10916 curB = curWild->nsSet;
10917 while (curB != NULL) {
10918 if (cur->value == curB->value) {
10919 found = 1;
10920 break;
10921 }
10922 curB = curB->next;
10923 }
10924 if (!found)
10925 break;
10926 cur = cur->next;
10927 }
10928 if (found)
10929 return(0);
10930 } else
10931 return(0);
10932 }
10933 }
10934 /*
10935 * 2 If either O1 or O2 is any, then the other must be the value.
10936 */
10937 if ((completeWild->any != curWild->any) && (completeWild->any)) {
10938 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
10939 return(-1);
10940 return(0);
10941 }
10942 /*
10943 * 3 If either O1 or O2 is a pair of not and a value (a namespace
10944 * name or ·absent·) and the other is a set of (namespace names or
10945 * ·absent·), then that set, minus the negated value if it was in
10946 * the set, minus ·absent· if it was in the set, must be the value.
10947 */
10948 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
10949 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
10950 const xmlChar *neg;
10951
10952 if (completeWild->nsSet == NULL) {
10953 neg = completeWild->negNsSet->value;
10954 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
10955 return(-1);
10956 } else
10957 neg = curWild->negNsSet->value;
10958 /*
10959 * Remove absent and negated.
10960 */
10961 prev = NULL;
10962 cur = completeWild->nsSet;
10963 while (cur != NULL) {
10964 if (cur->value == NULL) {
10965 if (prev == NULL)
10966 completeWild->nsSet = cur->next;
10967 else
10968 prev->next = cur->next;
10969 xmlFree(cur);
10970 break;
10971 }
10972 prev = cur;
10973 cur = cur->next;
10974 }
10975 if (neg != NULL) {
10976 prev = NULL;
10977 cur = completeWild->nsSet;
10978 while (cur != NULL) {
10979 if (cur->value == neg) {
10980 if (prev == NULL)
10981 completeWild->nsSet = cur->next;
10982 else
10983 prev->next = cur->next;
10984 xmlFree(cur);
10985 break;
10986 }
10987 prev = cur;
10988 cur = cur->next;
10989 }
10990 }
10991
10992 return(0);
10993 }
10994 /*
10995 * 4 If both O1 and O2 are sets of (namespace names or ·absent·),
10996 * then the intersection of those sets must be the value.
10997 */
10998 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
10999 int found;
11000
11001 cur = completeWild->nsSet;
11002 prev = NULL;
11003 while (cur != NULL) {
11004 found = 0;
11005 curB = curWild->nsSet;
11006 while (curB != NULL) {
11007 if (cur->value == curB->value) {
11008 found = 1;
11009 break;
11010 }
11011 curB = curB->next;
11012 }
11013 if (!found) {
11014 if (prev == NULL)
11015 completeWild->nsSet = cur->next;
11016 else
11017 prev->next = cur->next;
11018 tmp = cur->next;
11019 xmlFree(cur);
11020 cur = tmp;
11021 continue;
11022 }
11023 prev = cur;
11024 cur = cur->next;
11025 }
11026
11027 return(0);
11028 }
11029 /* 5 If the two are negations of different namespace names,
11030 * then the intersection is not expressible
11031 */
11032 if ((completeWild->negNsSet != NULL) &&
11033 (curWild->negNsSet != NULL) &&
11034 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
11035 (completeWild->negNsSet->value != NULL) &&
11036 (curWild->negNsSet->value != NULL)) {
11037
11038 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011039 "The intersection of the wilcard is not expressible.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +000011040 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000011041 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +000011042 }
11043 /*
11044 * 6 If the one is a negation of a namespace name and the other
11045 * is a negation of ·absent·, then the one which is the negation
11046 * of a namespace name must be the value.
11047 */
11048 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
11049 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
11050 (completeWild->negNsSet->value == NULL)) {
11051 completeWild->negNsSet->value = curWild->negNsSet->value;
11052 }
11053 return(0);
11054}
11055
Daniel Veillard50355f02004-06-08 17:52:16 +000011056/**
11057 * xmlSchemaIsWildcardNsConstraintSubset:
11058 * @ctxt: the schema parser context
11059 * @wildA: the first wildcard
11060 * @wildB: the second wildcard
11061 *
11062 * Returns 1 if the namespace constraint of @wildA is an intensional
11063 * subset of @wildB, 0 otherwise.
11064 */
11065static int
Daniel Veillardc0826a72004-08-10 14:17:33 +000011066xmlSchemaIsWildcardNsConstraintSubset(xmlSchemaWildcardPtr wildA,
11067 xmlSchemaWildcardPtr wildB)
Daniel Veillard50355f02004-06-08 17:52:16 +000011068{
Daniel Veillard3646d642004-06-02 19:19:14 +000011069
Daniel Veillard50355f02004-06-08 17:52:16 +000011070 /*
11071 * Schema Component Constraint: Wildcard Subset
11072 */
11073 /*
11074 * 1 super must be any.
11075 */
11076 if (wildB->any)
11077 return (1);
11078 /*
11079 * 2.1 sub must be a pair of not and a namespace name or ·absent·.
11080 * 2.2 super must be a pair of not and the same value.
11081 */
11082 if ((wildA->negNsSet != NULL) &&
11083 (wildB->negNsSet != NULL) &&
11084 (wildA->negNsSet->value == wildA->negNsSet->value))
11085 return (1);
11086 /*
11087 * 3.1 sub must be a set whose members are either namespace names or ·absent·.
11088 */
11089 if (wildA->nsSet != NULL) {
11090 /*
11091 * 3.2.1 super must be the same set or a superset thereof.
11092 */
11093 if (wildB->nsSet != NULL) {
11094 xmlSchemaWildcardNsPtr cur, curB;
11095 int found = 0;
11096
11097 cur = wildA->nsSet;
11098 while (cur != NULL) {
11099 found = 0;
11100 curB = wildB->nsSet;
11101 while (curB != NULL) {
11102 if (cur->value == curB->value) {
11103 found = 1;
11104 break;
11105 }
11106 curB = curB->next;
11107 }
11108 if (!found)
11109 return (0);
11110 cur = cur->next;
11111 }
11112 if (found)
11113 return (1);
11114 } else if (wildB->negNsSet != NULL) {
11115 xmlSchemaWildcardNsPtr cur;
11116 /*
11117 * 3.2.2 super must be a pair of not and a namespace name or
11118 * ·absent· and that value must not be in sub's set.
11119 */
11120 cur = wildA->nsSet;
11121 while (cur != NULL) {
11122 if (cur->value == wildB->negNsSet->value)
11123 return (0);
11124 cur = cur->next;
11125 }
11126 return (1);
11127 }
11128 }
11129 return (0);
11130}
11131
11132/**
11133 * xmlSchemaBuildCompleteAttributeWildcard:
11134 * @ctxt: the schema parser context
11135 * @attrs: the attribute list
11136 * @completeWild: the resulting complete wildcard
11137 *
11138 * Returns -1 in case of an internal error, 0 otherwise.
11139 */
11140static int
11141xmlSchemaBuildCompleteAttributeWildcard(xmlSchemaParserCtxtPtr ctxt,
11142 xmlSchemaAttributePtr attrs,
11143 xmlSchemaWildcardPtr *completeWild)
Daniel Veillard3646d642004-06-02 19:19:14 +000011144{
11145 while (attrs != NULL) {
11146 if (attrs->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
11147 xmlSchemaAttributeGroupPtr group;
11148
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011149 group = (xmlSchemaAttributeGroupPtr) attrs;
11150 /*
11151 * Handle attribute group references.
11152 */
11153 if (group->ref != NULL) {
11154 if (group->refItem == NULL) {
11155 /*
11156 * TODO: Should we raise a warning here?
11157 */
11158 /*
11159 * The referenced attribute group definition could not
11160 * be resolved beforehand, so skip.
11161 */
11162 attrs = attrs->next;
11163 continue;
11164 } else
11165 group = group->refItem;
11166 }
11167 /*
11168 * For every attribute group definition, an intersected wildcard
11169 * will be created (assumed that a wildcard exists on the
11170 * particular attr. gr. def. or on any contained attr. gr. def
11171 * at all).
11172 * The flag XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED ensures
11173 * that the intersection will be performed only once.
11174 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011175 if ((group->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
11176 if (group->attributes != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000011177 if (xmlSchemaBuildCompleteAttributeWildcard(ctxt,
11178 group->attributes, &group->attributeWildcard) == -1)
11179 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000011180 }
11181 group->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
11182 }
11183 if (group->attributeWildcard != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000011184 if (*completeWild == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011185 /*
11186 * Copy the first encountered wildcard as context, except for the annotation.
11187 */
Daniel Veillard50355f02004-06-08 17:52:16 +000011188 *completeWild = xmlSchemaAddWildcard(ctxt);
11189 (*completeWild)->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
11190 if (xmlSchemaCloneWildcardNsConstraints(ctxt,
11191 completeWild, group->attributeWildcard) == -1)
11192 return (-1);
11193 (*completeWild)->processContents = group->attributeWildcard->processContents;
Daniel Veillard3646d642004-06-02 19:19:14 +000011194 /*
11195 * Although the complete wildcard might not correspond to any
11196 * node in the schema, we will save this context node.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011197 * TODO: Hmm, is this sane?
Daniel Veillard3646d642004-06-02 19:19:14 +000011198 */
Daniel Veillard50355f02004-06-08 17:52:16 +000011199 (*completeWild)->node = group->attributeWildcard->node;
11200
11201 } else if (xmlSchemaIntersectWildcards(ctxt, *completeWild, group->attributeWildcard) == -1) {
11202 xmlSchemaFreeWildcard(*completeWild);
11203 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000011204 }
11205 }
11206 }
11207 attrs = attrs->next;
11208 }
11209
Daniel Veillard50355f02004-06-08 17:52:16 +000011210 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000011211}
11212
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011213static int
11214xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributePtr item,
11215 int *fixed,
11216 const xmlChar **value,
11217 xmlSchemaValPtr *val)
11218{
11219 *fixed = 0;
11220 *value = NULL;
11221 if (val != 0)
11222 *val = NULL;
11223
11224 if (item->defValue == NULL)
11225 item = item->refDecl;
11226
11227 if (item == NULL)
11228 return (0);
11229
11230 if (item->defValue != NULL) {
11231 *value = item->defValue;
11232 if (val != 0)
11233 *val = item->defVal;
11234 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
11235 *fixed = 1;
11236 return (1);
11237 }
11238 return (0);
11239}
Daniel Veillard3646d642004-06-02 19:19:14 +000011240/**
11241 * xmlSchemaMatchesWildcardNs:
11242 * @wild: the wildcard
11243 * @ns: the namespace
11244 *
11245 *
11246 * Returns 1 if the given namespace matches the wildcard,
11247 * 0 otherwise.
11248 */
11249static int
11250xmlSchemaMatchesWildcardNs(xmlSchemaWildcardPtr wild, const xmlChar* ns)
11251{
11252 if (wild == NULL)
11253 return(0);
11254
11255 if (wild->any)
11256 return(1);
11257 else if (wild->nsSet != NULL) {
11258 xmlSchemaWildcardNsPtr cur;
11259
11260 cur = wild->nsSet;
11261 while (cur != NULL) {
11262 if (xmlStrEqual(cur->value, ns))
11263 return(1);
11264 cur = cur->next;
11265 }
11266 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
11267 (!xmlStrEqual(wild->negNsSet->value, ns)))
11268 return(1);
11269
11270 return(0);
11271}
11272
11273/**
11274 * xmlSchemaBuildAttributeValidation:
11275 * @ctxt: the schema parser context
11276 * @type: the complex type definition
11277 *
11278 *
11279 * Builds the wildcard and the attribute uses on the given complex type.
11280 * Returns -1 if an internal error occurs, 0 otherwise.
11281 */
11282static int
11283xmlSchemaBuildAttributeValidation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaTypePtr type)
11284{
11285 xmlSchemaTypePtr baseType = NULL;
11286 xmlSchemaAttributeLinkPtr cur, base, tmp, id = NULL, prev = NULL, uses = NULL,
William M. Brack803812b2004-06-03 02:11:24 +000011287 lastUse = NULL, lastBaseUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000011288 xmlSchemaAttributePtr attrs;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011289 xmlSchemaTypePtr anyType;
Daniel Veillard50355f02004-06-08 17:52:16 +000011290 int baseIsAnyType = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011291 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000011292 int err = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000011293
Daniel Veillard01fa6152004-06-29 17:04:39 +000011294 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Daniel Veillard3646d642004-06-02 19:19:14 +000011295 /*
11296 * Complex Type Definition with complex content Schema Component.
11297 *
11298 * Attribute uses.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011299 * TODO: Add checks for absent referenced attribute declarations and
11300 * simple types.
Daniel Veillard3646d642004-06-02 19:19:14 +000011301 */
11302 if (type->attributeUses != NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011303 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011304 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillard3646d642004-06-02 19:19:14 +000011305 "attribute uses already builded.\n",
11306 NULL, NULL);
11307 return (-1);
11308 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011309 if (type->baseType == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011310 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011311 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011312 "complex type '%s' has no base type.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011313 type->name, NULL);
11314 return (-1);
11315 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011316 baseType = type->baseType;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011317 if (baseType == anyType)
11318 baseIsAnyType = 1;
11319 /*
11320 * Inherit the attribute uses of the base type.
11321 */
11322 /*
11323 * NOTE: It is allowed to "extend" the anyType complex type.
11324 */
11325 if (!baseIsAnyType) {
11326 if (baseType != NULL) {
11327 for (cur = baseType->attributeUses; cur != NULL; cur = cur->next) {
11328 tmp = (xmlSchemaAttributeLinkPtr)
11329 xmlMalloc(sizeof(xmlSchemaAttributeLink));
11330 if (tmp == NULL) {
11331 xmlSchemaPErrMemory(ctxt,
11332 "building attribute uses of complexType", NULL);
11333 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000011334 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011335 tmp->attr = cur->attr;
11336 tmp->next = NULL;
11337 if (type->attributeUses == NULL) {
11338 type->attributeUses = tmp;
11339 } else
11340 lastBaseUse->next = tmp;
11341 lastBaseUse = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000011342 }
11343 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011344 }
11345 if ((type->subtypes != NULL) &&
11346 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
11347 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011348 /*
11349 * type --> (<simpleContent>|<complexContent>)
11350 * --> (<restriction>|<extension>) --> attributes
11351 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011352 attrs = type->subtypes->subtypes->attributes;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011353 } else {
11354 /* Short hand form of the complexType. */
11355 attrs = type->attributes;
11356 }
11357 /*
11358 * Handle attribute wildcards.
11359 */
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000011360 err = xmlSchemaBuildCompleteAttributeWildcard(ctxt,
11361 attrs, &type->attributeWildcard);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011362 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011363 * NOTE: During the parse time, the wildcard is created on the complexType
11364 * directly, if encountered in a <restriction> or <extension> element.
Daniel Veillard01fa6152004-06-29 17:04:39 +000011365 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011366 if (err == -1) {
11367 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
11368 "Internal error: xmlSchemaBuildAttributeValidation: "
11369 "failed to build an intersected attribute wildcard.\n",
11370 NULL, NULL);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000011371 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011372 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011373
11374 if ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
11375 ((baseIsAnyType) ||
11376 ((baseType != NULL) &&
11377 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
11378 (baseType->attributeWildcard != NULL)))) {
11379 if (type->attributeWildcard != NULL) {
11380 /*
11381 * Union the complete wildcard with the base wildcard.
11382 */
11383 if (xmlSchemaUnionWildcards(ctxt, type->attributeWildcard,
11384 baseType->attributeWildcard) == -1)
11385 return (-1);
11386 } else {
11387 /*
11388 * Just inherit the wildcard.
11389 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011390 /*
11391 * NOTE: This is the only case where an attribute
11392 * wildcard is shared.
11393 */
11394 if (type->flags & XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD)
11395 type->flags ^= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011396 type->attributeWildcard = baseType->attributeWildcard;
Daniel Veillard50355f02004-06-08 17:52:16 +000011397 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011398 }
11399
11400 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
11401 if (type->attributeWildcard != NULL) {
11402 /*
11403 * Derivation Valid (Restriction, Complex)
11404 * 4.1 The {base type definition} must also have one.
11405 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011406 if (baseType->attributeWildcard == NULL) {
11407 xmlSchemaPCustomErr(ctxt,
11408 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
11409 NULL, type, NULL,
11410 "The type has an attribute wildcard, "
11411 "but the base type %s does not have one",
11412 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11413 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011414 return (1);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011415 } else if (xmlSchemaIsWildcardNsConstraintSubset(
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011416 type->attributeWildcard, baseType->attributeWildcard) == 0) {
11417 /* 4.2 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011418 xmlSchemaPCustomErr(ctxt,
11419 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
11420 NULL, type, NULL,
11421 "The attribute wildcard is not a valid "
11422 "subset of the wildcard in the base type %s",
11423 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11424 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011425 return (1);
11426 }
11427 /* 4.3 Unless the {base type definition} is the ·ur-type
11428 * definition·, the complex type definition's {attribute
11429 * wildcard}'s {process contents} must be identical to or
11430 * stronger than the {base type definition}'s {attribute
11431 * wildcard}'s {process contents}, where strict is stronger
11432 * than lax is stronger than skip.
11433 */
11434 if ((type->baseType != anyType) &&
11435 (type->attributeWildcard->processContents <
11436 baseType->attributeWildcard->processContents)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011437 xmlSchemaPCustomErr(ctxt,
11438 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
11439 NULL, type, NULL,
11440 "The 'process contents' of the attribute wildcard is weaker than "
11441 "the one in the base type %s",
11442 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11443 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011444 return (1);
11445 }
11446 }
11447 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
11448 /*
11449 * Derivation Valid (Extension)
11450 * At this point the type and the base have both, either
11451 * no wildcard or a wildcard.
11452 */
11453 if ((baseType->attributeWildcard != NULL) &&
11454 (baseType->attributeWildcard != type->attributeWildcard)) {
11455 /* 1.3 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011456 if (xmlSchemaIsWildcardNsConstraintSubset(
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011457 baseType->attributeWildcard, type->attributeWildcard) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011458 xmlSchemaPCustomErr(ctxt,
11459 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
11460 NULL, type, NULL,
11461 "The attribute wildcard is not a valid "
11462 "superset of the one in the base type %s",
11463 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11464 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011465 return (1);
11466 }
11467 }
11468 }
11469
Daniel Veillard3646d642004-06-02 19:19:14 +000011470 /*
11471 * Gather attribute uses defined by this type.
11472 */
11473 if (attrs != NULL) {
11474 if (xmlSchemaBuildAttributeUsesOwned(ctxt, attrs,
11475 &uses, &lastUse) == -1) {
11476 return (-1);
11477 }
11478 }
11479 /* 3.4.6 -> Complex Type Definition Properties Correct 4.
11480 * "Two distinct attribute declarations in the {attribute uses} must
11481 * not have identical {name}s and {target namespace}s."
11482 *
11483 * For "extension" this is done further down.
11484 */
11485 if ((uses != NULL) && ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
11486 cur = uses;
11487 while (cur != NULL) {
11488 tmp = cur->next;
11489 while (tmp != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011490 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
11491 xmlSchemaGetAttrName(tmp->attr))) &&
11492 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
11493 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
11494
11495 xmlSchemaPAttrUseErr(ctxt,
11496 XML_SCHEMAP_CT_PROPS_CORRECT_4,
11497 NULL, type, NULL, cur->attr,
11498 "Duplicate attribute use %s specified",
11499 xmlSchemaFormatNsUriLocal(&str,
11500 xmlSchemaGetAttrTargetNsURI(tmp->attr),
11501 xmlSchemaGetAttrName(tmp->attr))
11502 );
11503 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000011504 break;
11505 }
11506 tmp = tmp->next;
11507 }
11508 cur = cur->next;
11509 }
11510 }
11511 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
11512 /*
11513 * Derive by restriction.
11514 */
11515 if (baseIsAnyType) {
11516 type->attributeUses = uses;
11517 } else {
11518 int found;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011519 const xmlChar *bEffValue;
11520 int effFixed;
Daniel Veillard3646d642004-06-02 19:19:14 +000011521
11522 cur = uses;
11523 while (cur != NULL) {
11524 found = 0;
11525 base = type->attributeUses;
11526 while (base != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011527 if (xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
11528 xmlSchemaGetAttrName(base->attr)) &&
11529 xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
11530 xmlSchemaGetAttrTargetNsURI(base->attr))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011531
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011532 found = 1;
11533
Daniel Veillard3646d642004-06-02 19:19:14 +000011534 if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
11535 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
11536 /*
11537 * derivation-ok-restriction 2.1.1
Daniel Veillardc0826a72004-08-10 14:17:33 +000011538 */
11539 xmlSchemaPAttrUseErr(ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000011540 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011541 NULL, type, NULL, cur->attr,
11542 "The 'optional' use is inconsistent with a matching "
11543 "'required' use of the base type", NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000011544 } else if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
11545 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
11546 /*
11547 * derivation-ok-restriction 3
11548 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011549 xmlSchemaPCustomErr(ctxt,
11550 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
11551 NULL, type, NULL,
11552 "A matching attribute use for the 'required' "
11553 "attribute use %s of the base type is missing",
11554 xmlSchemaFormatNsUriLocal(&str,
11555 xmlSchemaGetAttrTargetNsURI(base->attr),
11556 xmlSchemaGetAttrName(base->attr)));
11557 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000011558 } else {
11559 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011560 * 2.1.3 [Definition:] Let the effective value
11561 * constraint of an attribute use be its {value
11562 * constraint}, if present, otherwise its {attribute
11563 * declaration}'s {value constraint} .
11564 */
11565 xmlSchemaGetEffectiveValueConstraint(base->attr, &effFixed,
11566 &bEffValue, 0);
11567 /*
11568 * 2.1.3 ... one of the following must be true
11569 *
11570 * 2.1.3.1 B's ·effective value constraint· is
11571 * ·absent· or default.
11572 */
11573 if ((bEffValue != NULL) &&
11574 (effFixed == 1)) {
11575 const xmlChar *rEffValue = NULL;
11576
11577 xmlSchemaGetEffectiveValueConstraint(base->attr, &effFixed,
11578 &rEffValue, 0);
11579 /*
11580 * 2.1.3.2 R's ·effective value constraint· is
11581 * fixed with the same string as B's.
11582 */
11583 if ((effFixed == 0) ||
11584 (! xmlStrEqual(rEffValue, bEffValue))) {
11585 xmlSchemaPAttrUseErr(ctxt,
11586 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
11587 NULL, type, NULL, cur->attr,
11588 "The effective value constraint of the "
11589 "attribute use is inconsistent with "
11590 "its correspondent of the base type",
11591 NULL);
11592 }
11593 }
11594 /*
11595 * TODO: derivation-ok-restriction 2.1.2 ({type definition} must be validly derived)
11596 */
11597 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000011598 * Override the attribute use.
11599 */
11600 base->attr = cur->attr;
11601 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011602
Daniel Veillard3646d642004-06-02 19:19:14 +000011603 break;
11604 }
11605 base = base->next;
11606 }
11607
11608 if (!found) {
11609 if (cur->attr->occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
11610 /*
11611 * derivation-ok-restriction 2.2
11612 */
11613 if ((type->attributeWildcard != NULL) &&
11614 xmlSchemaMatchesWildcardNs(type->attributeWildcard,
11615 cur->attr->targetNamespace))
11616 found = 1;
11617
11618 if (!found) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011619 xmlSchemaPAttrUseErr(ctxt,
11620 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
11621 NULL, type, NULL, cur->attr,
11622 "Neither a matching attribute use, "
11623 "nor a matching wildcard in the base type does exist",
11624 NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000011625 } else {
11626 /*
11627 * Add the attribute use.
11628 *
11629 * Note that this may lead to funny derivation error reports, if
11630 * multiple equal attribute uses exist; but this is not
11631 * allowed anyway, and it will be reported beforehand.
11632 */
11633 tmp = cur;
11634 if (prev != NULL)
11635 prev->next = cur->next;
11636 else
11637 uses = cur->next;
11638 cur = cur->next;
11639 if (type->attributeUses == NULL) {
11640 type->attributeUses = tmp;
11641 } else
11642 lastBaseUse->next = tmp;
11643 lastBaseUse = tmp;
11644
11645 continue;
11646 }
11647 }
11648 }
11649 prev = cur;
11650 cur = cur->next;
11651 }
11652 if (uses != NULL)
11653 xmlSchemaFreeAttributeUseList(uses);
11654 }
11655 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
11656 /*
11657 * The spec allows only appending, and not other kinds of extensions.
11658 *
11659 * This ensures: Schema Component Constraint: Derivation Valid (Extension) : 1.2
11660 */
11661 if (uses != NULL) {
11662 if (type->attributeUses == NULL) {
11663 type->attributeUses = uses;
11664 } else
11665 lastBaseUse->next = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000011666 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011667 } else {
11668 /*
Daniel Veillard50355f02004-06-08 17:52:16 +000011669 * Derive implicitely from the ur-type.
11670 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011671 type->attributeUses = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000011672 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011673 /*
11674 * 3.4.6 -> Complex Type Definition Properties Correct
11675 */
11676 if (type->attributeUses != NULL) {
11677 cur = type->attributeUses;
11678 prev = NULL;
11679 while (cur != NULL) {
11680 /*
11681 * 4. Two distinct attribute declarations in the {attribute uses} must
11682 * not have identical {name}s and {target namespace}s.
Daniel Veillard50355f02004-06-08 17:52:16 +000011683 *
Daniel Veillard3646d642004-06-02 19:19:14 +000011684 * Note that this was already done for "restriction" and types derived from
11685 * the ur-type.
Daniel Veillard50355f02004-06-08 17:52:16 +000011686 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011687 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
11688 tmp = cur->next;
11689 while (tmp != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011690 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
11691 xmlSchemaGetAttrName(tmp->attr))) &&
11692 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
11693 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011694
Daniel Veillardc0826a72004-08-10 14:17:33 +000011695 xmlSchemaPAttrUseErr(ctxt,
11696 XML_SCHEMAP_CT_PROPS_CORRECT_4,
11697 NULL, type, NULL, tmp->attr,
11698 "Duplicate attribute use specified", NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000011699 break;
11700 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011701 tmp = tmp->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000011702 }
11703 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011704 /*
11705 * 5. Two distinct attribute declarations in the {attribute uses} must
11706 * not have {type definition}s which are or are derived from ID.
11707 */
11708 if ((cur->attr->subtypes != NULL) &&
Daniel Veillard01fa6152004-06-29 17:04:39 +000011709 (xmlSchemaIsDerivedFromBuiltInType(ctxt, (xmlSchemaTypePtr) cur->attr, XML_SCHEMAS_ID))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011710 if (id != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011711 xmlSchemaPAttrUseErr(ctxt,
11712 XML_SCHEMAP_CT_PROPS_CORRECT_5,
11713 NULL, type, NULL, cur->attr,
11714 "There must not exist more than one attribute use, "
11715 "declared of type 'ID' or derived from it",
11716 NULL);
11717 FREE_AND_NULL(str)
Daniel Veillard50355f02004-06-08 17:52:16 +000011718 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011719 id = cur;
11720 }
11721 /*
11722 * Remove "prohibited" attribute uses. The reason this is done at this late
11723 * stage is to be able to catch dublicate attribute uses. So we had to keep
11724 * prohibited uses in the list as well.
11725 */
11726 if (cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
11727 tmp = cur;
11728 if (prev == NULL)
11729 type->attributeUses = cur->next;
11730 else
11731 prev->next = cur->next;
11732 cur = cur->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000011733 xmlFree(tmp);
Daniel Veillard3646d642004-06-02 19:19:14 +000011734 } else {
11735 prev = cur;
11736 cur = cur->next;
11737 }
11738 }
11739 }
11740 /*
11741 * TODO: This check should be removed if we are 100% sure of
11742 * the base type attribute uses already being built.
11743 */
11744 if ((baseType != NULL) && (!baseIsAnyType) &&
11745 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
11746 (baseType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011747 xmlSchemaPErr(ctxt, baseType->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011748 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011749 "attribute uses not builded on base type '%s'.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +000011750 baseType->name, NULL);
11751 }
11752 return (0);
11753}
11754
11755/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000011756 * xmlSchemaTypeFinalContains:
11757 * @schema: the schema
11758 * @type: the type definition
11759 * @final: the final
11760 *
11761 * Evaluates if a type definition contains the given "final".
11762 * This does take "finalDefault" into account as well.
11763 *
11764 * Returns 1 if the type does containt the given "final",
11765 * 0 otherwise.
11766 */
11767static int
11768xmlSchemaTypeFinalContains(xmlSchemaPtr schema, xmlSchemaTypePtr type, int final)
11769{
11770 int tfinal = final, tflags = type->flags;
11771
11772 if (type == NULL)
11773 return (0);
11774 if (type->flags & XML_SCHEMAS_TYPE_FINAL_DEFAULT) {
11775 switch (final) {
11776 case XML_SCHEMAS_TYPE_FINAL_RESTRICTION:
11777 tfinal = XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
11778 break;
11779 case XML_SCHEMAS_TYPE_FINAL_EXTENSION:
11780 tfinal = XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
11781 break;
11782 case XML_SCHEMAS_TYPE_FINAL_LIST:
11783 tfinal = XML_SCHEMAS_FINAL_DEFAULT_LIST;
11784 break;
11785 case XML_SCHEMAS_TYPE_FINAL_UNION:
11786 tfinal = XML_SCHEMAS_FINAL_DEFAULT_UNION;
11787 break;
11788 }
11789 tflags = schema->flags;
11790 }
11791 if (tflags & tfinal)
11792 return (1);
11793 else
11794 return (0);
11795
11796}
11797
11798/**
11799 * xmlSchemaGetUnionSimpleTypeMemberTypes:
11800 * @type: the Union Simple Type
11801 *
11802 * Returns a list of member types of @type if existing,
11803 * returns NULL otherwise.
11804 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011805static xmlSchemaTypeLinkPtr
Daniel Veillard01fa6152004-06-29 17:04:39 +000011806xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
11807{
11808 while (type != NULL) {
11809 if (type->memberTypes != NULL)
11810 return (type->memberTypes);
11811 else
11812 type = type->baseType;
11813 }
11814 return (NULL);
11815}
11816
11817/**
11818 * xmlSchemaGetListSimpleTypeItemType:
11819 * @type: the simple type definition
11820 *
11821 * Returns the item type definition of the list simple type.
11822 */
11823static xmlSchemaTypePtr
11824xmlSchemaGetListSimpleTypeItemType(xmlSchemaTypePtr type)
11825{
11826 if ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)
11827 return (NULL);
11828 /*
11829 * Note: In libxml2, the built-in types do not reflect
11830 * the datatype hierarchy (yet?) - we have to treat them
11831 * in a special way.
11832 */
11833 if (type->type == XML_SCHEMA_TYPE_BASIC)
11834 return (xmlSchemaGetBuiltInListSimpleTypeItemType(type));
11835 if (type->subtypes->type == XML_SCHEMA_TYPE_LIST)
11836 /* 1 If the <list> alternative is chosen, then the type
11837 * definition ·resolved· to by the ·actual value· of the
11838 * itemType [attribute] of <list>, if present, otherwise
11839 * the type definition corresponding to the <simpleType>
11840 * among the [children] of <list>.
11841 */
11842 return (type->subtypes->subtypes);
11843 else {
11844 /* 2 If the <restriction> option is chosen, then the
11845 * {item type definition} of the {base type definition}.
11846 */
11847 return (xmlSchemaGetListSimpleTypeItemType(type->baseType));
11848 }
11849}
11850
11851/**
11852 * xmlSchemaCheckCOSSTDerivedOK:
11853 * @type: the derived simple type definition
11854 * @baseType: the base type definition
11855 *
11856 * Checks wheter @type can be validly
11857 * derived from @baseType.
11858 *
11859 * Returns 0 on success, an positive error code otherwise.
11860 */
11861static int
11862xmlSchemaCheckCOSSTDerivedOK(xmlSchemaPtr schema,
11863 xmlSchemaTypePtr type,
11864 xmlSchemaTypePtr baseType,
11865 int subset)
11866{
11867 /*
11868 * Schema Component Constraint: Type Derivation OK (Simple)
11869 *
11870 *
11871 * 1 They are the same type definition.
11872 * TODO: The identy check might have to be more complex than this.
11873 */
11874 if (type == baseType)
11875 return (0);
11876 /*
11877 * 2.1 restriction is not in the subset, or in the {final}
11878 * of its own {base type definition};
11879 */
11880 if ((subset & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) ||
11881 (xmlSchemaTypeFinalContains(schema,
11882 type->baseType, XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
11883 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
11884 }
11885 /* 2.2 */
11886 if (type->baseType == baseType) {
11887 /*
11888 * 2.2.1 D's ·base type definition· is B.
11889 */
11890 return (0);
11891 }
11892 /*
11893 * 2.2.2 D's ·base type definition· is not the ·ur-type definition·
11894 * and is validly derived from B given the subset, as defined by this
11895 * constraint.
11896 */
11897 if ((type->baseType != xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE)) &&
11898 (xmlSchemaCheckCOSSTDerivedOK(schema, type->baseType, baseType, subset) == 0)) {
11899 return (0);
11900 }
11901 /*
11902 * 2.2.3 D's {variety} is list or union and B is the ·simple ur-type
11903 * definition·.
11904 */
11905 if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
11906 (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)) &&
11907 (baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE))) {
11908 return (0);
11909 }
11910 /*
11911 * 2.2.4 B's {variety} is union and D is validly derived from a type
11912 * definition in B's {member type definitions} given the subset, as
11913 * defined by this constraint.
11914 *
11915 * NOTE: This seems not to involve built-in types, since there is no
11916 * built-in Union Simple Type.
11917 */
11918 if (baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
11919 xmlSchemaTypeLinkPtr cur;
11920
11921 cur = baseType->memberTypes;
11922 while (cur != NULL) {
11923 if (xmlSchemaCheckCOSSTDerivedOK(schema, type,
11924 cur->type, subset) == 0)
11925 return (0);
11926 cur = cur->next;
11927 }
11928 }
11929
11930 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
11931}
11932
11933
11934/**
11935 * xmlSchemaCheckSTPropsCorrect:
11936 * @ctxt: the schema parser context
11937 * @type: the simple type definition
11938 *
11939 * Checks st-props-correct.
11940 *
11941 * Returns 0 if the properties are correct,
11942 * if not, a positive error code and -1 on internal
11943 * errors.
11944 */
11945static int
11946xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
11947 xmlSchemaTypePtr type)
11948{
11949 xmlSchemaTypePtr baseType = type->baseType, anySimpleType,
11950 anyType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011951 xmlChar *str = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011952
Daniel Veillardc0826a72004-08-10 14:17:33 +000011953 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011954 /*
11955 * Schema Component Constraint: Simple Type Definition Properties Correct
11956 *
11957 * NOTE: This is somehow redundant, since we actually built a simple type
11958 * to have all the needed information; this acts as an self test.
11959 */
11960 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
11961 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
11962 /*
11963 * TODO: 1 The values of the properties of a simple type definition must be as
11964 * described in the property tableau in Datatype definition, modulo the
11965 * impact of Missing Sub-components (§5.3).
11966 */
11967 /* Base type: If the datatype has been ·derived· by ·restriction·
11968 * then the Simple Type Definition component from which it is ·derived·,
11969 * otherwise the Simple Type Definition for anySimpleType (§4.1.6).
11970 */
11971 if (baseType == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011972 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011973 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011974 NULL, type, NULL,
11975 "No base type existent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011976 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
11977 }
11978 if ((baseType->type != XML_SCHEMA_TYPE_SIMPLE) &&
11979 ((baseType->type != XML_SCHEMA_TYPE_BASIC) ||
11980 (baseType == anyType))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011981 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011982 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011983 NULL, type, NULL,
11984 "The base type %s is not a simple type",
11985 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11986 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011987 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
11988 }
11989 if ((baseType != anySimpleType) &&
11990 (type->subtypes->type != XML_SCHEMA_TYPE_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011991 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011992 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011993 NULL, type, NULL,
11994 "A type, derived by list or union, must have"
11995 "the simple ur-type definition as base type, not %s",
11996 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11997 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011998 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
11999 }
12000 /*
12001 * Variety: One of {atomic, list, union}.
12002 */
12003 if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
12004 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) &&
12005 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012006 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012007 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012008 NULL, type, NULL,
12009 "The variety is absent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012010 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
12011 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000012012 /* TODO: Finish this. Hmm, is this finished? */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012013
12014 /*
12015 * 2 All simple type definitions must be derived ultimately from the ·simple
12016 * ur-type definition (so· circular definitions are disallowed). That is, it
12017 * must be possible to reach a built-in primitive datatype or the ·simple
12018 * ur-type definition· by repeatedly following the {base type definition}.
12019 */
12020 baseType = type->baseType;
12021 while ((baseType != NULL) && (baseType->type != XML_SCHEMA_TYPE_BASIC)) {
12022 if (baseType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
12023 xmlSchemaTypeFixup(baseType, ctxt, NULL);
12024 if (baseType == anySimpleType)
12025 break;
12026 else if (baseType == type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012027 xmlSchemaPCustomErr(ctxt,
12028 XML_SCHEMAP_ST_PROPS_CORRECT_2,
12029 NULL, type, NULL,
12030 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012031 return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
12032 }
12033 baseType = baseType->baseType;
12034 }
12035 /*
12036 * 3 The {final} of the {base type definition} must not contain restriction.
12037 */
12038 if (xmlSchemaTypeFinalContains(ctxt->schema, baseType,
12039 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012040 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012041 XML_SCHEMAP_ST_PROPS_CORRECT_3,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012042 NULL, type, NULL,
12043 "The 'final' of its base type %s must not contain "
12044 "'restriction'",
12045 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
12046 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012047 return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
12048 }
12049 return (0);
12050}
12051
12052/**
12053 * xmlSchemaCheckDerivationValidSimpleRestriction:
12054 * @ctxt: the schema parser context
12055 * @type: the simple type definition
12056 *
12057 * Checks if the given @type (simpleType) is derived
12058 * validly by restriction.
12059 *
12060 * Returns -1 on internal errors, 0 if the type is validly derived,
12061 * a positive error code otherwise.
12062 */
12063static int
12064xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012065 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012066{
Daniel Veillardc0826a72004-08-10 14:17:33 +000012067 xmlChar *str = NULL;
12068
12069 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012070
12071 if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
12072 xmlSchemaPErr(ctxt, type->node,
12073 XML_ERR_INTERNAL_ERROR,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012074 "xmlSchemaCheckDerivationValidSimpleRestriction: The given "
12075 "type '%s' is not a user-derived simpleType.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012076 type->name, NULL);
12077 return (-1);
12078 }
12079
12080 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
12081 xmlSchemaTypePtr primitive;
12082 /*
12083 * 1.1 The {base type definition} must be an atomic simple
12084 * type definition or a built-in primitive datatype.
12085 */
12086 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012087 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012088 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012089 NULL, type, NULL,
12090 "The base type %s is not an atomic simple type",
12091 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
12092 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012093 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
12094 }
12095 /* 1.2 The {final} of the {base type definition} must not contain
12096 * restriction.
12097 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000012098 /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012099 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
12100 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012101 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012102 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012103 NULL, type, NULL,
12104 "The final of its base type %s must not contain 'restriction'",
12105 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
12106 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012107 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
12108 }
12109
12110 /*
12111 * 1.3.1 DF must be an allowed constraining facet for the {primitive
12112 * type definition}, as specified in the appropriate subsection of 3.2
12113 * Primitive datatypes.
12114 */
12115 if (type->facets != NULL) {
12116 xmlSchemaFacetPtr facet;
12117 int ok = 1;
12118
12119 primitive = xmlSchemaGetPrimitiveType(type);
12120 if (primitive == NULL) {
12121 xmlSchemaPErr(ctxt, type->node,
12122 XML_ERR_INTERNAL_ERROR,
12123 "xmlSchemaCheckDerivationValidSimpleRestriction: failed "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012124 "to get primitive type of type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012125 type->name, NULL);
12126 return (-1);
12127 }
12128 facet = type->facets;
12129 do {
12130 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012131 ok = 0;
12132 xmlSchemaPIllegalFacetAtomicErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012133 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012134 NULL, type, primitive, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012135 }
12136 facet = facet->next;
12137 } while (facet != NULL);
12138 if (ok == 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +000012139 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012140 }
12141 /*
12142 * TODO: 1.3.2 (facet derivation)
12143 */
12144 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
12145 xmlSchemaTypePtr itemType = NULL;
12146
12147 itemType = xmlSchemaGetListSimpleTypeItemType(type);
12148 if (itemType == NULL) {
12149 xmlSchemaPErr(ctxt, type->node,
12150 XML_ERR_INTERNAL_ERROR,
12151 "Internal error: xmlSchemaCheckDerivationValidSimpleRestriction: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012152 "failed to evaluate the item type of type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012153 type->name, NULL);
12154 return (-1);
12155 }
12156 /*
12157 * 2.1 The {item type definition} must have a {variety} of atomic or
12158 * union (in which case all the {member type definitions}
12159 * must be atomic).
12160 */
12161 if (((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
12162 ((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012163 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012164 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012165 NULL, type, NULL,
12166 "The item type %s must have a variety of atomic or union",
12167 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1));
12168 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012169 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
12170 } else if (itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
12171 xmlSchemaTypeLinkPtr member;
12172
12173 member = itemType->memberTypes;
12174 while (member != NULL) {
12175 if ((member->type->flags &
12176 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012177 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012178 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012179 NULL, type, NULL,
12180 "The item type is a union type, but the "
12181 "member type %s of this item type is not atomic",
12182 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
12183 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012184 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
12185 }
12186 member = member->next;
12187 }
12188 }
12189
12190 if (type->baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE)) {
12191 xmlSchemaFacetPtr facet;
12192 /*
12193 * This is the case if we have: <simpleType><list ..
12194 */
12195 /*
12196 * 2.3.1
12197 * 2.3.1.1 The {final} of the {item type definition} must not
12198 * contain list.
12199 */
12200 if (xmlSchemaTypeFinalContains(ctxt->schema,
12201 itemType, XML_SCHEMAS_TYPE_FINAL_LIST)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012202 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012203 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012204 NULL, type, NULL,
12205 "The final of its item type %s must not contain 'list'",
12206 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1));
12207 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012208 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
12209 }
12210 /*
12211 * 2.3.1.2 The {facets} must only contain the whiteSpace
12212 * facet component.
12213 */
12214 if (type->facets != NULL) {
12215 facet = type->facets;
12216 do {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012217 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
12218 xmlSchemaPIllegalFacetListUnionErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012219 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012220 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012221 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
12222 }
12223 facet = facet->next;
12224 } while (facet != NULL);
12225 }
12226 /*
12227 * TODO: Datatypes states:
12228 * A ·list· datatype can be ·derived· from an ·atomic· datatype
12229 * whose ·lexical space· allows space (such as string or anyURI)or
12230 * a ·union· datatype any of whose {member type definitions}'s
12231 * ·lexical space· allows space.
12232 */
12233 } else {
12234 /*
12235 * This is the case if we have: <simpleType><restriction ...
12236 */
12237 /*
12238 * 2.3.2
12239 * 2.3.2.1 The {base type definition} must have a {variety} of list.
12240 */
12241 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012242 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012243 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012244 NULL, type, NULL,
12245 "The base type %s must be a list type",
12246 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
12247 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012248 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
12249 }
12250 /*
12251 * 2.3.2.2 The {final} of the {base type definition} must not
12252 * contain restriction.
12253 */
12254 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
12255 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012256 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012257 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012258 NULL, type, NULL,
12259 "The final of the base type %s must not contain 'restriction'",
12260 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
12261 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012262 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
12263 }
12264 /*
12265 * 2.3.2.3 The {item type definition} must be validly derived
12266 * from the {base type definition}'s {item type definition} given
12267 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6).
12268 */
12269 {
12270 xmlSchemaTypePtr baseItemType;
12271
12272 baseItemType = xmlSchemaGetListSimpleTypeItemType(type->baseType);
12273 if (baseItemType == NULL) {
12274 xmlSchemaPErr(ctxt, type->node,
12275 XML_ERR_INTERNAL_ERROR,
12276 "xmlSchemaCheckDerivationValidSimpleRestriction: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012277 "List simple type '%s': Failed to "
12278 "evaluate the item type of its base type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012279 type->name, type->baseType->name);
12280 return (-1);
12281 }
12282 if ((itemType != baseItemType) &&
12283 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema, itemType,
12284 baseItemType, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012285 xmlChar *strBIT = NULL, *strBT = NULL;
12286 xmlSchemaPCustomErrExt(ctxt,
12287 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
12288 NULL, type, NULL,
12289 "The item type %s is not validly derived from the "
12290 "item type %s of the base type %s",
12291 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1),
12292 xmlSchemaFormatItemForReport(&strBIT, NULL, baseItemType, NULL, 1),
12293 xmlSchemaFormatItemForReport(&strBT, NULL, type->baseType, NULL, 1));
12294
12295 FREE_AND_NULL(str)
12296 FREE_AND_NULL(strBIT)
12297 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012298 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
12299 }
12300 }
12301
12302 if (type->facets != NULL) {
12303 xmlSchemaFacetPtr facet;
12304 int ok = 1;
12305 /*
12306 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
12307 * and enumeration facet components are allowed among the {facets}.
12308 */
12309 facet = type->facets;
12310 do {
12311 switch (facet->type) {
12312 case XML_SCHEMA_FACET_LENGTH:
12313 case XML_SCHEMA_FACET_MINLENGTH:
12314 case XML_SCHEMA_FACET_MAXLENGTH:
12315 case XML_SCHEMA_FACET_WHITESPACE:
12316 /*
12317 * TODO: 2.5.1.2 List datatypes
12318 * The value of ·whiteSpace· is fixed to the value collapse.
12319 */
12320 case XML_SCHEMA_FACET_PATTERN:
12321 case XML_SCHEMA_FACET_ENUMERATION:
12322 break;
12323 default: {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012324 xmlSchemaPIllegalFacetListUnionErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012325 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012326 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012327 /*
12328 * We could return, but it's nicer to report all
12329 * invalid facets.
12330 */
12331 ok = 0;
12332 }
12333 }
12334 facet = facet->next;
12335 } while (facet != NULL);
12336 if (ok == 0)
12337 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
12338 /*
12339 * TODO: 2.3.2.5 For each facet in the {facets} (call this DF), if there
12340 * is a facet of the same kind in the {facets} of the {base type
12341 * definition} (call this BF),then the DF's {value} must be a valid
12342 * restriction of BF's {value} as defined in [XML Schemas: Datatypes].
12343 */
12344 }
12345
12346
12347 }
12348 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
12349 /*
12350 * 3.1 The {member type definitions} must all have {variety} of
12351 * atomic or list.
12352 */
12353 xmlSchemaTypeLinkPtr member;
12354
12355 member = type->memberTypes;
12356 while (member != NULL) {
12357 if (((member->type->flags &
12358 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
12359 ((member->type->flags &
12360 XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012361 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012362 XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012363 NULL, type, NULL,
12364 "The member type %s is neither an atomic, nor a list type",
12365 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
12366 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012367 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
12368 }
12369 member = member->next;
12370 }
12371 /*
12372 * 3.3.1 If the {base type definition} is the ·simple ur-type
12373 * definition·
12374 */
12375 if (type->baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE)) {
12376 /*
12377 * 3.3.1.1 All of the {member type definitions} must have a
12378 * {final} which does not contain union.
12379 */
12380 member = type->memberTypes;
12381 while (member != NULL) {
12382 if (xmlSchemaTypeFinalContains(ctxt->schema, member->type,
12383 XML_SCHEMAS_TYPE_FINAL_UNION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012384 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012385 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012386 NULL, type, NULL,
12387 "The final of member type %s contains 'union'",
12388 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
12389 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012390 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
12391 }
12392 member = member->next;
12393 }
12394 /*
12395 * 3.3.1.2 The {facets} must be empty.
12396 */
12397 if (type->facetSet != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012398 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012399 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012400 NULL, type, NULL,
12401 "No facets allowed", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012402 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
12403 }
12404 } else {
12405 /*
12406 * 3.3.2.1 The {base type definition} must have a {variety} of union.
12407 */
12408 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012409 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012410 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012411 NULL, type, NULL,
12412 "The base type %s is not a union type",
12413 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
12414 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012415 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
12416 }
12417 /*
12418 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
12419 */
12420 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
12421 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012422 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012423 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012424 NULL, type, NULL,
12425 "The final of its base type %s must not contain 'restriction'",
12426 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
12427 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012428 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
12429 }
12430 /*
12431 * 3.3.2.3 The {member type definitions}, in order, must be validly
12432 * derived from the corresponding type definitions in the {base
12433 * type definition}'s {member type definitions} given the empty set,
12434 * as defined in Type Derivation OK (Simple) (§3.14.6).
12435 */
12436 {
12437 xmlSchemaTypeLinkPtr baseMember;
12438
12439 /*
12440 * OPTIMIZE: if the type is restricting, it has no local defined
12441 * member types and inherits the member types of the base type;
12442 * thus a check for equality can be skipped.
12443 */
12444 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000012445 * Even worse: I cannot see a scenario where a restricting
Daniel Veillard01fa6152004-06-29 17:04:39 +000012446 * union simple type can have other member types as the member
12447 * types of it's base type. This check seems not necessary with
12448 * respect to the derivation process in libxml2.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000012449 * But necessary if constructing types with an API.
Daniel Veillard01fa6152004-06-29 17:04:39 +000012450 */
12451 if (type->memberTypes != NULL) {
12452 member = type->memberTypes;
12453 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
12454 if ((member == NULL) && (baseMember != NULL)) {
12455 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012456 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012457 "Internal error: "
12458 "xmlSchemaCheckDerivationValidSimpleRestriction "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012459 "(3.3.2.3), union simple type '%s', unequal number "
Daniel Veillard01fa6152004-06-29 17:04:39 +000012460 "of member types in the base type\n",
12461 type->name, NULL);
12462 }
12463 while (member != NULL) {
12464 if (baseMember == NULL) {
12465 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012466 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012467 "Internal error: "
12468 "xmlSchemaCheckDerivationValidSimpleRestriction "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012469 "(3.3.2.3), union simple type '%s', unequal number "
12470 "of member types in the base type.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012471 type->name, NULL);
12472 }
12473 if ((member->type != baseMember->type) &&
12474 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema,
12475 member->type, baseMember->type, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012476 xmlChar *strBMT = NULL, *strBT = NULL;
12477
12478 xmlSchemaPCustomErrExt(ctxt,
12479 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
12480 NULL, type, NULL,
12481 "The member type %s is not validly derived from its "
12482 "corresponding member type %s of the base type %s",
12483 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1),
12484 xmlSchemaFormatItemForReport(&strBMT, NULL, baseMember->type, NULL, 1),
12485 xmlSchemaFormatItemForReport(&strBT, NULL, type->baseType, NULL, 1));
12486 FREE_AND_NULL(str)
12487 FREE_AND_NULL(strBMT)
12488 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012489 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
12490 }
12491 member = member->next;
12492 baseMember = baseMember->next;
12493 }
12494 }
12495 }
12496 /*
12497 * 3.3.2.4 Only pattern and enumeration facet components are
12498 * allowed among the {facets}.
12499 */
12500 if (type->facets != NULL) {
12501 xmlSchemaFacetPtr facet;
12502 int ok = 1;
12503
12504 facet = type->facets;
12505 do {
12506 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
12507 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012508 xmlSchemaPIllegalFacetListUnionErr(ctxt,
12509 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
12510 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012511 ok = 0;
12512 }
12513 facet = facet->next;
12514 } while (facet != NULL);
12515 if (ok == 0)
12516 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
12517
12518 }
12519 /*
12520 * TODO: 3.3.2.5 (facet derivation)
12521 */
12522 }
12523 }
12524
12525 return (0);
12526}
12527
12528/**
12529 * xmlSchemaCheckSRCSimpleType:
12530 * @ctxt: the schema parser context
12531 * @type: the simple type definition
12532 *
12533 * Checks crc-simple-type constraints.
12534 *
12535 * Returns 0 if the constraints are satisfied,
12536 * if not a positive error code and -1 on internal
12537 * errors.
12538 */
12539static int
12540xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
12541 xmlSchemaTypePtr type)
12542{
12543 /*
12544 * NOTE: src-simple-type 2-4 are redundant, since the checks
12545 * were are done for the corresponding <restriction>, <list> and <union>
12546 * elements, but W3C wants a <simpleType> error as well, so it gets one.
12547 * Maby this can be skipped in the future, if we get sure it's not needed.
12548 */
12549 if (type->subtypes == NULL) {
12550 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012551 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012552 "Internal error: xmlSchemaCheckSRCSimpleType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012553 "no subtype on simple type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012554 type->name, NULL);
12555 return (-1);
12556 }
12557 /*
12558 * src-simple-type.1 The corresponding simple type definition, if any,
12559 * must satisfy the conditions set out in Constraints on Simple Type
12560 * Definition Schema Components (§3.14.6).
12561 */
12562 if ((xmlSchemaCheckSTPropsCorrect(ctxt, type) != 0) ||
12563 (xmlSchemaCheckCOSSTRestricts(ctxt, type) != 0)) {
12564 /*
12565 * TODO: Removed this, since it got annoying to get an
12566 * extra error report, if anything failed until now.
12567 * Enable this if needed.
12568 */
12569 /*
12570 xmlSchemaPErr(ctxt, type->node,
12571 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012572 "Simple type '%s' does not satisfy the constraints "
Daniel Veillard01fa6152004-06-29 17:04:39 +000012573 "on simple type definitions.\n",
12574 type->name, NULL);
12575 */
12576 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_1);
12577 }
12578
12579 if (type->subtypes->type == XML_SCHEMA_TYPE_RESTRICTION) {
12580 /*
12581 * src-simple-type.2 If the <restriction> alternative is chosen,
12582 * either it must have a base [attribute] or a <simpleType> among its
12583 * [children], but not both.
12584 */
William M. Brack2f2a6632004-08-20 23:09:47 +000012585 /*
12586 * XML_SCHEMAP_SRC_SIMPLE_TYPE_2
12587 * NOTE: This was removed, since this will be already handled
12588 * in the parse function for <restriction>.
12589 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012590 } else if (type->subtypes->type == XML_SCHEMA_TYPE_LIST) {
12591 /* src-simple-type.3 If the <list> alternative is chosen, either it must have
12592 * an itemType [attribute] or a <simpleType> among its [children],
12593 * but not both.
12594 * NOTE: baseType is set to the local simple type definiton,
12595 * if existent, at parse time. This is a hack and not nice.
12596 */
William M. Brack2f2a6632004-08-20 23:09:47 +000012597 /*
12598 * TODO: Remove this, and add the check to the parse function of <list>.
12599 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012600 if (((type->subtypes->base == NULL) &&
12601 (type->baseType == NULL)) ||
12602 ((type->subtypes->base != NULL) &&
12603 (type->subtypes->baseType != NULL))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012604 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012605 XML_SCHEMAP_SRC_SIMPLE_TYPE_3,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012606 NULL, type, NULL,
12607 "Either the attribute 'itemType' or the <simpleType> child "
12608 "must be present on the <list> child ", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012609 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_3);
12610 }
12611
12612
12613 } else if (type->subtypes->type == XML_SCHEMA_TYPE_UNION) {
12614 xmlSchemaTypeLinkPtr member;
12615 xmlSchemaTypePtr ancestor, anySimpleType;
12616
12617 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
12618
12619 /* src-simple-type.4 Circular union type definition is disallowed. That is, if
12620 * the <union> alternative is chosen, there must not be any entries
12621 * in the memberTypes [attribute] at any depth which resolve to the
12622 * component corresponding to the <simpleType>.
12623 */
12624 member = type->memberTypes;
12625 while (member != NULL) {
12626 ancestor = member->type;
12627 while ((ancestor != NULL) && (ancestor->type != XML_SCHEMA_TYPE_BASIC)) {
12628 if (ancestor->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
12629 xmlSchemaTypeFixup(ancestor, ctxt, NULL);
12630 if (ancestor == anySimpleType)
12631 break;
12632 else if (ancestor == type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012633 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012634 XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012635 NULL, type, NULL,
12636 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012637 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
12638 } else if (ancestor->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
12639 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000012640 * TODO, FIXME: Although a list simple type must not have a union ST
Daniel Veillard01fa6152004-06-29 17:04:39 +000012641 * type as item type, which in turn has a list ST as member
12642 * type, we will assume this here as well, since this check
12643 * was not yet performed.
12644 */
12645
12646 }
12647 ancestor = ancestor->baseType;
12648 }
12649 member = member->next;
12650 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012651 }
12652
12653 return (0);
12654}
12655
William M. Brack2f2a6632004-08-20 23:09:47 +000012656#if 0 /* Not yet used code for CT schema validation */
12657static int
12658xmlSchemaCheckCVCSimpleType(xmlSchemaValidCtxtPtr ctxt,
12659 const xmlChar * value,
12660 xmlSchemaTypePtr type,
12661 int fireErrors)
12662{
12663 int ret;
12664 /*
12665 * 3.14.4 Simple Type Definition Validation Rules
12666 * Validation Rule: String Valid
12667 */
12668 /*
12669 * 1 It is schema-valid with respect to that definition as defined
12670 * by Datatype Valid in [XML Schemas: Datatypes].
12671 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012672 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type, value,
12673 fireErrors, 1, 1, 1);
William M. Brack2f2a6632004-08-20 23:09:47 +000012674 return (ret);
12675 /*
12676 * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
12677 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6), then
12678 * the string must be a ·declared entity name·.
12679 */
12680 /*
12681 * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
12682 * given the empty set, as defined in Type Derivation OK (Simple) (§3.14.6),
12683 * then every whitespace-delimited substring of the string must be a ·declared
12684 * entity name·.
12685 */
12686 /*
12687 * 2.3 otherwise no further condition applies.
12688 */
12689
12690 return (0);
12691}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012692#endif
12693
William M. Brack2f2a6632004-08-20 23:09:47 +000012694
12695static int
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012696xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
12697{
12698 if (vctxt->pctxt == NULL) {
12699 vctxt->pctxt =xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
12700 /* vctxt->pctxt = xmlSchemaNewParserCtxt("*"); */
12701 if (vctxt->pctxt == NULL) {
12702 xmlSchemaVErr(vctxt, NULL,
12703 XML_SCHEMAV_INTERNAL,
12704 "Internal error: xmlSchemaCreatePCtxtOnVCtxt, "
12705 "failed to create a temp. parser context.\n",
William M. Brack2f2a6632004-08-20 23:09:47 +000012706 NULL, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012707 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012708 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012709 /* TODO: Pass user data. */
12710 xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error, vctxt->warning, NULL);
12711 }
12712 return (0);
12713}
12714
12715static int
12716xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
12717{
12718 if (ctxt->vctxt == NULL) {
12719 ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
12720 if (ctxt->vctxt == NULL) {
12721 xmlSchemaPErr(ctxt, NULL,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012722 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012723 "Internal error: xmlSchemaCreatePCtxtOnVCtxt, "
12724 "failed to create a temp. validation context.\n",
12725 NULL, NULL);
12726 return (-1);
12727 }
12728 /* TODO: Pass user data. */
12729 xmlSchemaSetValidErrors(ctxt->vctxt, ctxt->error, ctxt->warning, NULL);
12730 }
12731 return (0);
12732}
12733
12734/**
12735 * xmlSchemaCheckCOSValidDefault:
12736 * @ctxt: the schema parser context
12737 * @type: the simple type definition
12738 * @value: the default value
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000012739 * @val: the precomputed value to be returned
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012740 * @node: an optional node (the holder of the value)
12741 *
12742 * Checks the "cos-valid-default" constraints.
12743 *
12744 * Returns 0 if the constraints are satisfied,
12745 * if not, a positive error code and -1 on internal
12746 * errors.
12747 */
12748static int
12749xmlSchemaCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
12750 xmlSchemaValidCtxtPtr vctxt,
12751 xmlSchemaTypePtr type,
12752 const xmlChar *value,
12753 xmlNodePtr node)
12754{
12755 int ret = 0;
12756
12757 /*
12758 * cos-valid-default:
12759 * Schema Component Constraint: Element Default Valid (Immediate)
12760 * For a string to be a valid default with respect to a type
12761 * definition the appropriate case among the following must be true:
12762 */
12763 /*
12764 * NOTE: This has to work without a given node (the holder of the
12765 * value), since it should work on the component, i.e. an underlying
12766 * DOM must not be mandatory.
12767 */
12768 if ((pctxt == NULL) || (vctxt == NULL)) {
12769 xmlSchemaPErr(pctxt, node,
12770 XML_SCHEMAP_INTERNAL,
12771 "Internal error: xmlSchemaCheckCOSValidDefault, "
12772 "bad arguments: the parser and/or validation context is "
12773 "missing.\n",
12774 NULL, NULL);
12775 return (-1);
12776 }
12777 if IS_COMPLEX_TYPE(type) {
William M. Brack2f2a6632004-08-20 23:09:47 +000012778 /*
12779 * Complex type.
12780 *
12781 * 2.1 its {content type} must be a simple type definition or mixed.
12782 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012783 /*
12784 * TODO: Adjust this when the content type will be computed
12785 * correctly.
12786 */
12787 if ((type->contentType != XML_SCHEMA_CONTENT_SIMPLE) &&
12788 (type->contentType != XML_SCHEMA_CONTENT_BASIC) &&
12789 (type->contentType != XML_SCHEMA_CONTENT_MIXED)) {
12790 xmlSchemaPSimpleTypeErr(pctxt,
12791 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
12792 NULL, NULL, node,
12793 type, NULL, NULL,
12794 "If the type of a constraint value is complex, its content "
12795 "type must be mixed or a simple type",
12796 NULL, NULL);
12797 return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
12798 }
12799 if (type->contentType == XML_SCHEMA_CONTENT_MIXED) {
William M. Brack2f2a6632004-08-20 23:09:47 +000012800 /*
12801 * 2.2.2 If the {content type} is mixed, then the {content type}'s
12802 * particle must be ·emptiable· as defined by Particle Emptiable
12803 * (§3.9.6).
12804 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012805
William M. Brack2f2a6632004-08-20 23:09:47 +000012806 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012807 * URGENT TODO: Implement this.
William M. Brack2f2a6632004-08-20 23:09:47 +000012808 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012809 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000012810 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012811 }
12812 /*
12813 * 1 If the type definition is a simple type definition, then the string
12814 * must be ·valid· with respect to that definition as defined by String
12815 * Valid (§3.14.4).
12816 *
12817 * AND
12818 *
12819 * 2.2.1 If the {content type} is a simple type definition, then the
12820 * string must be ·valid· with respect to that simple type definition
12821 * as defined by String Valid (§3.14.4).
12822 */
12823 vctxt->node = node;
12824 vctxt->cur = NULL;
12825 ret = xmlSchemaValidateSimpleTypeValue(vctxt, type, value, 1, 1, 1, 0);
12826 /* ret = xmlSchemaCheckCVCSimpleType(vctxt, elemDecl->value, typeDef, 0); */
12827 if (ret < 0) {
12828 xmlSchemaPErr(pctxt, node,
12829 /* NOTNICE: error code: This function will be used during
12830 * schema construction and xsi:type validation.
12831 */
12832 XML_SCHEMAP_INTERNAL,
12833 "Internal error: xmlSchemaCheckCOSValidDefault, "
12834 "while validating a value constaint value.\n",
12835 NULL, NULL);
12836
12837 }
12838 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +000012839}
12840
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012841#if 0 /* Not yet used code for CT schema validation */
William M. Brack2f2a6632004-08-20 23:09:47 +000012842/**
12843 * xmlSchemaGetSTContentOfCT:
12844 * @ctxt: the schema parser context
12845 * @type: the complex type definition
12846 *
12847 *
12848 * Returns the corresponding simple type for the content of
12849 * the complex type.
12850 */
12851static xmlSchemaTypePtr
12852xmlSchemaGetSTContentOfCT(xmlSchemaParserCtxtPtr ctxt,
12853 xmlSchemaTypePtr type)
12854{
12855 xmlSchemaTypePtr orig = type, anyType;
12856
12857 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
12858 while ((type != NULL) && (type != anyType) &&
12859 (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
12860 if (type->type == XML_SCHEMA_TYPE_SIMPLE)
12861 return(type);
12862 type = type->baseType;
12863 }
12864 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012865 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000012866 NULL, orig, NULL,
12867 "Internal error: xmlSchemaGetSTContentTypeOfCT, "
12868 "no simple type for the content of complex type '%s' could be "
12869 "computed", orig->name);
12870 return (NULL);
12871}
12872
12873
William M. Brack2f2a6632004-08-20 23:09:47 +000012874
William M. Brack2f2a6632004-08-20 23:09:47 +000012875
12876/**
12877 * xmlSchemaCheckCOSCTExtends:
12878 * @ctxt: the schema parser context
12879 * @type: the complex type definition
12880 *
12881 * Schema Component Constraint: Derivation Valid (Extension)
12882 *
12883 * Returns 0 if the constraints are satisfied, a positive
12884 * error code if not and -1 if an internal error occured.
12885 */
12886static int
12887xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
12888 xmlSchemaTypePtr type)
12889{
12890 xmlSchemaTypePtr base;
12891 /*
12892 * 1 If the {base type definition} is a complex type definition,
12893 * then all of the following must be true:
12894 */
12895 base = type->baseType;
12896 if (base == NULL) {
12897 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012898 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000012899 NULL, type, NULL,
12900 "Internal error: xmlSchemaCheckCOSCTExtends, "
12901 "the complex type '%s' has no base type", type->name);
12902 return (-1);
12903 }
12904 if (base->type == XML_SCHEMA_TYPE_COMPLEX) {
12905 /*
12906 * 1.1 The {final} of the {base type definition} must not
12907 * contain extension.
12908 */
12909 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
12910 xmlSchemaPCustomErr(ctxt,
12911 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
12912 NULL, type, NULL,
12913 "The 'final' of the base type definition "
12914 "contains extension", NULL);
12915 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
12916 }
12917 /*
12918 * 1.2 Its {attribute uses} must be a subset of the {attribute uses}
12919 * of the complex type definition itself, that is, for every attribute
12920 * use in the {attribute uses} of the {base type definition}, there
12921 * must be an attribute use in the {attribute uses} of the complex
12922 * type definition itself whose {attribute declaration} has the same
12923 * {name}, {target namespace} and {type definition} as its attribute
12924 * declaration
12925 *
12926 * NOTE: This will be already satisfied by the way the attribute uses
12927 * are extended in xmlSchemaBuildAttributeValidation; thus this check
12928 * is not needed.
12929 */
12930
12931 /*
12932 * 1.3 If it has an {attribute wildcard}, the complex type definition
12933 * must also have one, and the base type definition's {attribute
12934 * wildcard}'s {namespace constraint} must be a subset of the complex
12935 * type definition's {attribute wildcard}'s {namespace constraint},
12936 * as defined by Wildcard Subset (§3.10.6).
12937 *
12938 * This is already checked in xmlSchemaBuildAttributeValidation; thus
12939 * this check is not needed.
12940 */
12941
12942 /*
12943 * 1.4 One of the following must be true:
12944 *
12945 * 1.4.1 The {content type} of the {base type definition} and the
12946 * {content type} of the complex type definition itself must be the same
12947 * simple type definition
12948 */
12949
12950
12951
12952 } else {
12953 /*
12954 * 2 If the {base type definition} is a simple type definition,
12955 * then all of the following must be true:
12956 */
12957 /*
12958 * 2.1 The {content type} must be the same simple type definition.
12959 */
12960 /*
12961 * 2.2 The {final} of the {base type definition} must not contain
12962 * extension
12963 */
12964 }
12965
12966}
12967
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012968static int
12969xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
12970 xmlSchemaTypePtr type)
12971{
12972 xmlSchemaTypePtr base, content;
12973 int OK = 0;
12974
12975 /*
12976 * TODO: Adjust the error codes here, as I used
12977 * XML_SCHEMAP_SRC_CT_1 only yet.
12978 */
12979 /*
12980 * Schema Representation Constraint:
12981 * Complex Type Definition Representation OK
12982 */
12983 base = type->baseType;
12984 if (base == NULL) {
12985 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL, NULL, type, NULL,
12986 "Internal error: xmlSchemaCheckSRCCT, '%s', no base type",
12987 type->name);
12988 return (-1);
12989 }
12990
12991 if (type->subtypes != NULL) {
12992 if (type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
12993 if IS_COMPLEX_TYPE(base) {
12994 /*
12995 * 1 If the <complexContent> alternative is chosen, the type definition
12996 * ·resolved· to by the ·actual value· of the base [attribute]
12997 * must be a complex type definition;
12998 */
12999 xmlSchemaPCustomErr(ctxt,
13000 XML_SCHEMAP_SRC_CT_1,
13001 NULL, type, NULL,
13002 "The base type is not a complex type", NULL);
13003 return (XML_SCHEMAP_SRC_CT_1);
13004 }
13005 } else if (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
13006
13007 if IS_SIMPLE_TYPE(base) {
13008 if (type->flags &
13009 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
13010 /*
13011 * 2.1.3 only if the <extension> alternative is also
13012 * chosen, a simple type definition.
13013 */
13014 /* TODO: Change error code to ..._SRC_CT_2_1_3. */
13015 xmlSchemaPCustomErr(ctxt,
13016 XML_SCHEMAP_SRC_CT_1,
13017 NULL, type, NULL,
13018 "A complex type (simple content) cannot restrict "
13019 "an other simple type",
13020 NULL);
13021 return (XML_SCHEMAP_SRC_CT_1);
13022 }
13023 OK = 1;
13024
13025 } else { /* if IS_SIMPLE_TYPE(base) */
13026 if (base->contentType = XML_SCHEMA_CONTENT_MIXED) {
13027 /*
13028 * 2.1.2 only if the <restriction> alternative is also
13029 * chosen, a complex type definition whose {content type}
13030 * is mixed and a particle emptyable.
13031 */
13032 /*
13033 * FIXME TODO: Check for *empiable particle* is missing.
13034 */
13035 if ((type->flags &
13036 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) == 0) {
13037 xmlSchemaPCustomErr(ctxt,
13038 XML_SCHEMAP_SRC_CT_1,
13039 NULL, type, NULL,
13040 "A complex type (simple content) cannot "
13041 "extend an other complex type which has a "
13042 "content type of: 'mixed' and emptiable particle",
13043 NULL);
13044 return (XML_SCHEMAP_SRC_CT_1);
13045 }
13046 /*
13047 * NOTE: This will be fired as well, if the base type
13048 * is *'anyType'*.
13049 * NOTE: type->subtypes->subtypes will be the
13050 * <restriction> item.
13051 */
13052 if (type->subtypes->subtypes == NULL) {
13053 /* Yes, this is paranoid programming. */
13054 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
13055 NULL, type, NULL,
13056 "Internal error: xmlSchemaCheckSRCCT, "
13057 "'%s', <simpleContent> has no <restriction>",
13058 type->name);
13059 return (-1);
13060 }
13061 /*
13062 * 2.2 If clause 2.1.2 above is satisfied, then there
13063 * must be a <simpleType> among the [children] of
13064 * <restriction>.
13065 */
13066 if (type->subtypes->subtypes->type !=
13067 XML_SCHEMA_TYPE_SIMPLE) {
13068 /* TODO: Change error code to ..._SRC_CT_2_2. */
13069 xmlSchemaPCustomErr(ctxt,
13070 XML_SCHEMAP_SRC_CT_1,
13071 NULL, type, NULL,
13072 "A <simpleType> is expected among the children "
13073 "of <restriction>", NULL);
13074 return (XML_SCHEMAP_SRC_CT_1);
13075 }
13076 OK = 1;
13077 } else { /* if (base->contentType = XML_SCHEMA_CONTENT_MIXED)*/
13078 /*
13079 * 2.1.1 a complex type definition whose {content type} is a
13080 * simple type definition;
13081 */
13082 if (base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) {
13083 xmlSchemaPCustomErr(ctxt,
13084 XML_SCHEMAP_SRC_CT_1,
13085 NULL, type, NULL,
13086 "A complex type (simple content) cannot "
13087 "be derived from the complex type '%s'",
13088 base->name);
13089 return (XML_SCHEMAP_SRC_CT_1);
13090 }
13091 content = base->contentTypeDef;
13092 if (content == NULL) {
13093 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
13094 NULL, type, NULL,
13095 "Internal error: xmlSchemaCheckSRCCT, "
13096 "'%s', base type has no content type",
13097 type->name);
13098 return (-1);
13099 }
13100 if (content->type != XML_SCHEMA_TYPE_SIMPLE) {
13101 xmlSchemaPCustomErr(ctxt,
13102 XML_SCHEMAP_SRC_CT_1,
13103 NULL, type, NULL,
13104 "A complex type (simple content) cannot "
13105 "be derived from the complex type '%s'",
13106 base->name);
13107 return (XML_SCHEMAP_SRC_CT_1);
13108 }
13109 }
13110 }
13111 }
13112 }
13113 /*
13114 * TODO: 3 The corresponding complex type definition component must
13115 * satisfy the conditions set out in Constraints on Complex Type
13116 * Definition Schema Components (§3.4.6);
13117 *
13118 * TODO: 4 If clause 2.2.1 or clause 2.2.2 in the correspondence specification
13119 * above for {attribute wildcard} is satisfied, the intensional
13120 * intersection must be expressible, as defined in Attribute Wildcard
13121 * Intersection (§3.10.6).
13122 */
13123
13124}
William M. Brack2f2a6632004-08-20 23:09:47 +000013125#endif
13126
Daniel Veillard01fa6152004-06-29 17:04:39 +000013127/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013128 * xmlSchemaGroupDefFixup:
13129 * @typeDecl: the schema model group definition
13130 * @ctxt: the schema parser context
13131 *
13132 * Fixes model group definitions.
13133 */
13134static void
13135xmlSchemaGroupDefFixup(xmlSchemaTypePtr group,
13136 xmlSchemaParserCtxtPtr ctxt,
13137 const xmlChar * name ATTRIBUTE_UNUSED)
13138{
13139 group->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
13140 if ((group->ref != NULL) && (group->subtypes == NULL)) {
13141 xmlSchemaTypePtr groupDef;
13142 /*
13143 * Resolve the reference.
13144 */
13145 groupDef = xmlSchemaGetGroup(ctxt->schema, group->ref,
13146 group->refNs);
13147 if (groupDef == NULL) {
13148 xmlSchemaPResCompAttrErr(ctxt,
13149 XML_SCHEMAP_SRC_RESOLVE,
13150 NULL, group, NULL,
13151 "ref", group->ref, group->refNs,
13152 XML_SCHEMA_TYPE_GROUP, NULL);
13153 return;
13154 }
13155 group->subtypes = groupDef;
13156 }
13157}
13158
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013159#if 0 /* Enable when the content type will be computed. */
13160static int
13161xmlSchemaComputeContentType(xmlSchemaParserCtxtPtr ctxt,
13162 xmlSchemaTypePtr type)
13163{
13164 xmlSchemaTypePtr base, res = NULL;
13165
13166 base = type->baseType;
13167 if (base == NULL) {
13168 xmlSchemaPCustomErr(ctxt,
13169 XML_SCHEMAP_INTERNAL,
13170 NULL, type, NULL,
13171 "Internal error: xmlSchemaGetContentType, "
13172 "the complex type '%s' has no base type", type->name);
13173 return (-1);
13174 }
13175 if (IS_ANYTYPE(base) || (type->subtypes->type ==
13176 XML_SCHEMA_TYPE_COMPLEX_CONTENT)) {
13177 xmlSchemaTypePtr start;
13178 /*
13179 * Effective 'mixed'.
13180 */
13181 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
13182 type->contentType = XML_SCHEMA_CONTENT_MIXED;
13183 /*
13184 * Effective content.
13185 */
13186 if (IS_ANYTYPE(base))
13187 start = type;
13188 else
13189 start = type->subtypes;
13190
13191 } else { /* if XML_SCHEMA_TYPE_COMPLEX_CONTENT */
13192 xmlSchemaTypePtr baseContentItem;
13193
13194 /*
13195 * Complex type with simple content.
13196 */
13197 if IS_COMPLEX_TYPE(base) {
13198 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
13199 /*
13200 * Summary: a complex type (simple content) can *restrict*
13201 * a complex type with the following content type:
13202 * 1. 'mixed' and an emptiable particle
13203 * 2. simple type
13204 */
13205 if (base->contentType == XML_SCHEMA_CONTENT_MIXED) {
13206 /*
13207 * 2 if the {content type} of the base type is mixed and a
13208 * particle which is ·emptiable·,
13209 * [...]
13210 * then starting from the simple type definition
13211 * corresponding to the <simpleType> among the [children]
13212 * of <restriction> (**which must be present**)
13213 *
13214 * FIXME TODO: Handle "emptiable particle".
13215 */
13216 res = type->subtypes->subtypes;
13217 if (res == NULL) {
13218 xmlSchemaPCustomErr(ctxt,
13219 XML_SCHEMAP_INTERNAL,
13220 NULL, type, NULL,
13221 "Internal error: xmlSchemaGetContentType, "
13222 "CT '%s' (restricting): <simpleContent> has no "
13223 "<restriction>",
13224 type->name);
13225 return (-1);
13226 }
13227
13228 res->subtypes;
13229 if (res == NULL) {
13230 xmlSchemaPCustomErr(ctxt,
13231 XML_SCHEMAP_INTERNAL,
13232 NULL, type, NULL,
13233 "Internal error: xmlSchemaGetContentType, "
13234 "CT '%s' (restricting): <restriction> has no "
13235 "mandatory <simpleType>",
13236 type->name);
13237 return (-1);
13238 }
13239 } else {
13240 baseContentItem = base->contentTypeDef;
13241 if (baseContentItem == NULL) {
13242 xmlSchemaPCustomErr(ctxt,
13243 XML_SCHEMAP_INTERNAL,
13244 NULL, type, NULL,
13245 "Internal error: xmlSchemaGetContentType, "
13246 "CT '%s' (restricting), the base type has no "
13247 "content type", type->name);
13248 return (-1);
13249 }
13250 if IS_SIMPLE_TYPE(baseContentItem) {
13251 /*
13252 * 1 If the base type is a complex type whose own
13253 * {content type} is a simple type and the <restriction>
13254 * alternative is chosen
13255 */
13256 /* type->subtypes->subtypes will be the restriction item.*/
13257 res = type->subtypes->subtypes;
13258 if (res == NULL) {
13259 xmlSchemaPCustomErr(ctxt,
13260 XML_SCHEMAP_INTERNAL,
13261 NULL, type, NULL,
13262 "Internal error: xmlSchemaGetContentType, "
13263 "CT '%s' (restricting): <simpleType> has no "
13264 "<restriction>", type->name);
13265 return (-1);
13266 }
13267 /*
13268 * 1.1 the simple type definition corresponding to the
13269 * <simpleType> among the [children] of <restriction>if
13270 * there is one;
13271 */
13272 res = res->subtypes;
13273 if (res == NULL) {
13274 /*
13275 * 1.2 otherwise the {content type}
13276 * of the base type .
13277 */
13278 res = baseContentItem;
13279 }
13280 }
13281 }
13282 /*
13283 * SPECIAL TODO: If *restricting* the spec wants us to
13284 * create an *additional* simple type which restricts the
13285 * located simple type; we won't do this yet, and look how
13286 * far we get with it.
13287 */
13288 } else { /* if XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION */
13289 /*
13290 * Summary: a complex type (simple content) can *extend*
13291 * only a complex base with a simple type as content.
13292 */
13293 /*
13294 * 3 If the type definition ·resolved· to by the ·actual
13295 * value· of the base [attribute] is a complex type
13296 * definition (whose own {content type} *must be* a simple
13297 * type definition, see below) and the *<extension>*
13298 * alternative is chosen, then the {content type} of that
13299 * complex type definition;
13300 */
13301 res = base->contentTypeDef;
13302 if (res == NULL) {
13303 xmlSchemaPCustomErr(ctxt,
13304 XML_SCHEMAP_INTERNAL,
13305 NULL, type, NULL,
13306 "Internal error: xmlSchemaGetContentType, "
13307 "CT '%s' (extending), the base type has no content "
13308 "type", type->name);
13309 return (-1);
13310 }
13311 if (! IS_SIMPLE_TYPE(res)) {
13312 xmlSchemaPCustomErr(ctxt,
13313 XML_SCHEMAP_INTERNAL,
13314 NULL, type, NULL,
13315 "Internal error: xmlSchemaGetContentType, "
13316 "CT '%s' (extending), the content type of the "
13317 "base is not a simple type", type->name);
13318 return (-1);
13319 }
13320 }
13321 } else /* if IS_COMPLEX_TYPE(base) */
13322 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
13323 /*
13324 * 4 otherwise (the type definition ·resolved· to by the
13325 * ·actual value· of the base [attribute] is a simple type
13326 * definition and the <extension> alternative is chosen),
13327 * then that simple type definition.
13328 */
13329 res = base;
13330 }
13331 type->contentTypeDef = res;
13332 if (res == NULL) {
13333 xmlSchemaPCustomErr(ctxt,
13334 XML_SCHEMAP_INTERNAL,
13335 NULL, type, NULL,
13336 "Internal error: xmlSchemaGetContentType, "
13337 "'%s', the content type could not be determined",
13338 type->name);
13339 return (-1);
13340 }
13341
13342 }
13343
13344}
13345#endif
13346
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013347/**
Daniel Veillard4255d502002-04-16 15:50:10 +000013348 * xmlSchemaTypeFixup:
13349 * @typeDecl: the schema type definition
13350 * @ctxt: the schema parser context
13351 *
13352 * Fixes the content model of the type.
13353 */
13354static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013355xmlSchemaTypeFixup(xmlSchemaTypePtr item,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013356 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000013357{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013358 xmlSchemaTypePtr ctxtType;
13359
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013360 if (item == NULL)
Daniel Veillard82bbbd42003-05-11 20:16:09 +000013361 return;
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013362 /*
13363 * Do not allow the following types to be typefixed, prior to
13364 * the corresponding simple/complex types.
13365 */
13366 if (ctxt->ctxtType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013367 switch (item->type) {
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013368 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
13369 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
13370 case XML_SCHEMA_TYPE_UNION:
13371 case XML_SCHEMA_TYPE_RESTRICTION:
13372 case XML_SCHEMA_TYPE_EXTENSION:
13373 return;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013374 default:
13375 break;
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013376 }
13377 }
Daniel Veillard4255d502002-04-16 15:50:10 +000013378 if (name == NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013379 name = item->name;
13380 if (item->contentType == XML_SCHEMA_CONTENT_UNKNOWN) {
13381 switch (item->type) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013382 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013383 if (item->subtypes != NULL) {
13384 if (item->subtypes->contentType ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013385 XML_SCHEMA_CONTENT_UNKNOWN) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013386 xmlSchemaTypeFixup(item->subtypes, ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013387 NULL);
13388 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013389 item->contentType =
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013390 XML_SCHEMA_CONTENT_SIMPLE;
13391 /* item->subtypes->contentType; */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013392 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013393 break;
13394 }
13395 case XML_SCHEMA_TYPE_RESTRICTION:{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013396 xmlSchemaTypePtr base = NULL;
13397
13398 ctxt->ctxtType->flags |=
13399 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013400 if (item->baseType != NULL)
13401 base = item->baseType;
13402 else if (item->base != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013403 base =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013404 xmlSchemaGetType(ctxt->schema, item->base,
13405 item->baseNs);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013406 if (base == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013407 xmlSchemaPResCompAttrErr(ctxt,
13408 XML_SCHEMAP_SRC_RESOLVE,
William M. Brack2f2a6632004-08-20 23:09:47 +000013409 NULL, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013410 (xmlNodePtr) xmlSchemaGetPropNode(item->node, "base"),
13411 "base", item->base, item->baseNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013412 XML_SCHEMA_TYPE_BASIC, "type definition");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013413 } else if (base->contentType ==
Daniel Veillard3646d642004-06-02 19:19:14 +000013414 XML_SCHEMA_CONTENT_UNKNOWN) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013415 xmlSchemaTypeFixup(base, ctxt, NULL);
13416 }
William M. Brack2f2a6632004-08-20 23:09:47 +000013417 }
13418 ctxt->ctxtType->baseType = base;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013419 if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX) {
13420 /*
13421 * ComplexType restriction.
William M. Brack2f2a6632004-08-20 23:09:47 +000013422 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013423 /*
13424 * Content type.
13425 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013426 if (item->subtypes == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013427 /* 1.1.1 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013428 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
13429 else if ((item->subtypes->subtypes == NULL) &&
13430 ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013431 XML_SCHEMA_TYPE_ALL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013432 || (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013433 XML_SCHEMA_TYPE_SEQUENCE)))
13434 /* 1.1.2 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013435 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
13436 else if ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013437 XML_SCHEMA_TYPE_CHOICE)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013438 && (item->subtypes->subtypes == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +000013439 /* 1.1.3 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013440 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013441 else {
13442 /* 1.2 and 2.X are applied at the other layer */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013443 item->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000013444 XML_SCHEMA_CONTENT_ELEMENTS;
13445 }
13446 } else {
13447 /*
13448 * SimpleType restriction.
13449 */
William M. Brack2f2a6632004-08-20 23:09:47 +000013450 /* TODO: Nothing? */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013451 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013452 break;
13453 }
13454 case XML_SCHEMA_TYPE_EXTENSION:{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013455 xmlSchemaTypePtr base = NULL;
13456 xmlSchemaContentType explicitContentType;
13457
13458 /*
13459 * An extension does exist on a complexType only.
13460 */
13461 ctxt->ctxtType->flags |=
13462 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013463 if (item->recurse) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013464 /* TODO: The word "recursive" should be changed to "circular" here. */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013465 xmlSchemaPCustomErr(ctxt,
13466 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013467 NULL, item, item->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013468 "This item is circular", NULL);
Daniel Veillard2582a332004-04-18 19:49:46 +000013469 return;
13470 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013471 if (item->base != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013472 base =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013473 xmlSchemaGetType(ctxt->schema, item->base,
13474 item->baseNs);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013475 if (base == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013476 xmlSchemaPResCompAttrErr(ctxt,
13477 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013478 NULL, item, item->node,
13479 "base", item->base, item->baseNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013480 XML_SCHEMA_TYPE_BASIC, "type definition");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013481 } else if (base->contentType ==
13482 XML_SCHEMA_CONTENT_UNKNOWN) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013483 item->recurse = 1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013484 xmlSchemaTypeFixup(base, ctxt, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013485 item->recurse = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013486 }
13487 /*
13488 * The type definition ·resolved· to by the ·actual
13489 * value· of the base [attribute]
13490 */
13491 ctxt->ctxtType->baseType = base;
13492 /*
13493 * TODO: This one is still needed for computation of
13494 * the content model by xmlSchemaBuildAContentModel.
13495 * Try to get rid of it.
13496 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013497 item->baseType = base;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013498 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013499 if ((item->subtypes != NULL) &&
13500 (item->subtypes->contentType == XML_SCHEMA_CONTENT_UNKNOWN))
13501 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013502
13503 explicitContentType = XML_SCHEMA_CONTENT_ELEMENTS;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013504 if (item->subtypes == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013505 /* 1.1.1 */
13506 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013507 else if ((item->subtypes->subtypes == NULL) &&
13508 ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013509 XML_SCHEMA_TYPE_ALL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013510 || (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013511 XML_SCHEMA_TYPE_SEQUENCE)))
13512 /* 1.1.2 */
13513 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013514 else if ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013515 XML_SCHEMA_TYPE_CHOICE)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013516 && (item->subtypes->subtypes == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +000013517 /* 1.1.3 */
13518 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
13519 if (base != NULL) {
13520 /* It will be reported later, if the base is missing. */
13521 if (explicitContentType == XML_SCHEMA_CONTENT_EMPTY) {
13522 /* 2.1 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013523 item->contentType = base->contentType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013524 } else if (base->contentType ==
13525 XML_SCHEMA_CONTENT_EMPTY) {
13526 /* 2.2 imbitable ! */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013527 item->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000013528 XML_SCHEMA_CONTENT_ELEMENTS;
13529 } else {
13530 /* 2.3 imbitable pareil ! */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013531 item->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000013532 XML_SCHEMA_CONTENT_ELEMENTS;
13533 }
13534 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013535 break;
13536 }
13537 case XML_SCHEMA_TYPE_COMPLEX:{
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013538 ctxtType = ctxt->ctxtType;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013539 ctxt->ctxtType = item;
13540 /*
13541 * Start with an empty content-type type.
13542 */
13543 if (item->subtypes == NULL)
13544 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
13545
13546 if ((item->subtypes == NULL) ||
13547 ((item->subtypes->type !=
Daniel Veillard01fa6152004-06-29 17:04:39 +000013548 XML_SCHEMA_TYPE_SIMPLE_CONTENT) &&
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013549 (item->subtypes->type !=
Daniel Veillard01fa6152004-06-29 17:04:39 +000013550 XML_SCHEMA_TYPE_COMPLEX_CONTENT))) {
13551 /*
13552 * This case is understood as shorthand for complex
13553 * content restricting the ur-type definition, and
13554 * the details of the mappings should be modified as
13555 * necessary.
13556 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013557 item->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
13558 item->flags |=
Daniel Veillard01fa6152004-06-29 17:04:39 +000013559 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013560 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013561 * Assume that we inherit the content-type type
13562 * from 'anyType', which is 'mixed' and a particle
13563 * emptiable.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013564 */
13565 item->contentType = item->baseType->contentType;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013566 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013567 /*
13568 * Fixup the sub components.
13569 */
13570 if ((item->subtypes != NULL) &&
13571 (item->subtypes->contentType ==
13572 XML_SCHEMA_CONTENT_UNKNOWN)) {
13573 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013574 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013575 if (item->flags & XML_SCHEMAS_TYPE_MIXED) {
13576 item->contentType = XML_SCHEMA_CONTENT_MIXED;
13577 } else if (item->subtypes != NULL) {
13578 /*
13579 * Use the content-type type of the model groups
13580 * defined, if 'mixed' is not set. If 'mixed' is set
13581 * it will expand the content-type by allowing character
13582 * content to appear.
13583 */
13584 item->contentType =
13585 item->subtypes->contentType;
13586 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013587
13588 /*
13589 * Some optimization for validation:
13590 * If there are no facets beside the "whitespace" facet,
13591 * then a value needs not to checked against against a
13592 * facet, thus no computed value is needed.
13593 * TODO URGENT: This is just a workaround, we need to
13594 * introduce the correct usage of contentType to store the
13595 * facets in!
13596 */
Daniel Veillardd3210bc2005-01-28 17:56:39 +000013597 if ((item->baseType != NULL) &&
13598 (item->baseType->flags &
13599 XML_SCHEMAS_TYPE_FACETSNEEDVALUE))
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013600 item->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
13601 else {
13602 xmlSchemaFacetLinkPtr cur;
13603
13604 for (cur = item->facetSet; cur != NULL;
13605 cur = cur->next) {
13606 if (cur->facet->type != XML_SCHEMA_FACET_WHITESPACE) {
13607 item->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
13608 break;
13609 }
13610 }
13611 }
13612
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013613 xmlSchemaBuildAttributeValidation(ctxt, item);
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000013614 xmlSchemaCheckDefaults(item, ctxt, item->name);
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013615 ctxt->ctxtType = ctxtType;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013616 break;
13617 }
13618 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013619 if (item->subtypes == NULL) {
13620 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
13621 if (item->flags & XML_SCHEMAS_TYPE_MIXED)
13622 item->contentType =
Daniel Veillard1aefc862004-03-04 11:40:48 +000013623 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013624 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013625 if (item->flags & XML_SCHEMAS_TYPE_MIXED) {
13626 item->contentType =
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013627 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillard3646d642004-06-02 19:19:14 +000013628 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013629 xmlSchemaTypeFixup(item->subtypes, ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013630 NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013631 if (item->subtypes != NULL)
13632 item->contentType =
13633 item->subtypes->contentType;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013634 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013635 /*
13636 * Removed due to implementation of the build of attribute uses.
13637 */
13638 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013639 if (item->attributes == NULL)
13640 item->attributes =
13641 item->subtypes->attributes;
Daniel Veillard3646d642004-06-02 19:19:14 +000013642 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013643 }
13644 break;
13645 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013646 case XML_SCHEMA_TYPE_SIMPLE:
13647 /*
13648 * Simple Type Definition Schema Component
13649 *
13650 */
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013651 ctxtType = ctxt->ctxtType;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013652 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
13653 if (item->subtypes->contentType ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013654 XML_SCHEMA_CONTENT_UNKNOWN) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013655 ctxt->ctxtType = item;
13656 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013657 }
13658 /* Fixup base type */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013659 if ((item->baseType != NULL) &&
13660 (item->baseType->contentType ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013661 XML_SCHEMA_CONTENT_UNKNOWN)) {
13662 /* OPTIMIZE: Actually this one will never by hit, since
13663 * the base type is already type-fixed in <restriction>.
13664 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013665 ctxt->ctxtType = item;
13666 xmlSchemaTypeFixup(item->baseType, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013667 }
13668 /* Base type:
13669 * 2 If the <list> or <union> alternative is chosen,
13670 * then the ·simple ur-type definition·.
13671 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013672 if (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013673 XML_SCHEMA_TYPE_LIST) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013674 item->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
13675 item->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
13676 } else if (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013677 XML_SCHEMA_TYPE_UNION) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013678 item->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
13679 item->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
13680 } else if (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013681 XML_SCHEMA_TYPE_RESTRICTION) {
13682 xmlSchemaFacetLinkPtr facet, cur, last = NULL;
13683
13684 /*
13685 * Variety
13686 * If the <restriction> alternative is chosen, then the
13687 * {variety} of the {base type definition}.
13688 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013689 if (item->baseType != NULL) {
13690 if (item->baseType->flags &
Daniel Veillard01fa6152004-06-29 17:04:39 +000013691 XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013692 item->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
13693 else if (item->baseType->flags &
Daniel Veillard01fa6152004-06-29 17:04:39 +000013694 XML_SCHEMAS_TYPE_VARIETY_LIST)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013695 item->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
13696 else if (item->baseType->flags &
Daniel Veillard01fa6152004-06-29 17:04:39 +000013697 XML_SCHEMAS_TYPE_VARIETY_UNION)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013698 item->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013699 /*
13700 * Schema Component Constraint: Simple Type Restriction
13701 * (Facets)
13702 * NOTE: Satisfaction of 1 and 2 arise from the fixup
13703 * applied beforehand.
13704 *
13705 * 3 The {facets} of R are the union of S and the {facets}
13706 * of B, eliminating duplicates. To eliminate duplicates,
13707 * when a facet of the same kind occurs in both S and the
13708 * {facets} of B, the one in the {facets} of B is not
13709 * included, with the exception of enumeration and pattern
13710 * facets, for which multiple occurrences with distinct values
13711 * are allowed.
13712 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013713 if (item->baseType->facetSet != NULL) {
13714 last = item->facetSet;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013715 if (last != NULL)
13716 while (last->next != NULL)
13717 last = last->next;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013718 cur = item->baseType->facetSet;
13719 for (; cur != NULL; cur = cur->next) {
13720 /*
13721 * Base patterns won't be add here:
13722 * they are ORed in a type and
13723 * ANDed in derived types. This will
13724 * happed at validation level by
13725 * walking the base axis of the type.
13726 */
13727 if (cur->facet->type ==
13728 XML_SCHEMA_FACET_PATTERN)
13729 continue;
13730 facet = NULL;
13731 if ((item->facetSet != NULL) &&
13732 /* REMOVED: a check for
13733 * XML_SCHEMA_FACET_PATTERN was already
13734 * performed above.
13735
13736 * (cur->facet->type !=
13737 * XML_SCHEMA_FACET_PATTERN) &&
Daniel Veillard01fa6152004-06-29 17:04:39 +000013738 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013739 (cur->facet->type !=
13740 XML_SCHEMA_FACET_ENUMERATION)) {
13741 facet = item->facetSet;
13742 do {
13743 if (cur->facet->type ==
13744 facet->facet->type)
13745 break;
13746 facet = facet->next;
13747 } while (facet != NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013748 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013749 if (facet == NULL) {
13750 facet = (xmlSchemaFacetLinkPtr)
13751 xmlMalloc(sizeof(xmlSchemaFacetLink));
13752 if (facet == NULL) {
13753 xmlSchemaPErrMemory(ctxt,
13754 "fixing simpleType", NULL);
13755 return;
13756 }
13757 /*
13758 * The facets are not copied but referenced
13759 * via the facet link.
13760 */
13761 facet->facet = cur->facet;
13762 facet->next = NULL;
13763 if (last == NULL)
13764 item->facetSet = facet;
13765 else
13766 last->next = facet;
13767 last = facet;
13768 }
13769 }
13770 }
13771 /*
13772 * Some optimization for validation:
13773 * If there are no facets beside the "whitespace" facet,
13774 * then a value needs not to checked against against a
13775 * facet, thus no computed value is needed.
13776 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000013777 if (item->baseType->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013778 item->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
13779 else {
13780 for (cur = item->facetSet; cur != NULL;
13781 cur = cur->next) {
13782 if (cur->facet->type != XML_SCHEMA_FACET_WHITESPACE) {
13783 item->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
13784 break;
13785 }
13786 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013787 }
13788 }
13789 }
13790 /*
13791 * Check constraints.
13792 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013793 xmlSchemaCheckSRCSimpleType(ctxt, item);
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000013794 xmlSchemaCheckDefaults(item, ctxt, item->name);
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013795 ctxt->ctxtType = ctxtType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013796 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013797 case XML_SCHEMA_TYPE_SEQUENCE:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013798 case XML_SCHEMA_TYPE_ALL:
13799 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013800 item->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013801 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013802 case XML_SCHEMA_TYPE_GROUP:
13803 /*
13804 * TODO: Handling was moved to xmlSchemaGroupDefFixup.
13805 */
13806 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013807 case XML_SCHEMA_TYPE_LIST:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013808 xmlSchemaParseListRefFixup(item, ctxt);
13809 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013810 break;
13811 case XML_SCHEMA_TYPE_UNION:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013812 xmlSchemaParseUnionRefCheck(item, ctxt);
13813 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013814 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013815 case XML_SCHEMA_TYPE_BASIC:
13816 case XML_SCHEMA_TYPE_ANY:
13817 case XML_SCHEMA_TYPE_FACET:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013818 case XML_SCHEMA_TYPE_UR:
13819 case XML_SCHEMA_TYPE_ELEMENT:
13820 case XML_SCHEMA_TYPE_ATTRIBUTE:
13821 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
William M. Brack29aa7722004-05-12 00:27:56 +000013822 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013823 case XML_SCHEMA_TYPE_NOTATION:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013824 case XML_SCHEMA_FACET_MININCLUSIVE:
13825 case XML_SCHEMA_FACET_MINEXCLUSIVE:
13826 case XML_SCHEMA_FACET_MAXINCLUSIVE:
13827 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
13828 case XML_SCHEMA_FACET_TOTALDIGITS:
13829 case XML_SCHEMA_FACET_FRACTIONDIGITS:
13830 case XML_SCHEMA_FACET_PATTERN:
13831 case XML_SCHEMA_FACET_ENUMERATION:
13832 case XML_SCHEMA_FACET_WHITESPACE:
13833 case XML_SCHEMA_FACET_LENGTH:
13834 case XML_SCHEMA_FACET_MAXLENGTH:
13835 case XML_SCHEMA_FACET_MINLENGTH:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013836 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
13837 if (item->subtypes != NULL)
13838 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013839 break;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000013840 case XML_SCHEMA_TYPE_IDC_UNIQUE:
13841 case XML_SCHEMA_TYPE_IDC_KEY:
13842 case XML_SCHEMA_TYPE_IDC_KEYREF:
13843 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013844 }
13845 }
Daniel Veillard8651f532002-04-17 09:06:27 +000013846#ifdef DEBUG_TYPE
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013847 if (item->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013848 xmlGenericError(xmlGenericErrorContext,
13849 "Type of %s : %s:%d :", name,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013850 item->node->doc->URL,
13851 xmlGetLineNo(item->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +000013852 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013853 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000013854 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013855 switch (item->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013856 case XML_SCHEMA_CONTENT_SIMPLE:
13857 xmlGenericError(xmlGenericErrorContext, "simple\n");
13858 break;
13859 case XML_SCHEMA_CONTENT_ELEMENTS:
13860 xmlGenericError(xmlGenericErrorContext, "elements\n");
13861 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000013862 case XML_SCHEMA_CONTENT_UNKNOWN:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013863 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
13864 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000013865 case XML_SCHEMA_CONTENT_EMPTY:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013866 xmlGenericError(xmlGenericErrorContext, "empty\n");
13867 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000013868 case XML_SCHEMA_CONTENT_MIXED:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013869 xmlGenericError(xmlGenericErrorContext, "mixed\n");
13870 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013871 /* Removed, since not used. */
13872 /*
Daniel Veillard8651f532002-04-17 09:06:27 +000013873 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013874 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
13875 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013876 */
Daniel Veillard8651f532002-04-17 09:06:27 +000013877 case XML_SCHEMA_CONTENT_BASIC:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013878 xmlGenericError(xmlGenericErrorContext, "basic\n");
13879 break;
13880 default:
13881 xmlGenericError(xmlGenericErrorContext,
13882 "not registered !!!\n");
13883 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000013884 }
13885#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000013886}
13887
13888/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000013889 * xmlSchemaCheckFacet:
13890 * @facet: the facet
13891 * @typeDecl: the schema type definition
13892 * @ctxt: the schema parser context or NULL
13893 * @name: name of the type
13894 *
13895 * Checks the default values types, especially for facets
13896 *
13897 * Returns 0 if okay or -1 in cae of error
13898 */
13899int
13900xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013901 xmlSchemaTypePtr typeDecl,
13902 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000013903{
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +000013904 xmlSchemaTypePtr nonNegativeIntegerType = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013905 int ret = 0, reuseValCtxt = 0;
13906
Daniel Veillardce682bc2004-11-05 17:22:25 +000013907 if ((facet == NULL) || (typeDecl == NULL))
13908 return(-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013909 /*
13910 * TODO: will the parser context be given if used from
13911 * the relaxNG module?
13912 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000013913
13914 if (nonNegativeIntegerType == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013915 nonNegativeIntegerType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000013916 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000013917 }
13918 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013919 case XML_SCHEMA_FACET_MININCLUSIVE:
13920 case XML_SCHEMA_FACET_MINEXCLUSIVE:
13921 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013922 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
13923 case XML_SCHEMA_FACET_ENUMERATION: {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013924 /*
13925 * Okay we need to validate the value
13926 * at that point.
13927 */
13928 xmlSchemaValidCtxtPtr vctxt;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013929 xmlSchemaTypePtr base;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013930
13931 /* 4.3.5.5 Constraints on enumeration Schema Components
13932 * Schema Component Constraint: enumeration valid restriction
13933 * It is an ·error· if any member of {value} is not in the
13934 * ·value space· of {base type definition}.
13935 *
13936 * minInclusive, maxInclusive, minExclusive, maxExclusive:
13937 * The value ·must· be in the
13938 * ·value space· of the ·base type·.
13939 */
13940 /*
13941 * This function is intended to deliver a compiled value
13942 * on the facet. In XML Schemas the type holding a facet,
13943 * cannot be a built-in type. Thus to ensure that other API
13944 * calls (relaxng) do work, if the given type is a built-in
13945 * type, we will assume that the given built-in type *is
13946 * already* the base type.
13947 */
13948 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
13949 base = typeDecl->baseType;
13950 if (base == NULL) {
13951 xmlSchemaPErr(ctxt, typeDecl->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013952 XML_SCHEMAP_INTERNAL,
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013953 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013954 "the type '%s' has no base type.\n",
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013955 typeDecl->name, NULL);
13956 return (-1);
13957 }
13958 } else
13959 base = typeDecl;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013960 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013961 * This avoids perseverative creation of the
13962 * validation context if a parser context is
13963 * used.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013964 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013965 if (ctxt != NULL) {
13966 reuseValCtxt = 1;
13967 if (ctxt->vctxt == NULL) {
13968 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
13969 return (-1);
13970 }
13971 vctxt = ctxt->vctxt;
13972 } else {
13973 vctxt = xmlSchemaNewValidCtxt(NULL);
13974 if (vctxt == NULL) {
13975 xmlSchemaPErr(ctxt, typeDecl->node,
13976 XML_SCHEMAP_INTERNAL,
13977 "Internal error: xmlSchemaCheckFacet, "
13978 "creating a new validation context.\n",
13979 NULL, NULL);
13980 return (-1);
13981 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013982 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013983
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013984 vctxt->node = facet->node;
13985 vctxt->cur = NULL;
13986 /*
13987 * NOTE: This call does not check the content nodes,
13988 * since they are not available:
13989 * facet->node is just the node holding the facet
13990 * definition, *not* the attribute holding the *value*
13991 * of the facet.
13992 */
13993 ret = xmlSchemaValidateSimpleTypeValue(vctxt, base,
13994 facet->value, 0, 1, 1, 0);
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013995 facet->val = vctxt->value;
13996 vctxt->value = NULL;
13997 if (ret > 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013998 /* error code */
13999 if (ctxt != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014000 xmlSchemaPErrExt(ctxt, facet->node,
14001 XML_SCHEMAP_INVALID_FACET,
14002 NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014003 "Type definition '%s': The value '%s' of the "
14004 "facet '%s' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000014005 name, facet->value,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014006 xmlSchemaFacetTypeToString(facet->type),
Daniel Veillard01fa6152004-06-29 17:04:39 +000014007 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014008 }
14009 ret = -1;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000014010 } else if (ret < 0) {
14011 xmlSchemaPErrExt(ctxt, facet->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014012 XML_SCHEMAP_INTERNAL,
Daniel Veillardf4b05d02004-07-05 13:10:37 +000014013 NULL, NULL, NULL,
14014 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000014015 "failed to validate the value '%s' name of the "
14016 "facet '%s' against the base type '%s'.\n",
Daniel Veillardf4b05d02004-07-05 13:10:37 +000014017 facet->value,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014018 xmlSchemaFacetTypeToString(facet->type),
Daniel Veillardf4b05d02004-07-05 13:10:37 +000014019 base->name, NULL, NULL);
14020 ret = -1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014021 }
14022 if (reuseValCtxt == 0)
14023 xmlSchemaFreeValidCtxt(vctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014024 break;
14025 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014026 case XML_SCHEMA_FACET_PATTERN:
14027 facet->regexp = xmlRegexpCompile(facet->value);
14028 if (facet->regexp == NULL) {
14029 xmlSchemaPErr(ctxt, typeDecl->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014030 XML_SCHEMAP_REGEXP_INVALID,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014031 "Type definition '%s': The value '%s' of the "
14032 "facet 'pattern' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000014033 name, facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014034 ret = -1;
14035 }
14036 break;
14037 case XML_SCHEMA_FACET_TOTALDIGITS:
14038 case XML_SCHEMA_FACET_FRACTIONDIGITS:
14039 case XML_SCHEMA_FACET_LENGTH:
14040 case XML_SCHEMA_FACET_MAXLENGTH:
14041 case XML_SCHEMA_FACET_MINLENGTH:{
14042 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000014043
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014044 tmp =
14045 xmlSchemaValidatePredefinedType(nonNegativeIntegerType,
14046 facet->value,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +000014047 &(facet->val));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014048 if (tmp != 0) {
14049 /* error code */
14050 if (ctxt != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014051 xmlSchemaPErrExt(ctxt, facet->node,
14052 XML_SCHEMAP_INVALID_FACET_VALUE,
14053 NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014054 "Type definition '%s': The value '%s' of the "
14055 "facet '%s' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000014056 name, facet->value,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014057 xmlSchemaFacetTypeToString(facet->type),
Daniel Veillard01fa6152004-06-29 17:04:39 +000014058 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014059 }
14060 ret = -1;
14061 }
14062 break;
14063 }
14064 case XML_SCHEMA_FACET_WHITESPACE:{
14065 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
14066 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
14067 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
14068 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
14069 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
14070 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
14071 } else {
14072 if (ctxt != NULL) {
14073 xmlSchemaPErr(ctxt, facet->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014074 XML_SCHEMAP_INVALID_WHITE_SPACE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014075 "Type definition '%s': The value '%s' of the "
14076 "facet 'whiteSpace' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000014077 name, facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014078 }
14079 ret = -1;
14080 }
14081 }
14082 default:
14083 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000014084 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014085 return (ret);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000014086}
14087
14088/**
Daniel Veillard4255d502002-04-16 15:50:10 +000014089 * xmlSchemaCheckDefaults:
14090 * @typeDecl: the schema type definition
14091 * @ctxt: the schema parser context
14092 *
14093 * Checks the default values types, especially for facets
14094 */
14095static void
14096xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014097 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000014098{
Daniel Veillard4255d502002-04-16 15:50:10 +000014099 if (name == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014100 name = typeDecl->name;
14101 /*
14102 * NOTE: It is intended to use the facets list, instead
14103 * of facetSet.
14104 */
14105 if (typeDecl->facets != NULL) {
14106 xmlSchemaFacetPtr facet = typeDecl->facets;
14107
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014108 /*
14109 * Temporarily assign the "schema" to the validation context
14110 * of the parser context. This is needed for NOTATION validation.
14111 */
14112 if (ctxt->vctxt == NULL) {
14113 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
14114 return;
14115 }
14116 ctxt->vctxt->schema = ctxt->schema;
14117
Daniel Veillard01fa6152004-06-29 17:04:39 +000014118 while (facet != NULL) {
14119 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
14120 facet = facet->next;
14121 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014122
14123 ctxt->vctxt->schema = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014124 }
Daniel Veillard4255d502002-04-16 15:50:10 +000014125}
14126
14127/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014128 * xmlSchemaGetCircModelGrDefRef:
14129 * @ctxtGr: the searched model group
14130 * @list: the list of model groups to be processed
14131 *
14132 * This one is intended to be used by
14133 * xmlSchemaCheckGroupDefCircular only.
14134 *
14135 * Returns the circular model group definition reference, otherwise NULL.
14136 */
14137static xmlSchemaTypePtr
14138xmlSchemaGetCircModelGrDefRef(xmlSchemaTypePtr ctxtGrDef,
14139 xmlSchemaTypePtr gr)
14140{
14141 xmlSchemaTypePtr circ = NULL;
14142 int marked;
14143 /*
14144 * We will search for an model group reference which
14145 * references the context model group definition.
14146 */
14147 while (gr != NULL) {
14148 if (((gr->type == XML_SCHEMA_TYPE_GROUP) ||
14149 (gr->type == XML_SCHEMA_TYPE_ALL) ||
14150 (gr->type == XML_SCHEMA_TYPE_SEQUENCE) ||
14151 (gr->type == XML_SCHEMA_TYPE_CHOICE)) &&
14152 (gr->subtypes != NULL)) {
14153 marked = 0;
14154 if ((gr->type == XML_SCHEMA_TYPE_GROUP) &&
14155 (gr->ref != NULL)) {
14156 if (gr->subtypes == ctxtGrDef)
14157 return (gr);
14158 else if (gr->subtypes->flags &
14159 XML_SCHEMAS_TYPE_MARKED) {
14160 gr = gr->next;
14161 continue;
14162 } else {
14163 /*
14164 * Mark to avoid infinite recursion on
14165 * circular references not yet examined.
14166 */
14167 gr->subtypes->flags |= XML_SCHEMAS_TYPE_MARKED;
14168 marked = 1;
14169 }
14170 if (gr->subtypes->subtypes != NULL)
14171 circ = xmlSchemaGetCircModelGrDefRef(ctxtGrDef,
14172 gr->subtypes->subtypes);
14173 /*
14174 * Unmark the visited model group definition.
14175 */
14176 if (marked)
14177 gr->subtypes->flags ^= XML_SCHEMAS_TYPE_MARKED;
14178 if (circ != NULL)
14179 return (circ);
14180 } else {
14181 circ = xmlSchemaGetCircModelGrDefRef(ctxtGrDef,
14182 (xmlSchemaTypePtr) gr->subtypes);
14183 if (circ != NULL)
14184 return (circ);
14185 }
14186
14187 }
14188 gr = gr->next;
14189 }
14190 return (NULL);
14191}
14192
14193/**
14194 * xmlSchemaCheckGroupDefCircular:
14195 * attrGr: the model group definition
14196 * @ctxt: the parser context
14197 * @name: the name
14198 *
14199 * Checks for circular references to model group definitions.
14200 */
14201static void
14202xmlSchemaCheckGroupDefCircular(xmlSchemaTypePtr modelGrDef,
14203 xmlSchemaParserCtxtPtr ctxt,
14204 const xmlChar * name ATTRIBUTE_UNUSED)
14205{
14206 /*
14207 * Schema Component Constraint: Model Group Correct
14208 * 2 Circular groups are disallowed. That is, within the {particles}
14209 * of a group there must not be at any depth a particle whose {term}
14210 * is the group itself.
14211 */
14212 /*
14213 * NOTE: "gr->subtypes" holds the referenced group.
14214 */
14215 if ((modelGrDef->type != XML_SCHEMA_TYPE_GROUP) ||
14216 ((modelGrDef->flags & XML_SCHEMAS_TYPE_GLOBAL) == 0) ||
14217 (modelGrDef->subtypes == NULL))
14218 return;
14219 else {
14220 xmlSchemaTypePtr circ;
14221
14222 circ = xmlSchemaGetCircModelGrDefRef(modelGrDef, modelGrDef->subtypes);
14223 if (circ != NULL) {
14224 /*
14225 * TODO: Report the referenced attr group as QName.
14226 */
14227 xmlSchemaPCustomErr(ctxt,
14228 XML_SCHEMAP_MG_PROPS_CORRECT_2,
14229 NULL, NULL, circ->node,
14230 "Circular reference to the model group definition '%s' "
14231 "defined", modelGrDef->name);
14232 /*
14233 * NOTE: We will cut the reference to avoid further
14234 * confusion of the processor.
14235 * TODO: SPEC: Does the spec define how to process here?
14236 */
14237 circ->subtypes = NULL;
14238 }
14239 }
14240}
14241
14242
14243/**
14244 * xmlSchemaGetCircAttrGrRef:
14245 * @ctxtGr: the searched attribute group
14246 * @attr: the current attribute list to be processed
14247 *
14248 * This one is intended to be used by
14249 * xmlSchemaCheckSRCAttributeGroupCircular only.
14250 *
14251 * Returns the circular attribute grou reference, otherwise NULL.
14252 */
14253static xmlSchemaAttributeGroupPtr
14254xmlSchemaGetCircAttrGrRef(xmlSchemaAttributeGroupPtr ctxtGr,
14255 xmlSchemaAttributePtr attr)
14256{
14257 xmlSchemaAttributeGroupPtr circ = NULL, gr;
14258 int marked;
14259 /*
14260 * We will search for an attribute group reference which
14261 * references the context attribute group.
14262 */
14263 while (attr != NULL) {
14264 marked = 0;
14265 if (attr->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
14266 gr = (xmlSchemaAttributeGroupPtr) attr;
14267 if (gr->refItem != NULL) {
14268 if (gr->refItem == ctxtGr)
14269 return (gr);
14270 else if (gr->refItem->flags &
14271 XML_SCHEMAS_ATTRGROUP_MARKED) {
14272 attr = attr->next;
14273 continue;
14274 } else {
14275 /*
14276 * Mark as visited to avoid infinite recursion on
14277 * circular references not yet examined.
14278 */
14279 gr->refItem->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
14280 marked = 1;
14281 }
14282 }
14283 if (gr->attributes != NULL)
14284 circ = xmlSchemaGetCircAttrGrRef(ctxtGr, gr->attributes);
14285 /*
14286 * Unmark the visited group's attributes.
14287 */
14288 if (marked)
14289 gr->refItem->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
14290 if (circ != NULL)
14291 return (circ);
14292 }
14293 attr = attr->next;
14294 }
14295 return (NULL);
14296}
14297
14298/**
14299 * xmlSchemaCheckSRCAttributeGroupCircular:
14300 * attrGr: the attribute group definition
14301 * @ctxt: the parser context
14302 * @name: the name
14303 *
14304 * Checks for circular references of attribute groups.
14305 */
14306static void
14307xmlSchemaCheckAttributeGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
14308 xmlSchemaParserCtxtPtr ctxt,
14309 const xmlChar * name ATTRIBUTE_UNUSED)
14310{
14311 /*
14312 * Schema Representation Constraint:
14313 * Attribute Group Definition Representation OK
14314 * 3 Circular group reference is disallowed outside <redefine>.
14315 * That is, unless this element information item's parent is
14316 * <redefine>, then among the [children], if any, there must
14317 * not be an <attributeGroup> with ref [attribute] which resolves
14318 * to the component corresponding to this <attributeGroup>. Indirect
14319 * circularity is also ruled out. That is, when QName resolution
14320 * (Schema Document) (§3.15.3) is applied to a ·QName· arising from
14321 * any <attributeGroup>s with a ref [attribute] among the [children],
14322 * it must not be the case that a ·QName· is encountered at any depth
14323 * which resolves to the component corresponding to this <attributeGroup>.
14324 */
14325 /*
14326 * Only global components can be referenced.
14327 */
14328 if (((attrGr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) == 0) ||
14329 (attrGr->attributes == NULL))
14330 return;
14331 else {
14332 xmlSchemaAttributeGroupPtr circ;
14333
14334 circ = xmlSchemaGetCircAttrGrRef(attrGr, attrGr->attributes);
14335 if (circ != NULL) {
14336 /*
14337 * TODO: Report the referenced attr group as QName.
14338 */
14339 xmlSchemaPCustomErr(ctxt,
14340 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
14341 NULL, NULL, circ->node,
14342 "Circular reference to the attribute group '%s' "
14343 "defined", attrGr->name);
14344 /*
14345 * NOTE: We will cut the reference to avoid further
14346 * confusion of the processor.
14347 * BADSPEC: The spec should define how to process in this case.
14348 */
14349 circ->attributes = NULL;
14350 circ->refItem = NULL;
14351 }
14352 }
14353}
14354
14355/**
Daniel Veillard13e04c62002-04-23 17:51:29 +000014356 * xmlSchemaAttrGrpFixup:
14357 * @attrgrpDecl: the schema attribute definition
14358 * @ctxt: the schema parser context
14359 * @name: the attribute name
14360 *
14361 * Fixes finish doing the computations on the attributes definitions
14362 */
14363static void
Daniel Veillard3646d642004-06-02 19:19:14 +000014364xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014365 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +000014366{
14367 if (name == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000014368 name = attrgrp->name;
14369 if (attrgrp->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014370 return;
Daniel Veillard3646d642004-06-02 19:19:14 +000014371 if (attrgrp->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014372 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +000014373
Daniel Veillardc0826a72004-08-10 14:17:33 +000014374 ref = xmlSchemaGetAttributeGroup(ctxt->schema, attrgrp->ref,
14375 attrgrp->refNs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014376 if (ref == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014377 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014378 XML_SCHEMAP_SRC_RESOLVE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014379 NULL, (xmlSchemaTypePtr) attrgrp, attrgrp->node,
14380 "ref", attrgrp->ref, attrgrp->refNs,
14381 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014382 return;
14383 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014384 attrgrp->refItem = ref;
14385 /*
14386 * Check for self reference!
14387 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014388 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000014389 attrgrp->attributes = ref->attributes;
14390 attrgrp->attributeWildcard = ref->attributeWildcard;
14391 }
Daniel Veillard13e04c62002-04-23 17:51:29 +000014392}
14393
14394/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014395 * xmlSchemaAttrCheckValConstr:
14396 * @item: an schema attribute declaration/use
14397 * @ctxt: a schema parser context
14398 * @name: the name of the attribute
14399 *
14400 * Validates the value constraints of an attribute declaration/use.
Daniel Veillard4255d502002-04-16 15:50:10 +000014401 *
14402 * Fixes finish doing the computations on the attributes definitions
14403 */
14404static void
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014405xmlSchemaCheckAttrValConstr(xmlSchemaAttributePtr item,
14406 xmlSchemaParserCtxtPtr ctxt,
14407 const xmlChar * name ATTRIBUTE_UNUSED)
14408{
14409
14410 /*
14411 * a-props-correct
14412 * Schema Component Constraint: Attribute Declaration Properties Correct
14413 *
14414 * 2 if there is a {value constraint}, the canonical lexical
14415 * representation of its value must be ·valid· with respect
14416 * to the {type definition} as defined in String Valid (§3.14.4).
14417 */
14418
14419 if (item->defValue != NULL) {
14420 int ret;
14421 xmlNodePtr node;
14422 xmlSchemaTypePtr type;
14423
14424 if (item->subtypes == NULL) {
14425 xmlSchemaPErr(ctxt, item->node,
14426 XML_SCHEMAP_INTERNAL,
14427 "Internal error: xmlSchemaCheckAttrValConstr, "
14428 "type is missing... skipping validation of "
14429 "value constraint", NULL, NULL);
14430 return;
14431 }
14432
14433 /*
14434 * TODO: Try to avoid creating a new context.
14435 * TODO: This all is not very performant.
14436 */
14437 type = item->subtypes;
14438 /*
14439 * Ensure there's validation context.
14440 */
14441 if (ctxt->vctxt == NULL) {
14442 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1) {
14443 xmlSchemaPErr(ctxt, item->node,
14444 XML_SCHEMAP_INTERNAL,
14445 "Internal error: xmlSchemaCheckAttrValConstr, "
14446 "creating a new validation context.\n",
14447 NULL, NULL);
14448 return;
14449 }
14450 }
14451
14452 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
14453 node = (xmlNodePtr) xmlHasProp(item->node, BAD_CAST "fixed");
14454 else
14455 node = (xmlNodePtr) xmlHasProp(item->node, BAD_CAST "default");
14456 ctxt->vctxt->node = node;
14457 ctxt->vctxt->cur = NULL;
14458 /*
14459 * NOTE: This call does not check the content nodes,
14460 * since they are not available:
14461 * facet->node is just the node holding the facet
14462 * definition, *not* the attribute holding the *value*
14463 * of the facet.
14464 */
14465 ret = xmlSchemaValidateSimpleTypeValue(ctxt->vctxt, type,
14466 item->defValue, 0, 1, 1, 0);
14467 if (ret == 0) {
14468 /*
14469 * Store the computed value.
14470 */
14471 item->defVal = ctxt->vctxt->value;
14472 ctxt->vctxt->value = NULL;
14473 } else if (ret > 0) {
14474 if (ctxt != NULL) {
14475 xmlSchemaPSimpleTypeErr(ctxt,
14476 XML_SCHEMAP_A_PROPS_CORRECT_2,
14477 NULL, NULL, node,
14478 type, NULL, item->defValue,
14479 NULL, NULL, NULL);
14480 }
14481 } else if (ret < 0) {
14482 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
14483 NULL, NULL, node,
14484 "Internal error: xmlSchemaAttrCheckValConstr, "
14485 "failed to validate the value constraint of the "
14486 "attribute decl/use against the type '%s'",
14487 type->name);
14488 }
14489 }
14490}
14491
14492#if 0 /* Not used yet. */
14493static int
14494xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
14495 xmlSchemaElementPtr edecl)
14496{
14497 /*
14498 * TODO: 1 The values of the properties of an element declaration must be as
14499 * described in the property tableau in The Element Declaration Schema
14500 * Component (§3.3.1), modulo the impact of Missing Sub-components (§5.3).
14501 */
14502 /*
14503 * 2 If there is a {value constraint}, the canonical lexical
14504 * representation of its value must be ·valid· with respect to the {type
14505 * definition} as defined in Element Default Valid (Immediate) (§3.3.6).
14506 *
14507 * NOTE: This is done in xmlSchemaCheckElemValConstr.
14508 */
14509 /*
14510 * 3 If there is a non-·absent· {substitution group affiliation},
14511 * then {scope} must be global.
14512 *
14513 * NOTE: This is done in xmlSchemaParseElement.
14514 * TODO: Move it to this layer here.
14515 */
14516 /*
14517 * TODO: 4 If there is a {substitution group affiliation}, the {type definition}
14518 * of the element declaration must be validly derived from the {type
14519 * definition} of the {substitution group affiliation}, given the value
14520 * of the {substitution group exclusions} of the {substitution group
14521 * affiliation}, as defined in Type Derivation OK (Complex) (§3.4.6)
14522 * (if the {type definition} is complex) or as defined in
14523 * Type Derivation OK (Simple) (§3.14.6) (if the {type definition} is
14524 * simple).
14525 */
14526 /*
14527 * TODO: 5 If the {type definition} or {type definition}'s {content type}
14528 * is or is derived from ID then there must not be a {value constraint}.
14529 * Note: The use of ID as a type definition for elements goes beyond
14530 * XML 1.0, and should be avoided if backwards compatibility is desired
14531 */
14532 /*
14533 * TODO: 6 Circular substitution groups are disallowed. That is, it must not
14534 * be possible to return to an element declaration by repeatedly following
14535 * the {substitution group affiliation} property.
14536 */
14537}
14538#endif
14539
14540/**
14541 * xmlSchemaCheckElemValConstr:
14542 * @item: an schema element declaration/particle
14543 * @ctxt: a schema parser context
14544 * @name: the name of the attribute
14545 *
14546 * Validates the value constraints of an element declaration.
14547 *
14548 * Fixes finish doing the computations on the element declarations.
14549 */
14550static void
14551xmlSchemaCheckElemValConstr(xmlSchemaElementPtr decl,
14552 xmlSchemaParserCtxtPtr ctxt,
14553 const xmlChar * name ATTRIBUTE_UNUSED)
14554{
14555 if (decl->value != NULL) {
14556 int ret;
14557 xmlNodePtr node = NULL;
14558 xmlSchemaTypePtr type;
14559
14560 /*
14561 * 2 If there is a {value constraint}, the canonical lexical
14562 * representation of its value must be ·valid· with respect to the {type
14563 * definition} as defined in Element Default Valid (Immediate) (§3.3.6).
14564 */
14565 if (decl->subtypes == NULL) {
14566 xmlSchemaPErr(ctxt, decl->node,
14567 XML_SCHEMAP_INTERNAL,
14568 "Internal error: xmlSchemaCheckElemValConstr, "
14569 "type is missing... skipping validation of "
14570 "the value constraint", NULL, NULL);
14571 return;
14572 }
14573 /*
14574 * Ensure there's a validation context.
14575 */
14576 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
14577 return;
14578
14579 type = decl->subtypes;
14580
14581 if (decl->node != NULL) {
14582 if (decl->flags & XML_SCHEMAS_ELEM_FIXED)
14583 node = (xmlNodePtr) xmlHasProp(decl->node, BAD_CAST "fixed");
14584 else
14585 node = (xmlNodePtr) xmlHasProp(decl->node, BAD_CAST "default");
14586 }
14587 ctxt->vctxt->node = node;
14588 ctxt->vctxt->cur = NULL;
14589 ret = xmlSchemaCheckCOSValidDefault(ctxt, ctxt->vctxt, type, decl->value,
14590 node);
14591 if (ret == 0) {
14592 /*
14593 * Consume the computed value.
14594 */
14595 decl->defVal = ctxt->vctxt->value;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000014596 ctxt->vctxt->value = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014597 } else if (ret < 0) {
14598 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
14599 NULL, NULL, node,
14600 "Internal error: xmlSchemaElemCheckValConstr, "
14601 "failed to validate the value constraint of the "
14602 "element declaration '%s'",
14603 decl->name);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000014604 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014605 }
14606}
14607
14608/**
14609 * xmlSchemaAttrFixup:
14610 * @item: an schema attribute declaration/use.
14611 * @ctxt: a schema parser context
14612 * @name: the name of the attribute
14613 *
14614 * Fixes finish doing the computations on attribute declarations/uses.
14615 */
14616static void
14617xmlSchemaAttrFixup(xmlSchemaAttributePtr item,
14618 xmlSchemaParserCtxtPtr ctxt,
14619 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000014620{
Daniel Veillardc0826a72004-08-10 14:17:33 +000014621 /*
14622 * TODO: If including this is done twice (!) for every attribute.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014623 * -> Hmm, check if this is still done.
Daniel Veillardc0826a72004-08-10 14:17:33 +000014624 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014625 /*
14626 * The simple type definition corresponding to the <simpleType> element
14627 * information item in the [children], if present, otherwise the simple
14628 * type definition ·resolved· to by the ·actual value· of the type
14629 * [attribute], if present, otherwise the ·simple ur-type definition·.
14630 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014631 if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
Daniel Veillardc0826a72004-08-10 14:17:33 +000014632 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014633 item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
14634 if (item->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014635 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014636 if (item->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014637 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000014638
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014639 type = xmlSchemaGetType(ctxt->schema, item->typeName,
14640 item->typeNs);
14641 if ((type == NULL) || (! IS_SIMPLE_TYPE(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014642 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014643 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014644 NULL, (xmlSchemaTypePtr) item, item->node,
14645 "type", item->typeName, item->typeNs,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014646 XML_SCHEMA_TYPE_SIMPLE, NULL);
14647 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014648 item->subtypes = type;
14649
14650 } else if (item->ref != NULL) {
14651 xmlSchemaAttributePtr decl;
Daniel Veillard4255d502002-04-16 15:50:10 +000014652
Daniel Veillardc0826a72004-08-10 14:17:33 +000014653 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014654 * We have an attribute use here; assign the referenced
14655 * attribute declaration.
14656 */
14657 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000014658 * TODO: Evaluate, what errors could occur if the declaration is not
14659 * found. It might be possible that the "typefixup" might crash if
14660 * no ref declaration was found.
14661 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014662 decl = xmlSchemaGetAttribute(ctxt->schema, item->ref, item->refNs);
14663 if (decl == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014664 xmlSchemaPResCompAttrErr(ctxt,
14665 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014666 NULL, (xmlSchemaTypePtr) item, item->node,
14667 "ref", item->ref, item->refNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014668 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014669 return;
14670 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014671 item->refDecl = decl;
14672 xmlSchemaAttrFixup(decl, ctxt, NULL);
14673
14674 item->subtypes = decl->subtypes;
14675 /*
14676 * Attribute Use Correct
14677 * au-props-correct.2: If the {attribute declaration} has a fixed
14678 * {value constraint}, then if the attribute use itself has a
14679 * {value constraint}, it must also be fixed and its value must match
14680 * that of the {attribute declaration}'s {value constraint}.
14681 */
14682 if ((decl->flags & XML_SCHEMAS_ATTR_FIXED) &&
14683 (item->defValue != NULL)) {
14684 if (((item->flags & XML_SCHEMAS_ATTR_FIXED) == 0) ||
14685 (!xmlStrEqual(item->defValue, decl->defValue))) {
14686 xmlSchemaPCustomErr(ctxt,
14687 XML_SCHEMAP_AU_PROPS_CORRECT_2,
14688 NULL, NULL, item->node,
14689 "The value constraint must be fixed "
14690 "and match the referenced attribute "
14691 "declarations's value constraint '%s'",
14692 decl->defValue);
14693 }
14694 /*
14695 * FUTURE: One should change the values of the attr. use
14696 * if ever validation should be attempted even if the
14697 * schema itself was not fully valid.
14698 */
14699 }
Daniel Veillard3646d642004-06-02 19:19:14 +000014700 } else {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014701 item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
14702 }
Daniel Veillard4255d502002-04-16 15:50:10 +000014703}
14704
14705/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000014706 * xmlSchemaResolveIDCKeyRef:
14707 * @idc: the identity-constraint definition
14708 * @ctxt: the schema parser context
14709 * @name: the attribute name
14710 *
14711 * Resolve keyRef references to key/unique IDCs.
14712 */
14713static void
14714xmlSchemaResolveIDCKeyRef(xmlSchemaIDCPtr idc,
14715 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000014716 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000014717{
14718 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
14719 return;
14720 if (idc->ref->name != NULL) {
14721 idc->ref->item = (xmlSchemaBasicItemPtr) xmlHashLookup2(
14722 ctxt->schema->idcDef,
14723 idc->ref->name,
14724 idc->ref->targetNamespace);
14725 if (idc->ref->item == NULL) {
14726 /*
14727 * TODO: It is actually not an error to fail to resolve.
14728 */
14729 xmlSchemaPResCompAttrErr(ctxt,
14730 XML_SCHEMAP_SRC_RESOLVE,
14731 NULL, (xmlSchemaTypePtr) idc, idc->node,
14732 "refer", idc->ref->name,
14733 idc->ref->targetNamespace,
14734 XML_SCHEMA_TYPE_IDC_KEYREF, NULL);
14735 return;
14736 }
14737 }
14738}
14739
14740/**
Daniel Veillard4255d502002-04-16 15:50:10 +000014741 * xmlSchemaParse:
14742 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000014743 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000014744 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +000014745 * XML Shema struture which can be used to validate instances.
14746 * *WARNING* this interface is highly subject to change
14747 *
14748 * Returns the internal XML Schema structure built from the resource or
14749 * NULL in case of error
14750 */
14751xmlSchemaPtr
14752xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
14753{
14754 xmlSchemaPtr ret = NULL;
14755 xmlDocPtr doc;
Daniel Veillardbd2904b2003-11-25 15:38:59 +000014756 xmlNodePtr root;
Daniel Veillarddda22c12004-01-24 08:31:30 +000014757 int preserve = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000014758
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014759 /*
14760 * This one is used if the schema to be parsed was specified via
14761 * the API; i.e. not automatically by the validated instance document.
14762 */
14763
Daniel Veillard4255d502002-04-16 15:50:10 +000014764 xmlSchemaInitTypes();
14765
Daniel Veillard6045c902002-10-09 21:13:59 +000014766 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +000014767 return (NULL);
14768
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000014769 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000014770 ctxt->counter = 0;
14771 ctxt->container = NULL;
14772
14773 /*
14774 * First step is to parse the input document into an DOM/Infoset
14775 */
Daniel Veillard6045c902002-10-09 21:13:59 +000014776 if (ctxt->URL != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000014777 doc = xmlReadFile((const char *) ctxt->URL, NULL,
14778 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014779 if (doc == NULL) {
14780 xmlSchemaPErr(ctxt, NULL,
14781 XML_SCHEMAP_FAILED_LOAD,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014782 "xmlSchemaParse: could not load '%s'.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014783 ctxt->URL, NULL);
14784 return (NULL);
14785 }
Daniel Veillard6045c902002-10-09 21:13:59 +000014786 } else if (ctxt->buffer != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000014787 doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
14788 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014789 if (doc == NULL) {
14790 xmlSchemaPErr(ctxt, NULL,
14791 XML_SCHEMAP_FAILED_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014792 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014793 NULL, NULL);
14794 return (NULL);
14795 }
14796 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard65765282004-01-08 16:59:30 +000014797 ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
Daniel Veillard9d751502003-10-29 13:21:47 +000014798 } else if (ctxt->doc != NULL) {
14799 doc = ctxt->doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000014800 preserve = 1;
Daniel Veillard6045c902002-10-09 21:13:59 +000014801 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014802 xmlSchemaPErr(ctxt, NULL,
14803 XML_SCHEMAP_NOTHING_TO_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014804 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014805 NULL, NULL);
14806 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000014807 }
14808
14809 /*
14810 * Then extract the root and Schema parse it
14811 */
14812 root = xmlDocGetRootElement(doc);
14813 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014814 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
14815 XML_SCHEMAP_NOROOT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014816 "The schema has no document element.\n", NULL, NULL);
Daniel Veillarddda22c12004-01-24 08:31:30 +000014817 if (!preserve) {
14818 xmlFreeDoc(doc);
14819 }
Daniel Veillard4255d502002-04-16 15:50:10 +000014820 return (NULL);
14821 }
14822
14823 /*
14824 * Remove all the blank text nodes
14825 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +000014826 xmlSchemaCleanupDoc(ctxt, root);
Daniel Veillard4255d502002-04-16 15:50:10 +000014827
14828 /*
14829 * Then do the parsing for good
14830 */
14831 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillard1d913862003-11-21 00:28:39 +000014832 if (ret == NULL) {
Daniel Veillarddda22c12004-01-24 08:31:30 +000014833 if (!preserve) {
14834 xmlFreeDoc(doc);
14835 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014836 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +000014837 }
Daniel Veillard4255d502002-04-16 15:50:10 +000014838 ret->doc = doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000014839 ret->preserve = preserve;
Daniel Veillard4255d502002-04-16 15:50:10 +000014840 ctxt->schema = ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014841 ctxt->ctxtType = NULL;
14842 ctxt->parentItem = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000014843 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +000014844 * Then fixup all attributes declarations
14845 */
14846 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
14847
14848 /*
14849 * Then fixup all attributes group declarations
14850 */
14851 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
14852 ctxt);
14853
14854 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000014855 * Resolve identity-constraint keyRefs.
14856 */
14857 xmlHashScan(ret->idcDef, (xmlHashScanner) xmlSchemaResolveIDCKeyRef, ctxt);
14858
14859 /*
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014860 * Check attribute groups for circular references.
14861 */
14862 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner)
14863 xmlSchemaCheckAttributeGroupCircular, ctxt);
14864
14865 /*
14866 * Then fixup all model group definitions.
14867 */
14868 xmlHashScan(ret->groupDecl, (xmlHashScanner) xmlSchemaGroupDefFixup, ctxt);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014869
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014870 /*
Daniel Veillard4255d502002-04-16 15:50:10 +000014871 * Then fixup all types properties
Daniel Veillardc0826a72004-08-10 14:17:33 +000014872 */
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014873 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014874
14875 /*
14876 * Then fix references of element declaration; apply constraints.
14877 */
14878 xmlHashScanFull(ret->elemDecl,
14879 (xmlHashScannerFull) xmlSchemaRefFixupCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000014880
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014881 /*
14882 * Check model groups defnitions for circular references.
14883 */
14884 xmlHashScan(ret->groupDecl, (xmlHashScanner)
14885 xmlSchemaCheckGroupDefCircular, ctxt);
14886
Daniel Veillard4255d502002-04-16 15:50:10 +000014887 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014888 * Then build the content model for all complex types
Daniel Veillard4255d502002-04-16 15:50:10 +000014889 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014890 xmlHashScan(ret->typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014891 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000014892
14893 /*
14894 * Then check the defaults part of the type like facets values
14895 */
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000014896 /* OLD: xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaCheckDefaults, ctxt); */
Daniel Veillard4255d502002-04-16 15:50:10 +000014897
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014898 /*
14899 * Validate the value constraint of attribute declarations/uses.
14900 */
14901 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaCheckAttrValConstr, ctxt);
14902
14903 /*
14904 * Validate the value constraint of element declarations.
14905 */
14906 xmlHashScan(ret->elemDecl, (xmlHashScanner) xmlSchemaCheckElemValConstr, ctxt);
14907
Daniel Veillardc0826a72004-08-10 14:17:33 +000014908
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000014909 if (ctxt->nberrors != 0) {
14910 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014911 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000014912 }
Daniel Veillard4255d502002-04-16 15:50:10 +000014913 return (ret);
14914}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014915
Daniel Veillard4255d502002-04-16 15:50:10 +000014916/**
Daniel Veillard01c13b52002-12-10 15:19:08 +000014917 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +000014918 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +000014919 * @err: the error callback
14920 * @warn: the warning callback
14921 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +000014922 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000014923 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000014924 */
14925void
14926xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014927 xmlSchemaValidityErrorFunc err,
14928 xmlSchemaValidityWarningFunc warn, void *ctx)
14929{
Daniel Veillard4255d502002-04-16 15:50:10 +000014930 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014931 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000014932 ctxt->error = err;
14933 ctxt->warning = warn;
14934 ctxt->userData = ctx;
14935}
14936
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014937/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000014938 * xmlSchemaGetParserErrors:
14939 * @ctxt: a XMl-Schema parser context
14940 * @err: the error callback result
14941 * @warn: the warning callback result
14942 * @ctx: contextual data for the callbacks result
14943 *
14944 * Get the callback information used to handle errors for a parser context
14945 *
14946 * Returns -1 in case of failure, 0 otherwise
14947 */
14948int
14949xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
14950 xmlSchemaValidityErrorFunc * err,
14951 xmlSchemaValidityWarningFunc * warn, void **ctx)
14952{
14953 if (ctxt == NULL)
14954 return(-1);
14955 if (err != NULL)
14956 *err = ctxt->error;
14957 if (warn != NULL)
14958 *warn = ctxt->warning;
14959 if (ctx != NULL)
14960 *ctx = ctxt->userData;
14961 return(0);
14962}
14963
14964/**
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014965 * xmlSchemaFacetTypeToString:
14966 * @type: the facet type
14967 *
14968 * Convert the xmlSchemaTypeType to a char string.
14969 *
14970 * Returns the char string representation of the facet type if the
14971 * type is a facet and an "Internal Error" string otherwise.
14972 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014973static const xmlChar *
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014974xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
14975{
14976 switch (type) {
14977 case XML_SCHEMA_FACET_PATTERN:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014978 return (BAD_CAST "pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014979 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014980 return (BAD_CAST "maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014981 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014982 return (BAD_CAST "maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014983 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014984 return (BAD_CAST "minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014985 case XML_SCHEMA_FACET_MININCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014986 return (BAD_CAST "minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014987 case XML_SCHEMA_FACET_WHITESPACE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014988 return (BAD_CAST "whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014989 case XML_SCHEMA_FACET_ENUMERATION:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014990 return (BAD_CAST "enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014991 case XML_SCHEMA_FACET_LENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014992 return (BAD_CAST "length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014993 case XML_SCHEMA_FACET_MAXLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014994 return (BAD_CAST "maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014995 case XML_SCHEMA_FACET_MINLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014996 return (BAD_CAST "minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014997 case XML_SCHEMA_FACET_TOTALDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014998 return (BAD_CAST "totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014999 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000015000 return (BAD_CAST "fractionDigits");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000015001 default:
15002 break;
15003 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000015004 return (BAD_CAST "Internal Error");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000015005}
15006
Daniel Veillardc0826a72004-08-10 14:17:33 +000015007static int
15008xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
15009{
15010 xmlSchemaTypePtr anc;
15011
15012 /*
15013 * The normalization type can be changed only for types which are derived
15014 * from xsd:string.
15015 */
15016 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000015017 if (type->builtInType == XML_SCHEMAS_STRING)
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000015018 return(XML_SCHEMAS_FACET_PRESERVE);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000015019 else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000015020 return(XML_SCHEMAS_FACET_REPLACE);
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000015021 else if (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)
15022 /*
15023 * Note that we assume a whitespace of preserve for anySimpleType.
15024 */
15025 return(XML_SCHEMAS_FACET_PRESERVE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015026 else {
15027 /*
15028 * For all ·atomic· datatypes other than string (and types ·derived·
15029 * by ·restriction· from it) the value of whiteSpace is fixed to
15030 * collapse
15031 */
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000015032 return(XML_SCHEMAS_FACET_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015033 }
15034 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
15035 /*
15036 * For list types the facet "whiteSpace" is fixed to "collapse".
15037 */
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000015038 return (XML_SCHEMAS_FACET_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015039 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000015040 return (XML_SCHEMAS_FACET_UNKNOWN);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015041 } else if (type->facetSet != NULL) {
15042 xmlSchemaTypePtr anyST;
15043 xmlSchemaFacetLinkPtr lin;
15044
15045 /*
15046 * Atomic types.
15047 */
15048 anyST = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
15049 anc = type->baseType;
15050 do {
15051 /*
15052 * For all ·atomic· datatypes other than string (and types ·derived·
15053 * by ·restriction· from it) the value of whiteSpace is fixed to
15054 * collapse
15055 */
15056 if ((anc->type == XML_SCHEMA_TYPE_BASIC) &&
15057 (anc->builtInType == XML_SCHEMAS_STRING)) {
15058
15059 lin = type->facetSet;
15060 do {
15061 if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000015062 return(lin->facet->whitespace);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015063 break;
15064 }
15065 lin = lin->next;
15066 } while (lin != NULL);
15067 break;
15068 }
15069 anc = anc->baseType;
15070 } while (anc != anyST);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000015071 return (XML_SCHEMAS_FACET_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015072 }
15073 return (-1);
15074}
15075
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000015076/**
Daniel Veillard377e1a92004-04-16 16:30:05 +000015077 * xmlSchemaValidateFacetsInternal:
15078 * @ctxt: a schema validation context
Daniel Veillardc0826a72004-08-10 14:17:33 +000015079 * @type: the type holding the facets
Daniel Veillard377e1a92004-04-16 16:30:05 +000015080 * @facets: the list of facets to check
15081 * @value: the lexical repr of the value to validate
15082 * @val: the precomputed value
William M. Bracke7091952004-05-11 15:09:58 +000015083 * @fireErrors: if 0, only internal errors will be fired;
15084 * otherwise all errors will be fired.
Daniel Veillard377e1a92004-04-16 16:30:05 +000015085 *
15086 * Check a value against all facet conditions
15087 *
15088 * Returns 0 if the element is schemas valid, a positive error code
15089 * number otherwise and -1 in case of internal or API error.
15090 */
15091static int
15092xmlSchemaValidateFacetsInternal(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015093 xmlSchemaTypePtr type,
15094 const xmlChar * value,
15095 unsigned long length,
15096 int fireErrors)
Daniel Veillard377e1a92004-04-16 16:30:05 +000015097{
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000015098 int ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015099 xmlNodePtr node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015100 xmlSchemaTypePtr biType; /* The build-in type. */
15101 xmlSchemaTypePtr tmpType;
15102 xmlSchemaFacetLinkPtr facetLink;
Daniel Veillardc7e3cc42004-09-28 12:33:52 +000015103 int retFacet;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015104 xmlSchemaFacetPtr facet;
15105 unsigned long len = 0;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000015106
Daniel Veillardc0826a72004-08-10 14:17:33 +000015107#ifdef DEBUG_UNION_VALIDATION
15108 printf("Facets of type: '%s'\n", (const char *) type->name);
15109 printf(" fireErrors: %d\n", fireErrors);
15110#endif
15111
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015112 node = ctxt->node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015113 /*
15114 * NOTE: Do not jump away, if the facetSet of the given type is
15115 * empty: until now, "pattern" facets of the *base types* need to
15116 * be checked as well.
15117 */
15118 biType = type->baseType;
15119 while ((biType != NULL) && (biType->type != XML_SCHEMA_TYPE_BASIC))
15120 biType = biType->baseType;
15121 if (biType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015122 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015123 "Internal error: xmlSchemaValidateFacetsInternal, "
15124 "the base type axis of the given type '%s' does not resolve to "
15125 "a built-in type.\n",
15126 type->name, NULL);
15127 return (-1);
15128 }
15129
15130 if (type->facetSet != NULL) {
15131 facetLink = type->facetSet;
15132 while (facetLink != NULL) {
15133 facet = facetLink->facet;
15134 /*
15135 * Skip the pattern "whiteSpace": it is used to
15136 * format the character content beforehand.
15137 */
15138 switch (facet->type) {
15139 case XML_SCHEMA_FACET_WHITESPACE:
15140 case XML_SCHEMA_FACET_PATTERN:
15141 case XML_SCHEMA_FACET_ENUMERATION:
15142 break;
15143 case XML_SCHEMA_FACET_LENGTH:
15144 case XML_SCHEMA_FACET_MINLENGTH:
15145 case XML_SCHEMA_FACET_MAXLENGTH:
15146 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
15147 ret = xmlSchemaValidateListSimpleTypeFacet(facet,
15148 value, length, 0);
15149 len = length;
15150 } else
15151 ret = xmlSchemaValidateLengthFacet(biType, facet,
15152 value, ctxt->value, &len);
15153 break;
15154 default:
15155 ret = xmlSchemaValidateFacet(biType, facet, value,
15156 ctxt->value);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015157 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000015158 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015159 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015160 "Internal error: xmlSchemaValidateFacetsInternal, "
15161 "validating facet of type '%s'.\n",
15162 type->name, NULL);
15163 break;
15164 } else if ((ret > 0) && (fireErrors)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015165 xmlSchemaVFacetErr(ctxt, ret, node, value, len,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015166 type, facet, NULL, NULL, NULL, NULL);
15167 }
15168
15169 facetLink = facetLink->next;
15170 }
15171 if (ret >= 0) {
15172 /*
15173 * Process enumerations.
15174 */
15175 retFacet = 0;
15176 facetLink = type->facetSet;
15177 while (facetLink != NULL) {
15178 if (facetLink->facet->type == XML_SCHEMA_FACET_ENUMERATION) {
15179 retFacet = xmlSchemaValidateFacet(biType, facetLink->facet,
15180 value, ctxt->value);
15181 if (retFacet <= 0)
15182 break;
15183 }
15184 facetLink = facetLink->next;
15185 }
15186 if (retFacet > 0) {
15187 ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
15188 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015189 xmlSchemaVFacetErr(ctxt, ret, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015190 value, 0, type, NULL, NULL, NULL, NULL, NULL);
15191 } else if (retFacet < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015192 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015193 "Internal error: xmlSchemaValidateFacetsInternal, "
15194 "validating facet of type '%s'.\n",
15195 BAD_CAST "enumeration", NULL);
15196 ret = -1;
15197 }
15198 }
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000015199 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000015200 if (ret >= 0) {
15201 /*
15202 * Process patters. Pattern facets are ORed at type level
15203 * and ANDed if derived. Walk the base type axis.
15204 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000015205 tmpType = type;
15206 facet = NULL;
15207 do {
15208 retFacet = 0;
15209 for (facetLink = tmpType->facetSet; facetLink != NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015210 facetLink = facetLink->next) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015211 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
15212 continue;
15213 retFacet = xmlSchemaValidateFacet(biType, facetLink->facet,
15214 value, ctxt->value);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015215 if (retFacet == 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +000015216 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015217 else if (retFacet < 0) {
15218 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
15219 "Internal error: xmlSchemaValidateFacetsInternal, "
15220 "validating 'pattern' facet '%s' of type '%s'.\n",
15221 facetLink->facet->value, tmpType->name);
15222 ret = -1;
15223 break;
15224 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +000015225 /* Save the last non-validating facet. */
15226 facet = facetLink->facet;
15227 }
15228 if (retFacet != 0)
15229 break;
15230 tmpType = tmpType->baseType;
15231 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015232 if (retFacet > 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015233 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
15234 if (fireErrors) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015235 xmlSchemaVFacetErr(ctxt, ret, node, value, 0, type, facet,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015236 NULL, NULL, NULL, NULL);
15237 }
15238 }
15239 }
15240
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000015241 return (ret);
15242}
15243
Daniel Veillard4255d502002-04-16 15:50:10 +000015244/************************************************************************
15245 * *
15246 * Simple type validation *
15247 * *
15248 ************************************************************************/
Daniel Veillard377e1a92004-04-16 16:30:05 +000015249
Daniel Veillard4255d502002-04-16 15:50:10 +000015250
15251/************************************************************************
15252 * *
15253 * DOM Validation code *
15254 * *
15255 ************************************************************************/
15256
Daniel Veillard4255d502002-04-16 15:50:10 +000015257static int xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015258 xmlNodePtr elem,
Daniel Veillard3646d642004-06-02 19:19:14 +000015259 xmlSchemaTypePtr type);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015260static int xmlSchemaValidateElementByType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015261 xmlSchemaTypePtr type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000015262 int isNil,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015263 int valSimpleContent);
Daniel Veillard4255d502002-04-16 15:50:10 +000015264
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015265static void xmlSchemaBeginElement(xmlSchemaValidCtxtPtr vctxt);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000015266static int xmlSchemaEndElement(xmlSchemaValidCtxtPtr vctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015267
15268#ifdef ELEM_INFO_ENABLED
15269/**
15270 * xmlSchemaGetFreshElemInfo:
15271 * @vctxt: the schema validation context
15272 *
15273 * Creates/reuses and initializes the element info item for
15274 * the currect tree depth.
15275 *
15276 * Returns the element info item or NULL on API or internal errors.
15277 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000015278static xmlSchemaNodeInfoPtr
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000015279xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt,
15280 int depth)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015281{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000015282 xmlSchemaNodeInfoPtr info = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015283
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000015284 if (depth > vctxt->sizeElemInfos) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015285 xmlSchemaVErr(vctxt, NULL, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000015286 "Internal error: xmlSchemaGetFreshElemInfo, "
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015287 "an inconsistent depth encountered.\n",
15288 NULL, NULL);
15289 return (NULL);
15290 }
15291 if (vctxt->elemInfos == NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000015292 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
15293 xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015294 if (vctxt->elemInfos == NULL) {
15295 xmlSchemaVErrMemory(vctxt,
15296 "allocating the element info array", NULL);
15297 return (NULL);
15298 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000015299 memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015300 vctxt->sizeElemInfos = 10;
15301 } else if (vctxt->sizeElemInfos == vctxt->depth) {
15302 int i = vctxt->sizeElemInfos;
15303
15304 vctxt->sizeElemInfos *= 2;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000015305 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015306 xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000015307 sizeof(xmlSchemaNodeInfoPtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015308 if (vctxt->elemInfos == NULL) {
15309 xmlSchemaVErrMemory(vctxt,
15310 "re-allocating the element info array", NULL);
15311 return (NULL);
15312 }
15313 /*
15314 * We need the new memory to be NULLed.
15315 * TODO: Use memset instead?
15316 */
15317 for (; i < vctxt->sizeElemInfos; i++)
15318 vctxt->elemInfos[i] = NULL;
15319 } else
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000015320 info = vctxt->elemInfos[depth];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015321
15322 if (info == NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000015323 info = (xmlSchemaNodeInfoPtr)
15324 xmlMalloc(sizeof(xmlSchemaNodeInfo));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015325 if (info == NULL) {
15326 xmlSchemaVErrMemory(vctxt,
15327 "allocating an element info", NULL);
15328 return (NULL);
15329 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000015330 vctxt->elemInfos[depth] = info;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015331 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000015332 memset(info, 0, sizeof(xmlSchemaNodeInfo));
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000015333 info->depth = depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015334
15335 return (info);
15336}
15337#endif /* ELEM_INFO_ENABLED */
15338
Daniel Veillard3646d642004-06-02 19:19:14 +000015339
15340/**
15341 * xmlSchemaFreeAttrStates:
15342 * @state: a list of attribute states
15343 *
15344 * Free the given list of attribute states
15345 *
15346 */
15347static void
15348xmlSchemaFreeAttributeStates(xmlSchemaAttrStatePtr state)
15349{
15350 xmlSchemaAttrStatePtr tmp;
15351 while (state != NULL) {
15352 tmp = state;
15353 state = state->next;
15354 xmlFree(tmp);
15355 }
15356}
15357
Daniel Veillard4255d502002-04-16 15:50:10 +000015358/**
15359 * xmlSchemaRegisterAttributes:
15360 * @ctxt: a schema validation context
15361 * @attrs: a list of attributes
15362 *
15363 * Register the list of attributes as the set to be validated on that element
15364 *
15365 * Returns -1 in case of error, 0 otherwise
15366 */
15367static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015368xmlSchemaRegisterAttributes(xmlSchemaValidCtxtPtr ctxt, xmlAttrPtr attrs)
15369{
Daniel Veillard3646d642004-06-02 19:19:14 +000015370 xmlSchemaAttrStatePtr tmp;
15371
15372 ctxt->attr = NULL;
15373 ctxt->attrTop = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000015374 while (attrs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015375 if ((attrs->ns != NULL) &&
15376 (xmlStrEqual(attrs->ns->href, xmlSchemaInstanceNs))) {
15377 attrs = attrs->next;
15378 continue;
15379 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000015380 tmp = (xmlSchemaAttrStatePtr)
15381 xmlMalloc(sizeof(xmlSchemaAttrState));
15382 if (tmp == NULL) {
15383 xmlSchemaVErrMemory(ctxt, "registering attributes", NULL);
15384 return (-1);
15385 }
Daniel Veillard3646d642004-06-02 19:19:14 +000015386 tmp->attr = attrs;
15387 tmp->state = XML_SCHEMAS_ATTR_UNKNOWN;
15388 tmp->next = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015389 tmp->decl = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000015390 if (ctxt->attr == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015391 ctxt->attr = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000015392 else
15393 ctxt->attrTop->next = tmp;
15394 ctxt->attrTop = tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015395 attrs = attrs->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000015396 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015397 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000015398}
15399
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015400#if 0 /* Currently not used */
Daniel Veillard4255d502002-04-16 15:50:10 +000015401/**
Daniel Veillard4255d502002-04-16 15:50:10 +000015402 * xmlSchemaValidateCheckNodeList
15403 * @nodelist: the list of nodes
15404 *
15405 * Check the node list is only made of text nodes and entities pointing
15406 * to text nodes
15407 *
15408 * Returns 1 if true, 0 if false and -1 in case of error
15409 */
15410static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015411xmlSchemaValidateCheckNodeList(xmlNodePtr nodelist)
15412{
Daniel Veillard4255d502002-04-16 15:50:10 +000015413 while (nodelist != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015414 if (nodelist->type == XML_ENTITY_REF_NODE) {
15415 TODO /* implement recursion in the entity content */
15416 }
15417 if ((nodelist->type != XML_TEXT_NODE) &&
15418 (nodelist->type != XML_COMMENT_NODE) &&
15419 (nodelist->type != XML_PI_NODE) &&
William M. Bracke7091952004-05-11 15:09:58 +000015420 (nodelist->type != XML_CDATA_SECTION_NODE)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015421 return (0);
15422 }
15423 nodelist = nodelist->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000015424 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015425 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +000015426}
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015427#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000015428
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015429static void
15430xmlSchemaPostSchemaAssembleFixup(xmlSchemaParserCtxtPtr ctxt)
15431{
15432 int i, nbItems;
15433 xmlSchemaTypePtr item, *items;
15434
15435
15436 /*
15437 * During the Assemble of the schema ctxt->curItems has
15438 * been filled with the relevant new items. Fix those up.
15439 */
15440 nbItems = ctxt->assemble->nbItems;
15441 items = (xmlSchemaTypePtr *) ctxt->assemble->items;
15442
15443 for (i = 0; i < nbItems; i++) {
15444 item = items[i];
15445 switch (item->type) {
15446 case XML_SCHEMA_TYPE_ATTRIBUTE:
15447 xmlSchemaAttrFixup((xmlSchemaAttributePtr) item, ctxt, NULL);
15448 break;
15449 case XML_SCHEMA_TYPE_ELEMENT:
15450 xmlSchemaRefFixupCallback((xmlSchemaElementPtr) item, ctxt,
15451 NULL, NULL, NULL);
15452 break;
15453 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
15454 xmlSchemaAttrGrpFixup((xmlSchemaAttributeGroupPtr) item,
15455 ctxt, NULL);
15456 break;
15457 case XML_SCHEMA_TYPE_GROUP:
15458 xmlSchemaGroupDefFixup(item, ctxt, NULL);
15459 default:
15460 break;
15461 }
15462 }
15463 /*
15464 * Circularity checks.
15465 */
15466 for (i = 0; i < nbItems; i++) {
15467 item = items[i];
15468 switch (item->type) {
15469 case XML_SCHEMA_TYPE_GROUP:
15470 xmlSchemaCheckGroupDefCircular(item, ctxt, NULL);
15471 break;
15472 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
15473 xmlSchemaCheckAttributeGroupCircular(
15474 (xmlSchemaAttributeGroupPtr) item, ctxt, NULL);
15475 break;
15476 default:
15477 break;
15478 }
15479 }
15480 /*
15481 * Fixup for all other item.
15482 * TODO: Hmm, not sure if starting from complex/simple types,
15483 * all subsequent items will be reached.
15484 */
15485 for (i = 0; i < nbItems; i++) {
15486 item = items[i];
15487 switch (item->type) {
15488 case XML_SCHEMA_TYPE_SIMPLE:
15489 case XML_SCHEMA_TYPE_COMPLEX:
15490 xmlSchemaTypeFixup(item, ctxt, NULL);
15491 break;
15492 default:
15493 break;
15494 }
15495 }
15496 /*
15497 * Check facet values. Note that facets are
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000015498 * hold by simple type components only (and
15499 * by complex types in the current implementation).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015500 */
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000015501 /* OLD:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015502 for (i = 0; i < nbItems; i++) {
15503 item = items[i];
15504 switch (item->type) {
15505 case XML_SCHEMA_TYPE_SIMPLE:
15506 case XML_SCHEMA_TYPE_COMPLEX:
15507 xmlSchemaCheckDefaults(item, ctxt, NULL);
15508 break;
15509 default:
15510 break;
15511 }
15512 }
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000015513 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015514 /*
15515 * Build the content model for complex types.
15516 */
15517 for (i = 0; i < nbItems; i++) {
15518 item = items[i];
15519 switch (item->type) {
15520 case XML_SCHEMA_TYPE_COMPLEX:
15521 xmlSchemaBuildContentModel(item, ctxt, NULL);
15522 break;
15523 default:
15524 break;
15525 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015526 }
15527 /*
15528 * Validate value contraint values.
15529 */
15530 for (i = 0; i < nbItems; i++) {
15531 item = items[i];
15532 switch (item->type) {
15533 case XML_SCHEMA_TYPE_ATTRIBUTE:
15534 xmlSchemaCheckAttrValConstr((xmlSchemaAttributePtr) item, ctxt, NULL);
15535 break;
15536 case XML_SCHEMA_TYPE_ELEMENT:
15537 xmlSchemaCheckElemValConstr((xmlSchemaElementPtr) item, ctxt, NULL);
15538 break;
15539 default:
15540 break;
15541 }
15542 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015543}
15544
15545/**
15546 * xmlSchemaAssembleByLocation:
15547 * @pctxt: a schema parser context
15548 * @vctxt: a schema validation context
15549 * @schema: the existing schema
15550 * @node: the node that fired the assembling
15551 * @nsName: the namespace name of the new schema
15552 * @location: the location of the schema
15553 *
15554 * Expands an existing schema by an additional schema.
15555 *
15556 * Returns 0 if the new schema is correct, a positive error code
15557 * number otherwise and -1 in case of an internal or API error.
15558 */
15559static int
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015560xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
15561 xmlSchemaPtr schema,
15562 xmlNodePtr node,
15563 const xmlChar *nsName,
15564 const xmlChar *location)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015565{
15566 const xmlChar *targetNs, *oldtns;
15567 xmlDocPtr doc, olddoc;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015568 int oldflags, ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015569 xmlNodePtr docElem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015570 xmlSchemaParserCtxtPtr pctxt;
15571
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015572 /*
15573 * This should be used:
15574 * 1. on <import>(s)
15575 * 2. if requested by the validated instance
15576 * 3. if requested via the API
15577 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015578 if ((vctxt == NULL) || (schema == NULL))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015579 return (-1);
15580 /*
15581 * Create a temporary parser context.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015582 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015583 if ((vctxt->pctxt == NULL) &&
15584 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1)) {
15585 xmlSchemaVErr(vctxt, node,
15586 XML_SCHEMAV_INTERNAL,
15587 "Internal error: xmlSchemaAssembleByLocation, "
15588 "failed to create a temp. parser context.\n",
15589 NULL, NULL);
15590 return (-1);
15591 }
15592 pctxt = vctxt->pctxt;
15593 /*
15594 * Set the counter to produce unique names for anonymous items.
15595 */
15596 pctxt->counter = schema->counter;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015597 /*
15598 * Acquire the schema document.
15599 */
15600 ret = xmlSchemaAcquireSchemaDoc(pctxt, schema, node,
15601 nsName, location, &doc, &targetNs, 0);
15602 if (ret != 0) {
15603 if (doc != NULL)
15604 xmlFreeDoc(doc);
15605 } else if (doc != NULL) {
15606 docElem = xmlDocGetRootElement(doc);
15607 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015608 * Create new assemble info.
15609 */
15610 if (pctxt->assemble == NULL) {
15611 pctxt->assemble = xmlSchemaNewAssemble();
15612 if (pctxt->assemble == NULL) {
15613 xmlSchemaVErrMemory(vctxt,
15614 "Memory error: xmlSchemaAssembleByLocation, "
15615 "allocating assemble info", NULL);
15616 xmlFreeDoc(doc);
15617 return (-1);
15618 }
15619 }
15620 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015621 * Save and reset the context & schema.
15622 */
15623 oldflags = schema->flags;
15624 oldtns = schema->targetNamespace;
15625 olddoc = schema->doc;
15626
15627 xmlSchemaClearSchemaDefaults(schema);
15628 schema->targetNamespace = targetNs;
15629 /* schema->nbCurItems = 0; */
15630 pctxt->schema = schema;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015631 pctxt->ctxtType = NULL;
15632 pctxt->parentItem = NULL;
15633
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015634 xmlSchemaParseSchemaDefaults(pctxt, schema, docElem);
15635 xmlSchemaParseSchemaTopLevel(pctxt, schema, docElem->children);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015636 xmlSchemaPostSchemaAssembleFixup(pctxt);
15637 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015638 * Set the counter of items.
15639 */
15640 schema->counter = pctxt->counter;
15641 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015642 * Free the list of assembled components.
15643 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015644 pctxt->assemble->nbItems = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015645 /*
15646 * Restore the context & schema.
15647 */
15648 schema->flags = oldflags;
15649 schema->targetNamespace = oldtns;
15650 schema->doc = olddoc;
15651 ret = pctxt->err;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015652 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015653 return (ret);
15654}
15655
15656/**
15657 * xmlSchemaAssembleByXSIAttr:
15658 * @vctxt: a schema validation context
15659 * @xsiAttr: an xsi attribute
15660 * @noNamespace: whether a schema with no target namespace is exptected
15661 *
15662 * Expands an existing schema by an additional schema using
15663 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
15664 * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
15665 * must be set to 1.
15666 *
15667 * Returns 0 if the new schema is correct, a positive error code
15668 * number otherwise and -1 in case of an internal or API error.
15669 */
15670static int
15671xmlSchemaAssembleByXSIAttr(xmlSchemaValidCtxtPtr vctxt,
15672 xmlAttrPtr xsiAttr,
15673 int noNamespace)
15674{
15675 xmlChar *value;
15676 const xmlChar *cur, *end;
15677 const xmlChar *nsname = NULL, *location;
15678 int count = 0;
15679 int ret = 0;
15680
15681 if (xsiAttr == NULL) {
15682 xmlSchemaVCustomErr(vctxt, XML_SCHEMAV_INTERNAL,
15683 NULL, NULL,
15684 "Internal error: xmlSchemaAssembleByXSIAttr, "
15685 "bad arguments", NULL);
15686 return (-1);
15687 }
15688 /*
15689 * Parse the value; we will assume an even number of values
15690 * to be given (this is how Xerces and XSV work).
15691 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015692 value = xmlNodeGetContent((xmlNodePtr) xsiAttr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015693 cur = value;
15694 do {
15695 if (noNamespace != 1) {
15696 /*
15697 * Get the namespace name.
15698 */
15699 while (IS_BLANK_CH(*cur))
15700 cur++;
15701 end = cur;
15702 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
15703 end++;
15704 if (end == cur)
15705 break;
15706 count++;
15707 nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
15708 cur = end;
15709 }
15710 /*
15711 * Get the URI.
15712 */
15713 while (IS_BLANK_CH(*cur))
15714 cur++;
15715 end = cur;
15716 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
15717 end++;
15718 if (end == cur)
15719 break;
15720 count++;
15721 location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015722 cur = end;
15723 ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015724 xsiAttr->parent, nsname, location);
15725 if (ret == -1) {
15726 xmlSchemaVCustomErr(vctxt,
15727 XML_SCHEMAV_INTERNAL,
15728 (xmlNodePtr) xsiAttr, NULL,
15729 "Internal error: xmlSchemaAssembleByXSIAttr, "
15730 "assembling schemata", NULL);
15731 if (value != NULL)
15732 xmlFree(value);
15733 return (-1);
15734 }
15735 } while (*cur != 0);
15736 if (value != NULL)
15737 xmlFree(value);
15738 return (ret);
15739}
15740
15741/**
15742 * xmlSchemaAssembleByXSIElem:
15743 * @vctxt: a schema validation context
15744 * @elem: an element node possibly holding xsi attributes
15745 * @noNamespace: whether a schema with no target namespace is exptected
15746 *
15747 * Assembles an existing schema by an additional schema using
15748 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attributes
15749 * of the given @elem.
15750 *
15751 * Returns 0 if the new schema is correct, a positive error code
15752 * number otherwise and -1 in case of an internal or API error.
15753 */
15754static int
15755xmlSchemaAssembleByXSIElem(xmlSchemaValidCtxtPtr vctxt,
15756 xmlNodePtr elem)
15757{
15758 int ret = 0, retNs = 0;
15759 xmlAttrPtr attr;
15760
15761 attr = xmlHasNsProp(elem, BAD_CAST "schemaLocation", xmlSchemaInstanceNs);
15762 if (attr != NULL) {
15763 retNs = xmlSchemaAssembleByXSIAttr(vctxt, attr, 0);
15764 if (retNs == -1)
15765 return (-1);
15766 }
15767 attr = xmlHasNsProp(elem, BAD_CAST "noNamespaceSchemaLocation", xmlSchemaInstanceNs);
15768 if (attr != NULL) {
15769 ret = xmlSchemaAssembleByXSIAttr(vctxt, attr, 1);
15770 if (ret == -1)
15771 return (-1);
15772 }
15773 if (retNs != 0)
15774 return (retNs);
15775 else
15776 return (ret);
15777}
15778
Daniel Veillard4255d502002-04-16 15:50:10 +000015779/**
Daniel Veillard4255d502002-04-16 15:50:10 +000015780 * xmlSchemaValidateCallback:
15781 * @ctxt: a schema validation context
15782 * @name: the name of the element detected (might be NULL)
15783 * @type: the type
15784 *
15785 * A transition has been made in the automata associated to an element
15786 * content model
15787 */
15788static void
15789xmlSchemaValidateCallback(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015790 const xmlChar * name ATTRIBUTE_UNUSED,
15791 xmlSchemaTypePtr type, xmlNodePtr node)
15792{
Daniel Veillard4255d502002-04-16 15:50:10 +000015793 xmlSchemaTypePtr oldtype = ctxt->type;
15794 xmlNodePtr oldnode = ctxt->node;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015795
Daniel Veillard4255d502002-04-16 15:50:10 +000015796#ifdef DEBUG_CONTENT
Daniel Veillard8651f532002-04-17 09:06:27 +000015797 xmlGenericError(xmlGenericErrorContext,
15798 "xmlSchemaValidateCallback: %s, %s, %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015799 name, type->name, node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +000015800#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015801 /*
15802 * @type->type will be XML_SCHEMA_TYPE_ANY or XML_SCHEMA_TYPE_ELEMENT.
15803 */
Daniel Veillard4255d502002-04-16 15:50:10 +000015804 ctxt->type = type;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015805 ctxt->node = node;
15806 ctxt->cur = node->children;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015807
15808#ifdef ELEM_INFO_ENABLED
15809 xmlSchemaBeginElement(ctxt);
15810#endif
15811
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015812 /*
15813 * Assemble new schemata using xsi.
15814 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015815 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015816 int ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015817
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015818 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
15819 if (ret == -1) {
15820 xmlSchemaVCustomErr(ctxt,
15821 XML_SCHEMAV_INTERNAL,
15822 ctxt->node, NULL,
15823 "Internal error: xmlSchemaValidateElement, "
15824 "assembling schema by xsi", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015825 goto leave;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015826 }
15827 /*
15828 * NOTE: We won't react on schema parser errors here.
15829 * TODO: But a warning would be nice.
15830 */
15831 }
15832 switch (type->type) {
15833 case XML_SCHEMA_TYPE_ELEMENT: {
15834 /*
15835 * NOTE: The build of the content model
15836 * (xmlSchemaBuildAContentModel) ensures that the element
15837 * declaration (and not a reference to it) will be given.
15838 */
15839 if (((xmlSchemaElementPtr) ctxt->type)->ref != NULL) {
15840 /*
15841 * This is paranoid coding ;-)... it should not
15842 * happen here any more.
15843 */
15844 xmlSchemaVCustomErr(ctxt,
15845 XML_SCHEMAV_INTERNAL,
15846 node, NULL,
15847 "Internal error: xmlSchemaValidateCallback, "
15848 "element declaration 'reference' encountered, "
15849 "but an element declaration was expected",
15850 NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015851 goto leave;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015852 }
15853 xmlSchemaValidateElementByDeclaration(ctxt,
15854 (xmlSchemaElementPtr) type);
15855 break;
15856 }
15857 case XML_SCHEMA_TYPE_ANY:
15858 xmlSchemaValidateElementByWildcard(ctxt, type);
15859 break;
15860 default:
15861 break;
15862 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015863leave:
15864
15865#ifdef ELEM_INFO_ENABLED
15866 xmlSchemaEndElement(ctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015867#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000015868 ctxt->type = oldtype;
15869 ctxt->node = oldnode;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015870}
Daniel Veillard4255d502002-04-16 15:50:10 +000015871
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000015872static int
15873xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
15874 const xmlChar *value,
15875 xmlSchemaValPtr *val,
15876 xmlNodePtr node)
15877{
15878 int ret;
15879
15880 ret = xmlValidateQName(value, 1);
15881 if (ret != 0)
15882 return (ret);
15883
15884 {
15885 xmlChar *uri = NULL;
15886 xmlChar *local = NULL;
15887 xmlChar *prefix;
15888
15889 local = xmlSplitQName2(value, &prefix);
15890 if (prefix != NULL) {
15891 xmlNsPtr ns;
15892
15893 /*
15894 * TODO: Make this streamable.
15895 */
15896 if ((node == NULL) || (node->doc == NULL)) {
15897 xmlFree(prefix);
15898 xmlFree(local);
15899 return (3);
15900 }
15901
15902 ns = xmlSearchNs(node->doc, node, prefix);
15903 if (ns == NULL) {
15904 xmlFree(prefix);
15905 xmlFree(local);
15906 return (1);
15907 }
15908 }
15909 if (prefix != NULL) {
15910 if (xmlHashLookup2(vctxt->schema->notaDecl, local, uri) == NULL)
15911 ret = 1;
15912 } else if (xmlHashLookup2(vctxt->schema->notaDecl, value,
15913 NULL) == NULL)
15914 ret = 1;
15915
15916 if ((ret == 0) && (val != NULL)) {
15917 if (prefix != NULL) {
15918 (*val) = xmlSchemaNewNOTATIONValue(BAD_CAST local,
15919 BAD_CAST xmlStrdup(uri));
15920 local = NULL;
15921 } else
15922 (*val) = xmlSchemaNewNOTATIONValue(BAD_CAST xmlStrdup(value),
15923 NULL);
15924 if (*val == NULL)
15925 ret = -1;
15926 }
15927 if (local != NULL)
15928 xmlFree(local);
15929 }
15930
15931 return (ret);
15932}
15933
Daniel Veillard01fa6152004-06-29 17:04:39 +000015934/**
15935 * xmlSchemaValidateSimpleTypeValue:
15936 * @ctxt: a schema validation context
15937 * @value: the value to be validated
15938 * @fireErrors: shall errors be reported?
15939 * @applyFacets: shall facets be applied?
Daniel Veillardc0826a72004-08-10 14:17:33 +000015940 * @normalize: shall the value be normalized?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015941 * @checkNodes: shall the content nodes be checked?
Daniel Veillard01fa6152004-06-29 17:04:39 +000015942 *
15943 * Validates a value by the given type (user derived or built-in).
15944 *
15945 * Returns 0 if the value is valid, a positive error code
15946 * number otherwise and -1 in case of an internal or API error.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015947 */
15948static int
15949xmlSchemaValidateSimpleTypeValue(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015950 xmlSchemaTypePtr type,
15951 const xmlChar *value,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015952 int fireErrors,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015953 int applyFacets,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015954 int normalize,
15955 int checkNodes)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015956{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015957 xmlNodePtr node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015958 int ret = 0;
15959 xmlChar *normValue = NULL;
15960 int wtsp;
15961
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015962 node = ctxt->node;
15963 /* Save the current whitespace normalization type. */
Daniel Veillardc0826a72004-08-10 14:17:33 +000015964 wtsp = ctxt->valueWS;
15965 /*
15966 * Normalize the value.
15967 */
15968 if (normalize &&
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000015969 (ctxt->valueWS != XML_SCHEMAS_FACET_COLLAPSE)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015970 int norm = xmlSchemaGetWhiteSpaceFacetValue(type);
15971
15972 if ((norm != -1) && (norm > ctxt->valueWS)) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000015973 if (norm == XML_SCHEMAS_FACET_COLLAPSE)
Daniel Veillardc0826a72004-08-10 14:17:33 +000015974 normValue = xmlSchemaCollapseString(value);
15975 else
15976 normValue = xmlSchemaWhiteSpaceReplace(value);
15977 ctxt->valueWS = norm;
15978 if (normValue != NULL)
15979 value = (const xmlChar *) normValue;
15980 }
15981 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015982 /*
15983 * The nodes of a content must be checked only once,
15984 * this is not working since list types will fire this
15985 * multiple times.
15986 */
15987 if ((checkNodes == 1) && (ctxt->cur != NULL)) {
15988 xmlNodePtr cur = ctxt->cur;
15989
15990 do {
15991 switch (cur->type) {
15992 case XML_TEXT_NODE:
15993 case XML_CDATA_SECTION_NODE:
15994 case XML_PI_NODE:
15995 case XML_COMMENT_NODE:
15996 case XML_XINCLUDE_START:
15997 case XML_XINCLUDE_END:
15998 break;
15999 case XML_ENTITY_REF_NODE:
16000 case XML_ENTITY_NODE:
16001 /* TODO: Scour the entities for illegal nodes. */
16002 TODO break;
16003 case XML_ELEMENT_NODE: {
16004 /* NOTE: Changed to an internal error, since the
16005 * existence of an element node will be already checked in
16006 * xmlSchemaValidateElementBySimpleType and in
16007 * xmlSchemaValidateElementByComplexType.
16008 */
16009 xmlSchemaVCustomErr(ctxt,
16010 XML_SCHEMAV_INTERNAL,
16011 /* XML_SCHEMAS_ERR_INVALIDELEM, */
16012 node, type,
16013 "Element '%s' found in simple type content",
16014 cur->name);
16015 return (XML_SCHEMAV_INTERNAL);
16016 }
16017 case XML_ATTRIBUTE_NODE:
16018 case XML_DOCUMENT_NODE:
16019 case XML_DOCUMENT_TYPE_NODE:
16020 case XML_DOCUMENT_FRAG_NODE:
16021 case XML_NOTATION_NODE:
16022 case XML_HTML_DOCUMENT_NODE:
16023 case XML_DTD_NODE:
16024 case XML_ELEMENT_DECL:
16025 case XML_ATTRIBUTE_DECL:
16026 case XML_ENTITY_DECL:
16027 case XML_NAMESPACE_DECL:
16028#ifdef LIBXML_DOCB_ENABLED
16029 case XML_DOCB_DOCUMENT_NODE:
16030#endif
16031 xmlSchemaVCustomErr(ctxt,
16032 XML_SCHEMAV_INTERNAL,
16033 /* XML_SCHEMAS_ERR_INVALIDELEM, */
16034 node, NULL,
16035 "Node of unexpected type found in simple type content",
16036 NULL);
16037 return (XML_SCHEMAV_INTERNAL);
16038 }
16039 cur = cur->next;
16040 } while (cur != NULL);
16041 }
16042
William M. Brack2f2a6632004-08-20 23:09:47 +000016043 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
16044 xmlSchemaTypePtr base, anyType;
16045
16046 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
16047
16048 base = type->baseType;
16049 while ((base != NULL) &&
16050 (base->type != XML_SCHEMA_TYPE_SIMPLE) &&
16051 (base->type != XML_SCHEMA_TYPE_BASIC) &&
16052 (base != anyType)) {
16053 base = base->baseType;
16054 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016055 ret = xmlSchemaValidateSimpleTypeValue(ctxt, base, value, 1, 0, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000016056 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016057 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000016058 "Internal error: xmlSchemaValidateSimpleTypeValue, "
16059 "validating complex type '%s'\n",
16060 type->name, NULL);
16061 } else if ((ret == 0) && (applyFacets) && (type->facetSet != NULL)) {
16062 /*
16063 * Check facets.
16064 */
16065 /*
16066 * This is somehow not nice, since if an error occurs
16067 * the reported type will be the complex type; the spec
16068 * wants a simple type to be created on the complex type
16069 * if it has a simple content. For now we have to live with
16070 * it.
16071 */
16072 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
16073 value, 0, fireErrors);
16074 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016075 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000016076 "Internal error: xmlSchemaValidateSimpleTypeValue, "
16077 "validating facets of complex type '%s'\n",
16078 type->name, NULL);
16079 } else if (ret > 0) {
16080 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
William M. Brack2f2a6632004-08-20 23:09:47 +000016081 if (fireErrors)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016082 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
William M. Brack2f2a6632004-08-20 23:09:47 +000016083 }
16084 }
16085 } else if (type->type == XML_SCHEMA_TYPE_BASIC) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016086
16087 if (ctxt->value != NULL) {
16088 xmlSchemaFreeValue(ctxt->value);
16089 ctxt->value = NULL;
16090 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016091 /*
16092 * STREAM-READ-CHILDREN.
16093 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016094 if ((type->builtInType == XML_SCHEMAS_NOTATION) &&
16095 (ctxt->schema != NULL)) {
16096 /*
16097 * NOTATIONs need to be processed here, since they need
16098 * to lookup in the hashtable of NOTATION declarations.
16099 */
16100 ret = xmlSchemaValidateNotation(ctxt, value, &(ctxt->value), node);
16101 } else
16102 ret = xmlSchemaValPredefTypeNodeNoNorm(type, value, &(ctxt->value), node);
Daniel Veillardc0826a72004-08-10 14:17:33 +000016103 if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016104 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
16105 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
16106 else
16107 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000016108 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016109 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016110 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016111 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016112 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000016113 "validating built-in type '%s'\n", type->name, NULL);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000016114 } else if ((ctxt->value == NULL) &&
16115 (type->builtInType == XML_SCHEMAS_STRING) &&
16116 (ctxt->nodeInfo != NULL) &&
16117 (ctxt->nodeInfo->flags & XML_SCHEMA_ELEM_INFO_VALUE_NEEDED)) {
16118#ifdef IDC_VALUE_SUPPORT
16119 xmlChar *valdup;
16120 /*
16121 * Create a precomputed string value for "string" as well if
16122 * requested.
16123 */
16124 valdup = xmlStrdup(value);
16125 ctxt->value = xmlSchemaNewStringValue(XML_SCHEMAS_STRING,
16126 BAD_CAST valdup);
16127 if ((valdup != NULL) && (ctxt->value == NULL))
16128 xmlFree(valdup);
16129#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +000016130 }
16131 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
16132 /* 1.2.1 if {variety} is ·atomic· then the string must ·match·
16133 * a literal in the ·lexical space· of {base type definition}
16134 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016135 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type->baseType, value, 0, 0, 0, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016136 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016137 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016138 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000016139 "validating atomic simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000016140 type->name, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000016141 } else if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016142 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000016143 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016144 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillardc0826a72004-08-10 14:17:33 +000016145 } else if ((applyFacets) && (type->facetSet != NULL)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016146 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000016147 * Check facets.
Daniel Veillard01fa6152004-06-29 17:04:39 +000016148 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000016149 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
16150 value, 0, fireErrors);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016151 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016152 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016153 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000016154 "validating facets of atomic simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000016155 type->name, NULL);
16156 } else if (ret > 0) {
16157 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000016158 /*
16159 Disabled, since the facet validation already reports errors.
16160 if (fireErrors)
16161 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
16162 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000016163 }
16164 }
16165 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
16166
16167 xmlSchemaTypePtr tmpType;
16168 const xmlChar *cur, *end;
16169 xmlChar *tmp;
Daniel Veillardc0826a72004-08-10 14:17:33 +000016170 unsigned long len = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016171
16172 /* 1.2.2 if {variety} is ·list· then the string must be a sequence
16173 * of white space separated tokens, each of which ·match·es a literal
16174 * in the ·lexical space· of {item type definition}
16175 */
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +000016176
Kasimier T. Buchcikde938cd2005-01-13 12:25:57 +000016177 if (value == NULL)
16178 value = BAD_CAST "";
Daniel Veillardc0826a72004-08-10 14:17:33 +000016179 tmpType = xmlSchemaGetListSimpleTypeItemType(type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016180 cur = value;
16181 do {
16182 while (IS_BLANK_CH(*cur))
16183 cur++;
16184 end = cur;
16185 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
16186 end++;
16187 if (end == cur)
16188 break;
16189 tmp = xmlStrndup(cur, end - cur);
16190 len++;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016191 ret = xmlSchemaValidateSimpleTypeValue(ctxt, tmpType, tmp, 0, 1, 0, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016192 xmlFree(tmp);
Daniel Veillardc0826a72004-08-10 14:17:33 +000016193 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016194 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016195 "Internal error: xmlSchemaValidateSimpleTypeValue, "
16196 "validating an item of list simple type '%s'\n",
16197 type->name, NULL);
16198 break;
16199 } else if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016200 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
Daniel Veillardc0826a72004-08-10 14:17:33 +000016201 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016202 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016203 break;
Daniel Veillardc0826a72004-08-10 14:17:33 +000016204 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000016205 cur = end;
16206 } while (*cur != 0);
16207 /*
16208 * Check facets.
16209 */
16210 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016211 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016212 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000016213 "validating list simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000016214 type->name, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000016215 } else if ((ret == 0) && (applyFacets)) {
16216 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
16217 value, len, fireErrors);
16218 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016219 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016220 "Internal error: xmlSchemaValidateSimpleTypeValue, "
16221 "validating facets of list simple type '%s'\n",
16222 type->name, NULL);
16223 } else if (ret > 0) {
16224 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016225 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000016226 Disabled, since the facet validation already reports errors.
16227 if (fireErrors)
16228 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016229 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000016230 }
16231
Daniel Veillard01fa6152004-06-29 17:04:39 +000016232 }
16233 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
16234 xmlSchemaTypeLinkPtr memberLink;
16235
16236 /*
16237 * TODO: For all datatypes ·derived· by ·union· whiteSpace does
16238 * not apply directly; however, the normalization behavior of ·union·
16239 * types is controlled by the value of whiteSpace on that one of the
16240 * ·memberTypes· against which the ·union· is successfully validated.
16241 *
16242 * This means that the value is normalized by the first validating
16243 * member type, then the facets of the union type are applied. This
16244 * needs changing of the value!
16245 */
16246
16247 /*
16248 * 1.2.3 if {variety} is ·union· then the string must ·match· a
16249 * literal in the ·lexical space· of at least one member of
16250 * {member type definitions}
16251 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000016252#ifdef DEBUG_UNION_VALIDATION
16253 printf("Union ST : '%s'\n", (const char *) type->name);
16254 printf(" fireErrors : %d\n", fireErrors);
16255 printf(" applyFacets: %d\n", applyFacets);
16256#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +000016257 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
16258 if (memberLink == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016259 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016260 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000016261 "union simple type '%s' has no member types\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000016262 type->name, NULL);
16263 ret = -1;
16264 }
16265 if (ret == 0) {
16266 while (memberLink != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016267 ret = xmlSchemaValidateSimpleTypeValue(ctxt, memberLink->type,
16268 value, 0, 1, 1, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016269 if ((ret <= 0) || (ret == 0))
16270 break;
16271 memberLink = memberLink->next;
16272 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000016273 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016274 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016275 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000016276 "validating members of union simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000016277 type->name, NULL);
16278 } else if (ret > 0) {
16279 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
Daniel Veillardc0826a72004-08-10 14:17:33 +000016280 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016281 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillardc0826a72004-08-10 14:17:33 +000016282 }
16283 }
16284 /*
16285 * Apply facets (pattern, enumeration).
16286 */
16287 if ((ret == 0) && (applyFacets) && (type->facetSet != NULL)) {
16288 int mws;
16289 /*
16290 * The normalization behavior of ·union· types is controlled by
16291 * the value of whiteSpace on that one of the ·memberTypes·
16292 * against which the ·union· is successfully validated.
16293 */
16294 if (normValue != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016295 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016296 "Internal error: xmlSchemaValidateSimpleTypeValue, "
16297 "the value was already normalized for the union simple "
16298 "type '%s'.\n", type->name, NULL);
16299 }
16300 mws = xmlSchemaGetWhiteSpaceFacetValue(memberLink->type);
16301 if (mws > ctxt->valueWS) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000016302 if (mws == XML_SCHEMAS_FACET_COLLAPSE)
Daniel Veillardc0826a72004-08-10 14:17:33 +000016303 normValue = xmlSchemaCollapseString(value);
16304 else
16305 normValue = xmlSchemaWhiteSpaceReplace(value);
16306 if (normValue != NULL)
16307 value = (const xmlChar *) normValue;
16308 }
16309
16310 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
16311 value, 0, fireErrors);
16312 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016313 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016314 "Internal error: xmlSchemaValidateSimpleTypeValue, "
16315 "validating facets of union simple type '%s'\n",
16316 type->name, NULL);
16317 } else if (ret > 0) {
16318 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
16319 /*
16320 if (fireErrors)
16321 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
16322 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000016323 }
16324 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000016325 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000016326 ctxt->valueWS = wtsp;
16327 if (normValue != NULL)
16328 xmlFree(normValue);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016329 return (ret);
16330}
16331
16332/**
16333 * xmlSchemaValidateSimpleTypeElement:
16334 * @ctxt: a schema validation context
16335 * @node: the element node to be validated.
16336 *
16337 * Validate the element against a simple type.
16338 *
16339 * Returns 0 if the element is valid, a positive error code
16340 * number otherwise and -1 in case of an internal or API error.
16341 */
16342static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016343xmlSchemaValidateElementBySimpleType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016344 xmlSchemaTypePtr type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000016345 int isNil,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016346 int valSimpleContent)
Daniel Veillard01fa6152004-06-29 17:04:39 +000016347{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016348 xmlSchemaTypePtr oldtype;
16349 xmlNodePtr node;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016350 xmlAttrPtr attr;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016351 xmlNodePtr cur;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016352 int ret = 0, retval = 0;
16353
Daniel Veillard01fa6152004-06-29 17:04:39 +000016354 if ((ctxt == NULL) || (type == NULL)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016355 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_INTERNAL, NULL, NULL,
16356 "Internal error: xmlSchemaValidateElementBySimpleType, "
16357 "bad arguments", NULL);
16358 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016359 }
16360
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016361 oldtype = ctxt->type;
16362 node = ctxt->node;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016363 /*
16364 * cvc-type: 3.1.2 The element information item must have no element
16365 * information item [children].
16366 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016367 /*
16368 * STREAM: Child nodes are processed.
16369 */
16370 cur = node->children;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016371 while (cur != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016372 /*
16373 * TODO: Entities, will they produce elements as well?
16374 */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016375 if (cur->type == XML_ELEMENT_NODE) {
16376 xmlSchemaVCustomErr(ctxt,
16377 XML_SCHEMAV_CVC_TYPE_3_1_2,
16378 node, type,
16379 "No element content allowed", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016380 ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016381 }
16382 cur = cur->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016383 }
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016384
Daniel Veillard01fa6152004-06-29 17:04:39 +000016385 /*
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016386 * cvc-type 3.1.1:
16387 *
16388 * The attributes of must be empty, excepting those whose namespace name
16389 * is identical to http://www.w3.org/2001/XMLSchema-instance and whose local
16390 * name is one of type, nil, schemaLocation or noNamespaceSchemaLocation.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016391 */
16392 /*
16393 * STREAM: Attribute nodes are processed.
16394 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000016395 attr = node->properties;
16396 while (attr != NULL) {
16397 if ((attr->ns == NULL) ||
16398 (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
16399 ((!xmlStrEqual(attr->name, BAD_CAST "type")) &&
16400 (!xmlStrEqual(attr->name, BAD_CAST "nil")) &&
16401 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation")) &&
16402 (!xmlStrEqual
16403 (attr->name, BAD_CAST "noNamespaceSchemaLocation")))) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016404 xmlSchemaVIllegalAttrErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016405 XML_SCHEMAV_CVC_TYPE_3_1_1, attr);
16406 ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016407 }
16408 attr = attr->next;
16409 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016410 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016411 * This will skip validation if the type is 'anySimpleType' and
16412 * if the value was already validated (e.g. default values).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016413 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000016414 if ((! isNil) &&
16415 (valSimpleContent == 1) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016416 ((type->type != XML_SCHEMA_TYPE_BASIC) ||
16417 (type->builtInType != XML_SCHEMAS_ANYSIMPLETYPE))) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016418 xmlChar *value;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016419
16420 value = xmlNodeGetContent(node);
16421 /*
16422 * NOTE: This call will not check the content nodes, since
16423 * this should be checked here already.
16424 */
16425 retval = xmlSchemaValidateSimpleTypeValue(ctxt, type, value,
16426 1, 1, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000016427 if (value != NULL)
16428 xmlFree(value);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016429 if (retval != 0)
16430 ret = retval;
William M. Brack2f2a6632004-08-20 23:09:47 +000016431 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016432 ctxt->type = oldtype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016433 return (ret);
16434}
Daniel Veillard4255d502002-04-16 15:50:10 +000016435
16436/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016437 * xmlSchemaValQNameAcquire:
16438 * @value: the lexical represantation of the QName value
16439 * @node: the node to search for the corresponding namespace declaration
16440 * @nsName: the resulting namespace name if found
16441 *
16442 * Checks that a value conforms to the lexical space of the type QName;
16443 * if valid, the corresponding namespace name is searched and retured
16444 * as a copy in @nsName. The local name is returned in @localName as
16445 * a copy.
16446 *
16447 * Returns 0 if valid, 1 if not valid by type, 2 if no corresponding
16448 * namespace declaration was found in scope; -1 in case of an internal or
16449 * API error.
16450 */
16451static int
16452xmlSchemaValQNameAcquire(const xmlChar *value, xmlNodePtr node,
16453 xmlChar **nsName, xmlChar **localName)
16454{
16455 int ret;
16456 xmlChar *local = NULL;
16457
16458 if ((nsName == NULL) || (localName == NULL) || (node == NULL))
16459 return (-1);
16460 *nsName = NULL;
16461 *localName = NULL;
16462 ret = xmlValidateQName(value, 1);
16463 if (ret == 0) {
16464 xmlChar *prefix;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016465 xmlNsPtr ns;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016466
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016467 /*
16468 * NOTE: xmlSplitQName2 will return a duplicated
16469 * string.
16470 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016471 local = xmlSplitQName2(value, &prefix);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016472 if (local == NULL)
16473 local = xmlStrdup(value);
16474 ns = xmlSearchNs(node->doc, node, prefix);
16475 /*
16476 * A namespace need not to be found if the prefix is NULL.
16477 */
16478 if (ns != NULL) {
16479 /*
16480 * TODO: Is it necessary to duplicate the URI here?
16481 */
16482 *nsName = xmlStrdup(ns->href);
16483 } else if (prefix != NULL) {
16484 xmlFree(prefix);
16485 if (local != NULL)
16486 xmlFree(local);
16487 return (2);
16488 }
16489 *localName = local;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016490 if (prefix != NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016491 xmlFree(prefix);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016492 } else
16493 return (1);
16494 return (ret);
16495}
16496
16497/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016498 * xmlSchemaHasElemContent:
16499 * @node: the node
16500 *
16501 * Scours the content of the given node for element
16502 * nodes.
16503 *
16504 * Returns 1 if an element node is found,
16505 * 0 otherwise.
16506 */
16507static int
16508xmlSchemaHasElemContent(xmlNodePtr node)
16509{
16510 if (node == NULL)
16511 return (0);
16512 node = node->children;
16513 while (node != NULL) {
16514 if (node->type == XML_ELEMENT_NODE)
16515 return (1);
16516 node = node->next;
16517 }
16518 return (0);
16519}
16520/**
16521 * xmlSchemaHasElemOrCharContent:
16522 * @node: the node
16523 *
16524 * Scours the content of the given node for element
16525 * and character nodes.
16526 *
16527 * Returns 1 if an element or character node is found,
16528 * 0 otherwise.
16529 */
16530static int
16531xmlSchemaHasElemOrCharContent(xmlNodePtr node)
16532{
16533 if (node == NULL)
16534 return (0);
16535 node = node->children;
16536 while (node != NULL) {
16537 switch (node->type) {
16538 case XML_ELEMENT_NODE:
16539 /*
16540 * TODO: Ask Daniel if these are all character nodes.
16541 */
16542 case XML_TEXT_NODE:
16543 case XML_CDATA_SECTION_NODE:
16544 /*
16545 * TODO: How XML_ENTITY_NODEs evaluated?
16546 */
16547 case XML_ENTITY_REF_NODE:
16548 case XML_ENTITY_NODE:
16549 return (1);
16550 break;
16551 default:
16552 break;
16553 }
16554 node = node->next;
16555 }
16556 return (0);
16557}
16558
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016559/************************************************************************
16560 * *
16561 * Identity-constraints (IDC) *
16562 * *
16563 ************************************************************************/
16564
16565#ifdef IDC_ENABLED
16566
16567/**
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016568 * xmlSchemaAugmentIDC:
16569 * @idcDef: the IDC definition
16570 *
16571 * Creates an augmented IDC definition item.
16572 *
16573 * Returns the item, or NULL on internal errors.
16574 */
16575static void
16576xmlSchemaAugmentIDC(xmlSchemaIDCPtr idcDef,
16577 xmlSchemaValidCtxtPtr vctxt)
16578{
16579 xmlSchemaIDCAugPtr aidc;
16580
16581 aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
16582 if (aidc == NULL) {
16583 xmlSchemaVErrMemory(vctxt,
16584 "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
16585 NULL);
16586 return;
16587 }
16588 aidc->bubbleDepth = -1;
16589 aidc->def = idcDef;
16590 aidc->next = NULL;
16591 if (vctxt->aidcs == NULL)
16592 vctxt->aidcs = aidc;
16593 else {
16594 aidc->next = vctxt->aidcs;
16595 vctxt->aidcs = aidc;
16596 }
16597}
16598
16599/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016600 * xmlSchemaIDCNewBinding:
16601 * @idcDef: the IDC definition of this binding
16602 *
16603 * Creates a new IDC binding.
16604 *
16605 * Returns the new binding in case of succeeded, NULL on internal errors.
16606 */
16607static xmlSchemaPSVIIDCBindingPtr
16608xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
16609{
16610 xmlSchemaPSVIIDCBindingPtr ret;
16611
16612 ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
16613 sizeof(xmlSchemaPSVIIDCBinding));
16614 if (ret == NULL) {
16615 xmlSchemaVErrMemory(NULL,
16616 "allocating a PSVI IDC binding item", NULL);
16617 return (NULL);
16618 }
16619 memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
16620 ret->definition = idcDef;
16621 return (ret);
16622}
16623
16624/**
16625 * xmlSchemaIDCStoreNodeTableItem:
16626 * @vctxt: the WXS validation context
16627 * @item: the IDC node table item
16628 *
16629 * The validation context is used to store an IDC node table items.
16630 * They are stored to avoid copying them if IDC node-tables are merged
16631 * with corresponding parent IDC node-tables (bubbling).
16632 *
16633 * Returns 0 if succeeded, -1 on internal errors.
16634 */
16635static int
16636xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
16637 xmlSchemaPSVIIDCNodePtr item)
16638{
16639 /*
16640 * Add to gobal list.
16641 */
16642 if (vctxt->idcNodes == NULL) {
16643 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
16644 xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
16645 if (vctxt->idcNodes == NULL) {
16646 xmlSchemaVErrMemory(vctxt,
16647 "allocating the IDC node table item list", NULL);
16648 return (-1);
16649 }
16650 vctxt->sizeIdcNodes = 20;
16651 } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
16652 vctxt->sizeIdcNodes *= 2;
16653 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
16654 xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
16655 sizeof(xmlSchemaPSVIIDCNodePtr));
16656 if (vctxt->idcNodes == NULL) {
16657 xmlSchemaVErrMemory(vctxt,
16658 "re-allocating the IDC node table item list", NULL);
16659 return (-1);
16660 }
16661 }
16662 vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
16663
16664 return (0);
16665}
16666
16667/**
16668 * xmlSchemaIDCStoreKey:
16669 * @vctxt: the WXS validation context
16670 * @item: the IDC key
16671 *
16672 * The validation context is used to store an IDC key.
16673 *
16674 * Returns 0 if succeeded, -1 on internal errors.
16675 */
16676static int
16677xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
16678 xmlSchemaPSVIIDCKeyPtr key)
16679{
16680 /*
16681 * Add to gobal list.
16682 */
16683 if (vctxt->idcKeys == NULL) {
16684 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
16685 xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
16686 if (vctxt->idcKeys == NULL) {
16687 xmlSchemaVErrMemory(vctxt,
16688 "allocating the IDC key storage list", NULL);
16689 return (-1);
16690 }
16691 vctxt->sizeIdcKeys = 40;
16692 } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
16693 vctxt->sizeIdcKeys *= 2;
16694 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
16695 xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
16696 sizeof(xmlSchemaPSVIIDCKeyPtr));
16697 if (vctxt->idcKeys == NULL) {
16698 xmlSchemaVErrMemory(vctxt,
16699 "re-allocating the IDC key storage list", NULL);
16700 return (-1);
16701 }
16702 }
16703 vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
16704
16705 return (0);
16706}
16707
16708/**
16709 * xmlSchemaIDCAppendNodeTableItem:
16710 * @bind: the IDC binding
16711 * @ntItem: the node-table item
16712 *
16713 * Appends the IDC node-table item to the binding.
16714 *
16715 * Returns 0 on success and -1 on internal errors.
16716 */
16717static int
16718xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
16719 xmlSchemaPSVIIDCNodePtr ntItem)
16720{
16721 if (bind->nodeTable == NULL) {
16722 bind->sizeNodes = 10;
16723 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
16724 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
16725 if (bind->nodeTable == NULL) {
16726 xmlSchemaVErrMemory(NULL,
16727 "allocating an array of IDC node-table items", NULL);
16728 return(-1);
16729 }
16730 } else if (bind->sizeNodes <= bind->nbNodes) {
16731 bind->sizeNodes *= 2;
16732 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
16733 xmlRealloc(bind->nodeTable, bind->sizeNodes *
16734 sizeof(xmlSchemaPSVIIDCNodePtr));
16735 if (bind->nodeTable == NULL) {
16736 xmlSchemaVErrMemory(NULL,
16737 "re-allocating an array of IDC node-table items", NULL);
16738 return(-1);
16739 }
16740 }
16741 bind->nodeTable[bind->nbNodes++] = ntItem;
16742 return(0);
16743}
16744
16745/**
16746 * xmlSchemaIDCAquireBinding:
16747 * @vctxt: the WXS validation context
16748 * @matcher: the IDC matcher
16749 *
16750 * Looks up an PSVI IDC binding, for the IDC definition and
16751 * of the given matcher. If none found, a new one is created
16752 * and added to the IDC table.
16753 *
16754 * Returns an IDC binding or NULL on internal errors.
16755 */
16756static xmlSchemaPSVIIDCBindingPtr
16757xmlSchemaIDCAquireBinding(xmlSchemaValidCtxtPtr vctxt,
16758 xmlSchemaIDCMatcherPtr matcher)
16759{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000016760 xmlSchemaNodeInfoPtr info;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016761
16762 info = vctxt->elemInfos[matcher->depth];
16763
16764 if (info->idcTable == NULL) {
16765 info->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
16766 if (info->idcTable == NULL)
16767 return (NULL);
16768 return(info->idcTable);
16769 } else {
16770 xmlSchemaPSVIIDCBindingPtr bind = NULL;
16771
16772 bind = info->idcTable;
16773 do {
16774 if (bind->definition == matcher->aidc->def)
16775 return(bind);
16776 if (bind->next == NULL) {
16777 bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
16778 if (bind->next == NULL)
16779 return (NULL);
16780 return(bind->next);
16781 }
16782 bind = bind->next;
16783 } while (bind != NULL);
16784 }
16785 return (NULL);
16786}
16787
16788/**
16789 * xmlSchemaIDCFreeKey:
16790 * @key: the IDC key
16791 *
16792 * Frees an IDC key together with its compiled value.
16793 */
16794static void
16795xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
16796{
16797 if (key->compValue != NULL)
16798 xmlSchemaFreeValue(key->compValue);
16799 xmlFree(key);
16800}
16801
16802/**
16803 * xmlSchemaIDCFreeBinding:
16804 *
16805 * Frees an IDC binding. Note that the node table-items
16806 * are not freed.
16807 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000016808static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016809xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
16810{
16811 if (bind->nodeTable != NULL) {
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000016812 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
16813 int i;
16814 /*
16815 * Node-table items for keyrefs are not stored globally
16816 * to the validation context, since they are not bubbled.
16817 * We need to free them here.
16818 */
16819 for (i = 0; i < bind->nbNodes; i++) {
16820 xmlFree(bind->nodeTable[i]->keys);
16821 xmlFree(bind->nodeTable[i]);
16822 }
16823 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016824 xmlFree(bind->nodeTable);
16825 }
16826 xmlFree(bind);
16827}
16828
16829/**
16830 * xmlSchemaIDCFreeIDCTable:
16831 * @bind: the first IDC binding in the list
16832 *
16833 * Frees an IDC table, i.e. all the IDC bindings in the list.
16834 */
16835static void
16836xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
16837{
16838 xmlSchemaPSVIIDCBindingPtr prev;
16839
16840 while (bind != NULL) {
16841 prev = bind;
16842 bind = bind->next;
16843 xmlSchemaIDCFreeBinding(prev);
16844 }
16845}
16846
16847/**
16848 * xmlSchemaIDCFreeMatcherList:
16849 * @matcher: the first IDC matcher in the list
16850 *
16851 * Frees a list of IDC matchers.
16852 */
16853static void
16854xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
16855{
16856 xmlSchemaIDCMatcherPtr next;
16857
16858 while (matcher != NULL) {
16859 next = matcher->next;
16860 if (matcher->keySeqs != NULL) {
16861 int i;
16862 for (i = 0; i < matcher->sizeKeySeqs; i++)
16863 if (matcher->keySeqs[i] != NULL)
16864 xmlFree(matcher->keySeqs[i]);
16865 xmlFree(matcher->keySeqs);
16866 }
16867 xmlFree(matcher);
16868 matcher = next;
16869 }
16870}
16871
16872/**
16873 * xmlSchemaAreValuesEqual:
16874 * @ta: the first type
16875 * @a: the first value
16876 * @tb: the second type
16877 * @b: the second value
16878 *
16879 * Compares two values.
16880 *
16881 * Returns 1 if they are equal, 0 if not and -1 on internal errors.
16882 */
16883static int
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000016884xmlSchemaAreValuesEqual(xmlSchemaValidCtxtPtr vctxt,
16885 xmlSchemaTypePtr ta,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016886 xmlSchemaValPtr a,
16887 xmlSchemaTypePtr tb,
16888 xmlSchemaValPtr b)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000016889{
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016890 /* Same user derived/built-in derived/built-in primitive types. */
16891 if (ta == tb)
16892 goto compareValue;
16893
16894 /*
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000016895 * Note that comparison with anySimpleTypes with be supported for
16896 * string based types as well.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016897 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000016898#if 0
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016899 if ((ta->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
16900 (tb->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
16901 return(0);
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000016902#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016903
16904 /*
16905 * 4.2.1 equal (data-types)
16906 *
16907 * the ·value space·s of all ·primitive· datatypes are disjoint
16908 * (they do not share any values)
16909 */
16910 if ((ta->builtInType != 0) && (tb->builtInType != 0) &&
16911 (ta->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE) &&
16912 (tb->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
16913 return(0);
16914
16915 if ((ta->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
16916 (ta->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) ||
16917 (tb->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
16918 (tb->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)) {
16919 TODO
16920 return(0);
16921 }
16922 /*
16923 * (1) if a datatype T' is ·derived· by ·restriction· from an atomic datatype
16924 * T then the ·value space· of T' is a subset of the ·value space· of T.
16925 */
16926 /*
16927 * (2) if datatypes T' and T'' are ·derived· by ·restriction· from a common
16928 * atomic ancestor T then the ·value space·s of T' and T'' may overlap.
16929 */
16930
16931 {
16932 xmlSchemaTypePtr pta = ta, ptb = tb;
16933
16934 /* Note that we will compare the primitives here. */
16935 while ((pta->builtInType == 0) ||
16936 ((pta->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE) == 0))
16937 pta = pta->baseType;
16938 while ((ptb->builtInType == 0) ||
16939 ((ptb->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE) == 0))
16940 ptb = ptb->baseType;
16941 if (pta == ptb)
16942 goto compareValue;
16943 return(0);
16944 }
16945compareValue:
16946 {
16947#ifdef IDC_VALUE_SUPPORT
16948 int ret;
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000016949 int aws, bws;
16950
16951 aws = xmlSchemaGetWhiteSpaceFacetValue(ta);
16952 bws = xmlSchemaGetWhiteSpaceFacetValue(tb);
16953
16954 ret = xmlSchemaCompareValuesWhtsp(
16955 a, (xmlSchemaWhitespaceValueType) aws,
16956 b, (xmlSchemaWhitespaceValueType) bws);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016957 if (ret == 0)
16958 return(1);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000016959 else if (ret == -2) {
16960 xmlSchemaVErr(vctxt, vctxt->node,
16961 XML_SCHEMAV_INTERNAL,
16962 "Internal error: xmlSchemaAreValuesEqual, "
16963 "failed to compare the values.\n",
16964 NULL, NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016965 return(-1);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000016966 } else
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016967 return(0);
16968#else
16969 return (1);
16970#endif
16971 }
16972}
16973
16974/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016975 * xmlSchemaIDCAddStateObject:
16976 * @vctxt: the WXS validation context
16977 * @matcher: the IDC matcher
16978 * @sel: the XPath information
16979 * @parent: the parent "selector" state object if any
16980 * @type: "selector" or "field"
16981 *
16982 * Creates/reuses and activates state objects for the given
16983 * XPath information; if the XPath expression consists of unions,
16984 * multiple state objects are created for every unioned expression.
16985 *
16986 * Returns 0 on success and -1 on internal errors.
16987 */
16988static int
16989xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
16990 xmlSchemaIDCMatcherPtr matcher,
16991 xmlSchemaIDCSelectPtr sel,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016992 int type)
16993{
16994 xmlSchemaIDCStateObjPtr sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016995
16996 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016997 * Reuse the state objects from the pool.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016998 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016999 if (vctxt->xpathStatePool != NULL) {
17000 sto = vctxt->xpathStatePool;
17001 vctxt->xpathStatePool = sto->next;
17002 sto->next = NULL;
17003 } else {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017004 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017005 * Create a new state object.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017006 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017007 sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
17008 if (sto == NULL) {
17009 xmlSchemaVErrMemory(NULL,
17010 "allocating an IDC state object", NULL);
17011 return (-1);
17012 }
17013 memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
17014 }
17015 /*
17016 * Add to global list.
17017 */
17018 if (vctxt->xpathStates != NULL)
17019 sto->next = vctxt->xpathStates;
17020 vctxt->xpathStates = sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017021
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017022 /*
17023 * Free the old xpath validation context.
17024 */
17025 if (sto->xpathCtxt != NULL)
17026 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
17027
17028 /*
17029 * Create a new XPath (pattern) validation context.
17030 */
17031 sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
17032 (xmlPatternPtr) sel->xpathComp);
17033 if (sto->xpathCtxt == NULL) {
17034 xmlSchemaVErr(vctxt, vctxt->node,
17035 XML_SCHEMAV_INTERNAL,
17036 "Internal error: xmlSchemaIDCAddStateObject, "
17037 "failed to create the XPath validation context.\n",
17038 NULL, NULL);
17039 return (-1);
17040 }
17041 sto->type = type;
17042 sto->depth = vctxt->depth;
17043 sto->matcher = matcher;
17044 sto->sel = sel;
17045 sto->nbHistory = 0;
17046
17047#if DEBUG_IDC
17048 xmlGenericError(xmlGenericErrorContext, "IDC: STO push '%s'\n",
17049 sto->sel->xpath);
17050#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017051 return (0);
17052}
17053
17054/**
17055 * xmlSchemaXPathEvaluate:
17056 * @vctxt: the WXS validation context
17057 * @nodeType: the nodeType of the current node
17058 *
17059 * Evaluates all active XPath state objects.
17060 *
17061 * Returns the number of IC "field" state objects which resolved to
17062 * this node, 0 if none resolved and -1 on internal errors.
17063 */
17064static int
17065xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017066 xmlElementType nodeType)
17067{
17068 xmlSchemaIDCStateObjPtr sto, head = NULL, first;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017069 int res, resolved = 0, depth = vctxt->depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017070
17071 if (vctxt->xpathStates == NULL)
17072 return (0);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017073
17074 if (nodeType == XML_ATTRIBUTE_NODE)
17075 depth++;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017076#if DEBUG_IDC
17077 {
17078 xmlChar *str = NULL;
17079 xmlGenericError(xmlGenericErrorContext,
17080 "IDC: EVAL on %s, depth %d, type %d\n",
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017081 xmlSchemaFormatNsUriLocal(&str, vctxt->nodeInfo->namespaceName,
17082 vctxt->nodeInfo->localName), depth, nodeType);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017083 FREE_AND_NULL(str)
17084 }
17085#endif
17086 /*
17087 * Process all active XPath state objects.
17088 */
17089 first = vctxt->xpathStates;
17090 sto = first;
17091 while (sto != head) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017092#if DEBUG_IDC
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017093 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017094 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] selector '%s'\n",
17095 sto->matcher->aidc->def->name, sto->sel->xpath);
17096 else
17097 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] field '%s'\n",
17098 sto->matcher->aidc->def->name, sto->sel->xpath);
17099#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017100
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017101#ifdef IDC_XPATH_SUPPORT
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017102 if (nodeType == XML_ELEMENT_NODE)
17103 res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
17104 vctxt->nodeInfo->localName, vctxt->nodeInfo->namespaceName);
17105 else
17106 res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
17107 vctxt->nodeInfo->localName, vctxt->nodeInfo->namespaceName);
17108
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017109#else
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017110 res = 0;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017111#endif
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017112 if (res == -1) {
17113 xmlSchemaVErr(vctxt, vctxt->node,
17114 XML_SCHEMAV_INTERNAL,
17115 "Internal error: xmlSchemaXPathEvaluate, "
17116 "failed to evaluate a node.\n",
17117 NULL, NULL);
17118 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017119 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017120 if (res == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017121 goto next_sto;
17122 /*
17123 * Full match.
17124 */
17125#if DEBUG_IDC
17126 xmlGenericError(xmlGenericErrorContext, "IDC: "
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017127 "MATCH\n");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017128#endif
17129 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017130 * Register a match in the state object history.
17131 */
17132 if (sto->history == NULL) {
17133 sto->history = (int *) xmlMalloc(5 * sizeof(int));
17134 if (sto->history == NULL) {
17135 xmlSchemaVErrMemory(NULL,
17136 "allocating the state object history", NULL);
17137 return(-1);
17138 }
17139 sto->sizeHistory = 10;
17140 } else if (sto->sizeHistory <= sto->nbHistory) {
17141 sto->sizeHistory *= 2;
17142 sto->history = (int *) xmlRealloc(sto->history,
17143 sto->sizeHistory * sizeof(int));
17144 if (sto->history == NULL) {
17145 xmlSchemaVErrMemory(NULL,
17146 "re-allocating the state object history", NULL);
17147 return(-1);
17148 }
17149 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017150 sto->history[sto->nbHistory++] = depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017151
17152#ifdef DEBUG_IDC
17153 xmlGenericError(xmlGenericErrorContext, "IDC: push match '%d'\n",
17154 vctxt->depth);
17155#endif
17156
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017157 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
17158 xmlSchemaIDCSelectPtr sel;
17159 /*
17160 * Activate state objects for the IDC fields of
17161 * the IDC selector.
17162 */
17163#if DEBUG_IDC
17164 xmlGenericError(xmlGenericErrorContext, "IDC: "
17165 "activating field states\n");
17166#endif
17167 sel = sto->matcher->aidc->def->fields;
17168 while (sel != NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017169 if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
17170 sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
17171 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017172 sel = sel->next;
17173 }
17174 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
17175 /*
17176 * An IDC key node was found.
17177 */
17178#if DEBUG_IDC
17179 xmlGenericError(xmlGenericErrorContext,
17180 "IDC: key found\n");
17181#endif
17182 /*
17183 * Notify that the character value of this node is
17184 * needed.
17185 */
17186 if (resolved == 0)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017187 vctxt->nodeInfo->flags |= XML_SCHEMA_ELEM_INFO_VALUE_NEEDED;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017188 resolved++;
17189 }
17190next_sto:
17191 if (sto->next == NULL) {
17192 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017193 * Evaluate field state objects created on this node as well.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017194 */
17195 head = first;
17196 sto = vctxt->xpathStates;
17197 } else
17198 sto = sto->next;
17199 }
17200 return (resolved);
17201}
17202
17203/**
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017204 * xmlSchemaXPathProcessHistory:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017205 * @vctxt: the WXS validation context
17206 * @type: the simple/complex type of the current node if any at all
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017207 * @compValue: the precompiled value
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017208 *
17209 * Processes and pops the history items of the IDC state objects.
17210 * IDC key-sequences are validated/created on IDC bindings.
17211 *
17212 * Returns 0 on success and -1 on internal errors.
17213 */
17214static int
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017215xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017216 int depth)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017217{
17218 xmlSchemaIDCStateObjPtr sto, nextsto;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017219 int res, matchDepth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017220 xmlSchemaPSVIIDCKeyPtr key = NULL;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017221 xmlSchemaTypePtr type = vctxt->nodeInfo->typeDef;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017222
17223 if (vctxt->xpathStates == NULL)
17224 return (0);
17225 sto = vctxt->xpathStates;
17226
17227#if DEBUG_IDC
17228 {
17229 xmlChar *str = NULL;
17230 xmlGenericError(xmlGenericErrorContext,
17231 "IDC: BACK on %s, depth %d\n",
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017232 xmlSchemaFormatNsUriLocal(&str, vctxt->nodeInfo->namespaceName,
17233 vctxt->nodeInfo->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017234 FREE_AND_NULL(str)
17235 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017236#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017237 /*
17238 * Evaluate the state objects.
17239 */
17240 while (sto != NULL) {
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017241#ifdef IDC_XPATH_SUPPORT
17242 xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
17243 #if DEBUG_IDC
17244 xmlGenericError(xmlGenericErrorContext, "IDC: stream pop '%s'\n",
17245 sto->sel->xpath);
17246 #endif
17247#endif
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017248 if (sto->nbHistory == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017249 goto deregister_check;
17250
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017251 matchDepth = sto->history[sto->nbHistory -1];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017252
17253 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017254 * Only matches at the current depth are of interest.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017255 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017256 if (matchDepth != depth) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017257 sto = sto->next;
17258 continue;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017259 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017260 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
17261 if (! IS_SIMPLE_TYPE(type)) {
17262 /*
17263 * Not qualified if the field resolves to a node of non
17264 * simple type.
17265 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017266 xmlSchemaStreamVCustomErr(vctxt,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017267 XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017268 vctxt->nodeInfo,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017269 (xmlSchemaTypePtr) sto->matcher->aidc->def,
17270 "The field '%s' does evaluate to a node of "
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017271 "non-simple type", sto->sel->xpath, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017272
17273 sto->nbHistory--;
17274 goto deregister_check;
17275 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017276 if ((key == NULL) && (vctxt->nodeInfo->value == NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017277 /*
17278 * Failed to provide the normalized value; maby
17279 * the value was invalid.
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017280 */
17281 xmlSchemaStreamVCustomErr(vctxt,
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000017282 XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017283 vctxt->nodeInfo,
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000017284 (xmlSchemaTypePtr) sto->matcher->aidc->def,
17285 "Warning: No precomputed value available, the value "
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017286 "was either invalid or something strange happend",
17287 NULL, NULL);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000017288 /*
17289 xmlSchemaVErr(vctxt, vctxt->nodeInfo->node,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017290 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017291 "Internal error: xmlSchemaXPathProcessHistory, "
17292 "computed value not available.\n",
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017293 NULL, NULL);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000017294 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017295 sto->nbHistory--;
17296 goto deregister_check;
17297 } else {
17298 xmlSchemaIDCMatcherPtr matcher = sto->matcher;
17299 xmlSchemaPSVIIDCKeyPtr *keySeq;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017300 int pos, idx;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017301
17302 /*
17303 * The key will be anchored on the matcher's list of
17304 * key-sequences. The position in this list is determined
17305 * by the target node's depth relative to the matcher's
17306 * depth of creation (i.e. the depth of the scope element).
17307 */
17308 pos = sto->depth - matcher->depth;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017309 idx = sto->sel->index;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017310
17311 /*
17312 * Create/grow the array of key-sequences.
17313 */
17314 if (matcher->keySeqs == NULL) {
17315 if (pos > 9)
17316 matcher->sizeKeySeqs = pos * 2;
17317 else
17318 matcher->sizeKeySeqs = 10;
17319 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
17320 xmlMalloc(matcher->sizeKeySeqs *
17321 sizeof(xmlSchemaPSVIIDCKeyPtr *));
17322 if (matcher->keySeqs == NULL) {
17323 xmlSchemaVErrMemory(NULL,
17324 "allocating an array of key-sequences",
17325 NULL);
17326 return(-1);
17327 }
17328 memset(matcher->keySeqs, 0,
17329 matcher->sizeKeySeqs *
17330 sizeof(xmlSchemaPSVIIDCKeyPtr *));
17331 } else if (pos >= matcher->sizeKeySeqs) {
17332 int i = matcher->sizeKeySeqs;
17333
17334 matcher->sizeKeySeqs *= 2;
17335 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
17336 xmlRealloc(matcher->keySeqs,
17337 matcher->sizeKeySeqs *
17338 sizeof(xmlSchemaPSVIIDCKeyPtr *));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017339 if (matcher->keySeqs == NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017340 xmlSchemaVErrMemory(NULL,
17341 "reallocating an array of key-sequences",
17342 NULL);
17343 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017344 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017345 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017346 * The array needs to be NULLed.
17347 * TODO: Use memset?
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017348 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017349 for (; i < matcher->sizeKeySeqs; i++)
17350 matcher->keySeqs[i] = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017351 }
17352
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017353 /*
17354 * Get/create the key-sequence.
17355 */
17356 keySeq = matcher->keySeqs[pos];
17357 if (keySeq == NULL) {
17358 goto create_sequence;
17359 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017360 if (keySeq[idx] != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017361 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017362 * cvc-identity-constraint:
17363 * 3 For each node in the ·target node set· all
17364 * of the {fields}, with that node as the context
17365 * node, evaluate to either an empty node-set or
17366 * a node-set with exactly one member, which must
17367 * have a simple type.
17368 *
17369 * The key was already set; report an error.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017370 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017371 xmlSchemaStreamVCustomErr(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017372 XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017373 vctxt->nodeInfo,
17374 (xmlSchemaTypePtr) matcher->aidc->def,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017375 "The field '%s' evaluates to a node-set "
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017376 "with more than one member",
17377 sto->sel->xpath, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017378 sto->nbHistory--;
17379 goto deregister_check;
17380 } else {
17381 goto create_key;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017382 }
17383 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017384
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017385create_sequence:
17386 /*
17387 * Create a key-sequence.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017388 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017389 keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
17390 matcher->aidc->def->nbFields *
17391 sizeof(xmlSchemaPSVIIDCKeyPtr));
17392 if (keySeq == NULL) {
17393 xmlSchemaVErrMemory(NULL,
17394 "allocating an IDC key-sequence", NULL);
17395 return(-1);
17396 }
17397 memset(keySeq, 0, matcher->aidc->def->nbFields *
17398 sizeof(xmlSchemaPSVIIDCKeyPtr));
17399 matcher->keySeqs[pos] = keySeq;
17400create_key:
17401 /*
17402 * Created a key once per node only.
17403 */
17404 if (key == NULL) {
17405 key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
17406 sizeof(xmlSchemaPSVIIDCKey));
17407 if (key == NULL) {
17408 xmlSchemaVErrMemory(NULL,
17409 "allocating a IDC key", NULL);
17410 xmlFree(keySeq);
17411 matcher->keySeqs[pos] = NULL;
17412 return(-1);
17413 }
17414 /*
17415 * Consume the compiled value.
17416 */
17417 key->type = type;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017418 key->compValue = vctxt->nodeInfo->value;
17419 vctxt->nodeInfo->value = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017420 /*
17421 * Store the key in a global list.
17422 */
17423 if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
17424 xmlSchemaIDCFreeKey(key);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017425 return (-1);
17426 }
17427 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017428 keySeq[idx] = key;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017429 }
17430 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017431
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017432 xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
17433 xmlSchemaPSVIIDCBindingPtr bind;
17434 xmlSchemaPSVIIDCNodePtr ntItem;
17435 xmlSchemaIDCMatcherPtr matcher;
17436 xmlSchemaIDCPtr idc;
17437 int pos, i, j, nbKeys;
17438 /*
17439 * Here we have the following scenario:
17440 * An IDC 'selector' state object resolved to a target node,
17441 * during the time this target node was in the
17442 * ancestor-or-self axis, the 'field' state object(s) looked
17443 * out for matching nodes to create a key-sequence for this
17444 * target node. Now we are back to this target node and need
17445 * to put the key-sequence, together with the target node
17446 * itself, into the node-table of the corresponding IDC
17447 * binding.
17448 */
17449 matcher = sto->matcher;
17450 idc = matcher->aidc->def;
17451 nbKeys = idc->nbFields;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017452 pos = depth - matcher->depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017453 /*
17454 * Check if the matcher has any key-sequences at all, plus
17455 * if it has a key-sequence for the current target node.
17456 */
17457 if ((matcher->keySeqs == NULL) ||
17458 (matcher->sizeKeySeqs <= pos)) {
17459 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
17460 goto selector_key_error;
17461 else
17462 goto selector_leave;
17463 }
17464
17465 keySeq = &(matcher->keySeqs[pos]);
17466 if (*keySeq == NULL) {
17467 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
17468 goto selector_key_error;
17469 else
17470 goto selector_leave;
17471 }
17472
17473 for (i = 0; i < nbKeys; i++) {
17474 if ((*keySeq)[i] == NULL) {
17475 /*
17476 * Not qualified, if not all fields did resolve.
17477 */
17478 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
17479 /*
17480 * All fields of a "key" IDC must resolve.
17481 */
17482 goto selector_key_error;
17483 }
17484 goto selector_leave;
17485 }
17486 }
17487 /*
17488 * All fields did resolve.
17489 */
17490
17491 /*
17492 * 4.1 If the {identity-constraint category} is unique(/key),
17493 * then no two members of the ·qualified node set· have
17494 * ·key-sequences· whose members are pairwise equal, as
17495 * defined by Equal in [XML Schemas: Datatypes].
17496 *
17497 * Get the IDC binding from the matcher and check for
17498 * duplicate key-sequences.
17499 */
17500 bind = xmlSchemaIDCAquireBinding(vctxt, matcher);
17501 if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
17502 (bind->nbNodes != 0)) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017503 xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017504
17505 i = 0;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017506 res = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017507 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017508 * Compare the key-sequences, key by key.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017509 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017510 do {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017511 bkeySeq = bind->nodeTable[i]->keys;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017512 for (j = 0; j < nbKeys; j++) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017513 ckey = (*keySeq)[j];
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017514 bkey = bkeySeq[j];
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017515 res = xmlSchemaAreValuesEqual(vctxt, ckey->type,
17516 ckey->compValue, bkey->type, bkey->compValue);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017517 if (res == -1) {
17518 return (-1);
17519 } else if (res == 0)
17520 break;
17521 }
17522 if (res == 1) {
17523 /*
17524 * Duplicate found.
17525 */
17526 break;
17527 }
17528 i++;
17529 } while (i < bind->nbNodes);
17530 if (i != bind->nbNodes) {
17531 /*
17532 * TODO: Try to report the key-sequence.
17533 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017534 xmlSchemaStreamVCustomErr(vctxt,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017535 XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017536 vctxt->nodeInfo,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017537 (xmlSchemaTypePtr) idc,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017538 "Duplicate key-sequence found", NULL, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017539
17540 goto selector_leave;
17541 }
17542 }
17543 /*
17544 * Add a node-table item to the IDC binding.
17545 */
17546 ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
17547 sizeof(xmlSchemaPSVIIDCNode));
17548 if (ntItem == NULL) {
17549 xmlSchemaVErrMemory(NULL,
17550 "allocating an IDC node-table item", NULL);
17551 xmlFree(*keySeq);
17552 *keySeq = NULL;
17553 return(-1);
17554 }
17555 memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
17556
17557 /*
17558 * Store the node-table item on global list.
17559 */
17560 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
17561 if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
17562 xmlFree(ntItem);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017563 xmlFree(*keySeq);
17564 *keySeq = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017565 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017566 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017567 }
17568 /*
17569 * Init the node-table item. Consume the key-sequence.
17570 */
17571 ntItem->node = vctxt->node;
17572 ntItem->keys = *keySeq;
17573 *keySeq = NULL;
17574 if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1) {
17575 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
17576 /*
17577 * Free the item, since keyref items won't be
17578 * put on a global list.
17579 */
17580 xmlFree(ntItem->keys);
17581 xmlFree(ntItem);
17582 }
17583 return (-1);
17584 }
17585
17586 goto selector_leave;
17587selector_key_error:
17588 /*
17589 * 4.2.1 (KEY) The ·target node set· and the
17590 * ·qualified node set· are equal, that is, every
17591 * member of the ·target node set· is also a member
17592 * of the ·qualified node set· and vice versa.
17593 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017594 xmlSchemaStreamVCustomErr(vctxt,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017595 XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017596 vctxt->nodeInfo,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017597 (xmlSchemaTypePtr) idc,
17598 "All 'key' fields must evaluate to a node",
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017599 NULL, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017600selector_leave:
17601 /*
17602 * Free the key-sequence if not added to the IDC table.
17603 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017604 if ((keySeq != NULL) && (*keySeq != NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017605 xmlFree(*keySeq);
17606 *keySeq = NULL;
17607 }
17608 } /* if selector */
17609
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017610 sto->nbHistory--;
17611
17612deregister_check:
17613 /*
17614 * Deregister state objects if they reach the depth of creation.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017615 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017616 if ((sto->nbHistory == 0) && (sto->depth == depth)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017617#if DEBUG_IDC
17618 xmlGenericError(xmlGenericErrorContext, "IDC: STO pop '%s'\n",
17619 sto->sel->xpath);
17620#endif
17621 if (vctxt->xpathStates != sto) {
17622 xmlSchemaVErr(vctxt, vctxt->node,
17623 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017624 "Internal error: xmlSchemaXPathProcessHistory, "
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017625 "The state object to be removed is not the first "
17626 "in the list.\n",
17627 NULL, NULL);
17628 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017629 nextsto = sto->next;
17630 /*
17631 * Unlink from the list of active XPath state objects.
17632 */
17633 vctxt->xpathStates = sto->next;
17634 sto->next = vctxt->xpathStatePool;
17635 /*
17636 * Link it to the pool of reusable state objects.
17637 */
17638 vctxt->xpathStatePool = sto;
17639 sto = nextsto;
17640 } else
17641 sto = sto->next;
17642 } /* while (sto != NULL) */
17643 return (0);
17644}
17645
17646/**
17647 * xmlSchemaIDCRegisterMatchers:
17648 * @vctxt: the WXS validation context
17649 * @elemDecl: the element declaration
17650 *
17651 * Creates helper objects to evaluate IDC selectors/fields
17652 * successively.
17653 *
17654 * Returns 0 if OK and -1 on internal errors.
17655 */
17656static int
17657xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
17658 xmlSchemaElementPtr elemDecl)
17659{
17660 xmlSchemaIDCMatcherPtr matcher, last = NULL;
17661 xmlSchemaIDCPtr idc, refIdc;
17662 xmlSchemaIDCAugPtr aidc;
17663
17664 idc = (xmlSchemaIDCPtr) elemDecl->idcs;
17665 if (idc == NULL)
17666 return (0);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017667
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017668#if DEBUG_IDC
17669 {
17670 xmlChar *str = NULL;
17671 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017672 "IDC: REGISTER on %s, depth %d\n",
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017673 (char *) xmlSchemaFormatNsUriLocal(&str, vctxt->nodeInfo->namespaceName,
17674 vctxt->nodeInfo->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017675 FREE_AND_NULL(str)
17676 }
17677#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017678 if (vctxt->nodeInfo->idcMatchers != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017679 xmlSchemaVErr(vctxt, vctxt->node,
17680 XML_SCHEMAV_INTERNAL,
17681 "Internal error: xmlSchemaIDCRegisterMatchers: "
17682 "The chain of IDC matchers is expected to be empty.\n",
17683 NULL, NULL);
17684 return (-1);
17685 }
17686 do {
17687 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
17688 /*
17689 * Since IDCs bubbles are expensive we need to know the
17690 * depth at which the bubbles should stop; this will be
17691 * the depth of the top-most keyref IDC. If no keyref
17692 * references a key/unique IDC, the bubbleDepth will
17693 * be -1, indicating that no bubbles are needed.
17694 */
17695 refIdc = (xmlSchemaIDCPtr) idc->ref->item;
17696 if (refIdc != NULL) {
17697 /*
17698 * Lookup the augmented IDC.
17699 */
17700 aidc = vctxt->aidcs;
17701 while (aidc != NULL) {
17702 if (aidc->def == refIdc)
17703 break;
17704 aidc = aidc->next;
17705 }
17706 if (aidc == NULL) {
17707 xmlSchemaVErr(vctxt, vctxt->node,
17708 XML_SCHEMAV_INTERNAL,
17709 "Internal error: xmlSchemaIDCRegisterMatchers: "
17710 "Could not find an augmented IDC item for an IDC "
17711 "definition.\n",
17712 NULL, NULL);
17713 return (-1);
17714 }
17715 if ((aidc->bubbleDepth == -1) ||
17716 (vctxt->depth < aidc->bubbleDepth))
17717 aidc->bubbleDepth = vctxt->depth;
17718 }
17719 }
17720 /*
17721 * Lookup the augmented IDC item for the IDC definition.
17722 */
17723 aidc = vctxt->aidcs;
17724 while (aidc != NULL) {
17725 if (aidc->def == idc)
17726 break;
17727 aidc = aidc->next;
17728 }
17729 if (aidc == NULL) {
17730 xmlSchemaVErr(vctxt, vctxt->node,
17731 XML_SCHEMAV_INTERNAL,
17732 "Internal error: xmlSchemaIDCRegisterMatchers: "
17733 "Could not find an augmented IDC item for an IDC definition.\n",
17734 NULL, NULL);
17735 return (-1);
17736 }
17737 /*
17738 * Create an IDC matcher for every IDC definition.
17739 */
17740 matcher = (xmlSchemaIDCMatcherPtr)
17741 xmlMalloc(sizeof(xmlSchemaIDCMatcher));
17742 if (matcher == NULL) {
17743 xmlSchemaVErrMemory(vctxt,
17744 "allocating an IDC matcher", NULL);
17745 return (-1);
17746 }
17747 memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
17748 if (last == NULL)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017749 vctxt->nodeInfo->idcMatchers = matcher;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017750 else
17751 last->next = matcher;
17752 last = matcher;
17753
17754 matcher->type = IDC_MATCHER;
17755 matcher->depth = vctxt->depth;
17756 matcher->aidc = aidc;
17757#if DEBUG_IDC
17758 xmlGenericError(xmlGenericErrorContext, "IDC: register matcher\n");
17759#endif
17760 /*
17761 * Init the automaton state object.
17762 */
17763 if (xmlSchemaIDCAddStateObject(vctxt, matcher,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017764 idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017765 return (-1);
17766
17767 idc = idc->next;
17768 } while (idc != NULL);
17769 return (0);
17770}
17771
17772/**
17773 * xmlSchemaBubbleIDCNodeTables:
17774 * @depth: the current tree depth
17775 *
17776 * Merges IDC bindings of an element at @depth into the corresponding IDC
17777 * bindings of its parent element. If a duplicate note-table entry is found,
17778 * both, the parent node-table entry and child entry are discarded from the
17779 * node-table of the parent.
17780 *
17781 * Returns 0 if OK and -1 on internal errors.
17782 */
17783static int
17784xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
17785{
17786 xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017787 xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL, lastParBind = NULL; /* parent IDC bindings. */
17788 xmlSchemaPSVIIDCNodePtr node, parNode = NULL; /* node-table entries. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017789 xmlSchemaPSVIIDCKeyPtr key, parKey; /* keys of in a key-sequence. */
17790 xmlSchemaIDCAugPtr aidc;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017791 int i, j, k, ret = 0, oldNum, newDupls = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017792 int duplTop;
17793
17794 /*
17795 * The node table has the following sections:
17796 *
17797 * O --> old node-table entries (first)
17798 * O
17799 * + --> new node-table entries
17800 * +
17801 * % --> new duplicate node-table entries
17802 * %
17803 * # --> old duplicate node-table entries
17804 * # (last)
17805 *
17806 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017807 bind = vctxt->nodeInfo->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017808 if (bind == NULL) {
17809 /* Fine, no table, no bubbles. */
17810 return (0);
17811 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017812
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017813 parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
17814 /*
17815 * Walk all bindings; create new or add to existing bindings.
17816 * Remove duplicate key-sequences.
17817 */
17818start_binding:
17819 while (bind != NULL) {
17820 /*
17821 * Skip keyref IDCs.
17822 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017823 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
17824 bind = bind->next;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017825 continue;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017826 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017827 /*
17828 * Check if the key/unique IDC table needs to be bubbled.
17829 */
17830 aidc = vctxt->aidcs;
17831 do {
17832 if (aidc->def == bind->definition) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017833 if (aidc->bubbleDepth >= vctxt->depth) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017834 bind = bind->next;
17835 goto start_binding;
17836 }
17837 break;
17838 }
17839 aidc = aidc->next;
17840 } while (aidc != NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017841
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017842 if (parTable != NULL)
17843 parBind = *parTable;
17844 while (parBind != NULL) {
17845 /*
17846 * Search a matching parent binding for the
17847 * IDC definition.
17848 */
17849 if (parBind->definition == bind->definition) {
17850
17851 /*
17852 * Compare every node-table entry of the child node,
17853 * i.e. the key-sequence within, ...
17854 */
17855 oldNum = parBind->nbNodes; /* Skip newly added items. */
17856 duplTop = oldNum + parBind->nbDupls;
17857
17858 for (i = 0; i < bind->nbNodes; i++) {
17859 node = bind->nodeTable[i];
17860 if (node == NULL)
17861 continue;
17862 /*
17863 * ...with every key-sequence of the parent node, already
17864 * evaluated to be a duplicate key-sequence.
17865 */
17866 if (parBind->nbDupls != 0) {
17867 j = bind->nbNodes + newDupls;
17868 while (j < duplTop) {
17869 parNode = parBind->nodeTable[j];
17870 for (k = 0; k < bind->definition->nbFields; k++) {
17871 key = node->keys[k];
17872 parKey = parNode->keys[k];
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017873 ret = xmlSchemaAreValuesEqual(vctxt, key->type,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017874 key->compValue,
17875 parKey->type, parKey->compValue);
17876 if (ret == -1) {
17877 /* TODO: Internal error */
17878 return(-1);
17879 } else if (ret == 0)
17880 break;
17881
17882 }
17883 if (ret == 1)
17884 /* Duplicate found. */
17885 break;
17886 j++;
17887 }
17888 if (j != duplTop) {
17889 /* Duplicate found. */
17890 continue;
17891 }
17892 }
17893 /*
17894 * ... and with every key-sequence of the parent node.
17895 */
17896 j = 0;
17897 while (j < oldNum) {
17898 parNode = parBind->nodeTable[j];
17899 /*
17900 * Compare key by key.
17901 */
17902 for (k = 0; k < parBind->definition->nbFields; k++) {
17903 key = node->keys[k];
17904 parKey = parNode->keys[k];
17905
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017906 ret = xmlSchemaAreValuesEqual(vctxt, key->type,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017907 key->compValue,
17908 parKey->type, parKey->compValue);
17909 if (ret == -1) {
17910 /* TODO: Internal error */
17911 } else if (ret == 0)
17912 break;
17913
17914 }
17915 if (ret == 1)
17916 /*
17917 * The key-sequences are equal.
17918 */
17919 break;
17920 j++;
17921 }
17922 if (j != oldNum) {
17923 /*
17924 * Handle duplicates.
17925 */
17926 newDupls++;
17927 oldNum--;
17928 parBind->nbNodes--;
17929 /*
17930 * Move last old item to pos of duplicate.
17931 */
17932 parBind->nodeTable[j] =
17933 parBind->nodeTable[oldNum];
17934
17935 if (parBind->nbNodes != oldNum) {
17936 /*
17937 * If new items exist, move last new item to
17938 * last of old items.
17939 */
17940 parBind->nodeTable[oldNum] =
17941 parBind->nodeTable[parBind->nbNodes];
17942 }
17943 /*
17944 * Move duplicate to last pos of new/old items.
17945 */
17946 parBind->nodeTable[parBind->nbNodes] = parNode;
17947
17948 } else {
17949 /*
17950 * Add the node-table entry (node and key-sequence) of
17951 * the child node to the node table of the parent node.
17952 */
17953 if (parBind->nodeTable == NULL) {
17954 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
17955 xmlMalloc(1 * sizeof(xmlSchemaPSVIIDCNodePtr));
17956 if (parBind->nodeTable == NULL) {
17957 xmlSchemaVErrMemory(NULL,
17958 "allocating IDC list of node-table items", NULL);
17959 return(-1);
17960 }
17961 parBind->sizeNodes = 1;
17962 } else if (duplTop >= parBind->sizeNodes) {
17963 parBind->sizeNodes++;
17964 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
17965 xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
17966 sizeof(xmlSchemaPSVIIDCNodePtr));
17967 if (parBind->nodeTable == NULL) {
17968 xmlSchemaVErrMemory(NULL,
17969 "re-allocating IDC list of node-table items", NULL);
17970 return(-1);
17971 }
17972 }
17973
17974 /*
17975 * Move first old duplicate to last position
17976 * of old duplicates +1.
17977 */
17978 if (parBind->nbDupls != 0) {
17979 parBind->nodeTable[duplTop] =
17980 parBind->nodeTable[parBind->nbNodes + newDupls];
17981 }
17982 /*
17983 * Move first new duplicate to last position of
17984 * new duplicates +1.
17985 */
17986 if (newDupls != 0) {
17987 parBind->nodeTable[parBind->nbNodes + newDupls] =
17988 parBind->nodeTable[parBind->nbNodes];
17989 }
17990 /*
17991 * Append the new node-table entry to the 'new node-table
17992 * entries' section.
17993 */
17994 parBind->nodeTable[parBind->nbNodes] = node;
17995 parBind->nbNodes++;
17996 duplTop++;
17997 }
17998 }
17999 parBind->nbDupls += newDupls;
18000 break;
18001 }
18002 if (parBind->next == NULL)
18003 lastParBind = parBind;
18004 parBind = parBind->next;
18005 }
18006 if (parBind == NULL) {
18007 /*
18008 * No binding for the IDC was found: create a new one and
18009 * copy all node-tables.
18010 */
18011 parBind = xmlSchemaIDCNewBinding(bind->definition);
18012 if (parBind == NULL)
18013 return(-1);
18014
18015 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
18016 xmlMalloc(bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
18017 if (parBind->nodeTable == NULL) {
18018 xmlSchemaVErrMemory(NULL,
18019 "allocating an array of IDC node-table items", NULL);
18020 xmlSchemaIDCFreeBinding(parBind);
18021 return(-1);
18022 }
18023 parBind->sizeNodes = bind->nbNodes;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018024 parBind->nbNodes = bind->nbNodes;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018025 memcpy(parBind->nodeTable, bind->nodeTable,
18026 bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018027 if (*parTable == NULL)
18028 *parTable = parBind;
18029 else
18030 lastParBind->next = parBind;
18031 }
18032 bind = bind->next;
18033 }
18034 return (0);
18035}
18036
18037/**
18038 * xmlSchemaCheckCVCIDCKeyRef:
18039 * @vctxt: the WXS validation context
18040 * @elemDecl: the element declaration
18041 *
18042 * Check the cvc-idc-keyref constraints.
18043 */
18044static int
18045xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
18046{
18047 xmlSchemaPSVIIDCBindingPtr refbind, bind;
18048
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018049 refbind = vctxt->nodeInfo->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018050 /*
18051 * Find a keyref.
18052 */
18053 while (refbind != NULL) {
18054 if (refbind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
18055 int i, j, k, res;
18056 xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
18057 xmlSchemaPSVIIDCKeyPtr refKey, key;
18058
18059 /*
18060 * Find the referred key/unique.
18061 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018062 bind = vctxt->nodeInfo->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018063 do {
18064 if ((xmlSchemaIDCPtr) refbind->definition->ref->item ==
18065 bind->definition)
18066 break;
18067 bind = bind->next;
18068 } while (bind != NULL);
18069
18070 /*
18071 * Search for a matching key-sequences.
18072 */
18073 for (i = 0; i < refbind->nbNodes; i++) {
18074 res = 0;
18075 if (bind != NULL) {
18076 refKeys = refbind->nodeTable[i]->keys;
18077 for (j = 0; j < bind->nbNodes; j++) {
18078 keys = bind->nodeTable[j]->keys;
18079 for (k = 0; k < bind->definition->nbFields; k++) {
18080 refKey = refKeys[k];
18081 key = keys[k];
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018082 res = xmlSchemaAreValuesEqual(vctxt,
18083 key->type, key->compValue,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018084 refKey->type, refKey->compValue);
18085 if (res == 0)
18086 break;
18087 else if (res == -1) {
18088 return (-1);
18089 }
18090 }
18091 if (res == 1) {
18092 /*
18093 * Match found.
18094 */
18095 break;
18096 }
18097 }
18098 }
18099 if (res == 0) {
18100 /* TODO: Report the key-sequence. */
18101 xmlSchemaVCustomErr(vctxt,
18102 XML_SCHEMAV_CVC_IDC,
18103 refbind->nodeTable[i]->node,
18104 (xmlSchemaTypePtr) refbind->definition,
18105 "No matching key-sequence found", NULL);
18106 }
18107 }
18108 }
18109 refbind = refbind->next;
18110 }
18111 return (0);
18112}
18113#endif /* IDC_ENABLED */
18114
18115#ifdef ELEM_INFO_ENABLED
18116/**
18117 * xmlSchemaBeginElement:
18118 * @vctxt: the WXS validation context
18119 *
18120 * Just a temporary workaround to simulate streaming validation
18121 * a bit.
18122 */
18123static void
18124xmlSchemaBeginElement(xmlSchemaValidCtxtPtr vctxt)
18125{
18126 vctxt->depth++;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018127 vctxt->nodeInfo = xmlSchemaGetFreshElemInfo(vctxt, vctxt->depth);
18128 vctxt->nodeInfo->node = vctxt->node;
18129 vctxt->nodeInfo->localName = vctxt->node->name;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018130 if (vctxt->node->ns != NULL)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018131 vctxt->nodeInfo->namespaceName = vctxt->node->ns->href;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018132 else
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018133 vctxt->nodeInfo->namespaceName = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018134}
18135
18136/**
18137 * xmlSchemaEndElement:
18138 * @vctxt: the WXS validation context
18139 *
18140 * Just a temporary workaround to simulate streaming validation
18141 * a bit.
18142 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018143static int
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018144xmlSchemaEndElement(xmlSchemaValidCtxtPtr vctxt)
18145{
18146 if (vctxt->depth < 0) {
18147 /* TODO: raise error? */
18148 vctxt->depth--;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018149 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018150 }
18151#ifdef IDC_ENABLED
18152 /*
18153 * Evaluate the history of changes of active state objects.
18154 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018155 if (xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1)
18156 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018157
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018158 if (vctxt->nodeInfo->value != NULL) {
18159 xmlSchemaFreeValue(vctxt->nodeInfo->value);
18160 vctxt->nodeInfo->value = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018161 }
18162 /*
18163 * TODO: 6 The element information item must be ·valid· with respect to each of
18164 * the {identity-constraint definitions} as per Identity-constraint
18165 * Satisfied (§3.11.4).
18166 */
18167 /*
18168 * Validate IDC keyrefs.
18169 */
18170 xmlSchemaCheckCVCIDCKeyRef(vctxt);
18171#endif
18172
18173 /*
18174 * Merge/free the IDC table.
18175 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018176 if (vctxt->nodeInfo->idcTable != NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018177#ifdef IDC_ENABLED
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018178#ifdef DEBUG_IDC
18179 xmlSchemaDebugDumpIDCTable(stdout,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018180 vctxt->nodeInfo->namespaceName,
18181 vctxt->nodeInfo->localName,
18182 vctxt->nodeInfo->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018183#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018184 if (vctxt->depth > 0) {
18185 /*
18186 * Merge the IDC node table with the table of the parent node.
18187 */
18188 xmlSchemaBubbleIDCNodeTables(vctxt);
18189 }
18190 /*
18191 * TODO: Don't free the PSVI IDC tables if they are
18192 * requested for the PSVI.
18193 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018194 xmlSchemaIDCFreeIDCTable(vctxt->nodeInfo->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018195#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018196 vctxt->nodeInfo->idcTable = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018197 }
18198
18199 /*
18200 * Cleanup IDC matchers.
18201 */
18202#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018203 if (vctxt->nodeInfo->idcMatchers != NULL) {
18204 xmlSchemaIDCFreeMatcherList(vctxt->nodeInfo->idcMatchers);
18205 vctxt->nodeInfo->idcMatchers = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018206 }
18207#endif
18208
18209 /*
18210 * Skip further processing if we are on the validation root.
18211 */
18212 if (vctxt->depth == 0) {
18213 vctxt->depth--;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018214 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018215 }
18216
18217 /*
18218 * Reset the bubbleDepth if needed.
18219 */
18220#ifdef IDC_ENABLED
18221 if (vctxt->aidcs != NULL) {
18222 xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
18223 do {
18224 if (aidc->bubbleDepth == vctxt->depth) {
18225 /*
18226 * A bubbleDepth of a key/unique IDC matches the current
18227 * depth, this means that we are leaving the scope of the
18228 * top-most keyref IDC.
18229 */
18230 aidc->bubbleDepth = -1;
18231 }
18232 aidc = aidc->next;
18233 } while (aidc != NULL);
18234 }
18235#endif
18236 vctxt->depth--;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018237 /*
18238 * Clear the current elemInfo.
18239 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018240 if (vctxt->nodeInfo->value != NULL) {
18241 xmlSchemaFreeValue(vctxt->nodeInfo->value);
18242 vctxt->nodeInfo->value = NULL;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018243 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018244 vctxt->nodeInfo = vctxt->elemInfos[vctxt->depth];
18245 vctxt->node = vctxt->nodeInfo->node;
18246
18247 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018248}
18249
18250#endif /* ELEM_INFO_ENABLED */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018251
18252/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018253 * xmlSchemaValidateElementByDeclaration:
Daniel Veillard4255d502002-04-16 15:50:10 +000018254 * @ctxt: a schema validation context
18255 * @node: the top node.
18256 *
18257 * Validate the content of an element type.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018258 * Validation Rule: Element Locally Valid (Element)
Daniel Veillard4255d502002-04-16 15:50:10 +000018259 *
18260 * Returns 0 if the element is schemas valid, a positive error code
18261 * number otherwise and -1 in case of internal or API error.
18262 */
18263static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018264xmlSchemaValidateElementByDeclaration(xmlSchemaValidCtxtPtr ctxt,
18265 xmlSchemaElementPtr elemDecl)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018266{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018267 xmlNodePtr elem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018268 int ret = 0;
18269 xmlSchemaTypePtr actualType = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018270 xmlAttrPtr attr;
18271 xmlChar *attrValue;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018272 int nilled = 0, elemHasContent = -1;
Daniel Veillard3646d642004-06-02 19:19:14 +000018273
18274 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018275 * This one is called by xmlSchemaValidateElementByWildcardInternal,
18276 * xmlSchemaValidateElementByAnyType and xmlSchemaValidateElement.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018277 * Note that @elemDecl will be the declaration and never the
18278 * reference to a declaration.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018279 */
Daniel Veillard3646d642004-06-02 19:19:14 +000018280
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018281 if (ctxt == NULL) {
18282 xmlSchemaVErr(ctxt, NULL, XML_SCHEMAV_INTERNAL,
18283 "Internal error: xmlSchemaValidateElementByDeclaration, "
18284 "bad arguments.\n",
18285 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018286 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000018287 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018288
18289 elem = ctxt->node;
18290
18291 /*
18292 * cvc-elt (3.3.4) : 1
18293 */
18294 if (elemDecl == NULL) {
18295 xmlSchemaVCustomErr(ctxt,
18296 XML_SCHEMAV_CVC_ELT_1,
18297 elem, NULL,
18298 "No matching declaration available", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018299 /*
18300 * Evaluate IDCs even if an error occured.
18301 */
18302#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018303 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018304 return (-1);
18305#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018306 return (ctxt->err);
18307 }
18308 /*
18309 * cvc-elt (3.3.4) : 2
18310 */
18311 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
18312 xmlSchemaVCustomErr(ctxt,
18313 XML_SCHEMAV_CVC_ELT_2,
18314 elem, NULL,
18315 "The element declaration is abstract", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018316 /*
18317 * Evaluate IDCs even if an error occured.
18318 */
18319#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018320 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018321 return (-1);
18322#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018323 return (ctxt->err);
18324 }
18325
18326 /*
18327 * cvc-elt (3.3.4) : 3
18328 * Handle 'xsi:nil'.
18329 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018330
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018331 attr = xmlHasNsProp(elem, BAD_CAST "nil", xmlSchemaInstanceNs);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018332 if (attr != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018333 attrValue = xmlNodeGetContent((xmlNodePtr) attr);
18334 ctxt->node = (xmlNodePtr) attr;
18335 ctxt->cur = attr->children;
18336 ret = xmlSchemaValidateSimpleTypeValue(ctxt,
18337 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
18338 BAD_CAST attrValue, 1, 1, 1, 1);
18339 ctxt->node = elem;
18340 ctxt->type = (xmlSchemaTypePtr) elemDecl;
18341 if (ret < 0) {
18342 xmlSchemaVCustomErr(ctxt,
18343 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018344 (xmlNodePtr) attr, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018345 "Internal error: xmlSchemaValidateElementByDeclaration, "
18346 "validating the attribute 'xsi:nil'", NULL);
18347 if (attrValue != NULL)
18348 xmlFree(attrValue);
18349 return (-1);
18350 }
18351 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018352 /*
18353 * cvc-elt (3.3.4) : 3.1
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018354 */
18355 xmlSchemaVCustomErr(ctxt,
18356 XML_SCHEMAV_CVC_ELT_3_1,
18357 elem, NULL,
18358 "The element is not 'nillable'", NULL);
18359 } else {
18360 if (xmlStrEqual(BAD_CAST attrValue, BAD_CAST "true") ||
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018361 xmlStrEqual(BAD_CAST attrValue, BAD_CAST "1")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018362 ret = 0;
18363 /*
18364 * cvc-elt (3.3.4) : 3.2.1
18365 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018366 elemHasContent = xmlSchemaHasElemOrCharContent(elem);
18367 if (elemHasContent == 1) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018368 xmlSchemaVCustomErr(ctxt,
18369 XML_SCHEMAV_CVC_ELT_3_2_1,
18370 /* XML_SCHEMAS_ERR_NOTEMPTY, */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018371 elem, (xmlSchemaTypePtr) elemDecl,
18372 "The 'nilled' element must have no character or "
18373 "element content", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018374 ret = XML_SCHEMAV_CVC_ELT_3_2_1;
18375 }
18376 /*
18377 * cvc-elt (3.3.4) : 3.2.2
18378 */
18379 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
18380 (elemDecl->value != NULL)) {
18381 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_CVC_ELT_3_2_2,
18382 /* XML_SCHEMAS_ERR_HAVEDEFAULT, */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018383 elem, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018384 "There is a fixed value constraint defined for "
18385 "the 'nilled' element", NULL);
18386 ret = XML_SCHEMAV_CVC_ELT_3_2_2;
18387 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018388 if (ret == 0)
18389 nilled = 1;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018390 }
18391 }
18392 if (attrValue != NULL)
18393 xmlFree(attrValue);
18394 }
18395
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018396
18397 actualType = elemDecl->subtypes;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018398 /*
18399 * cvc-elt (3.3.4) : 4
18400 * Handle 'xsi:type'.
18401 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018402
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018403 attr = xmlHasNsProp(elem, BAD_CAST "type", xmlSchemaInstanceNs);
18404 if (attr != NULL) {
18405 xmlChar *nsName = NULL, *local = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018406
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018407 /*
18408 * TODO: We should report a *warning* that the type was overriden
18409 * by the instance.
18410 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018411
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018412 /*
18413 * cvc-elt (3.3.4) : 4.1
18414 */
18415 attrValue = xmlNodeGetContent((xmlNodePtr) attr);
18416 ret = xmlSchemaValQNameAcquire(attrValue, attr->parent,
18417 &nsName, &local);
18418 if (ret < 0) {
18419 xmlSchemaVCustomErr(ctxt,
18420 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018421 (xmlNodePtr) attr, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018422 "Internal error: xmlSchemaValidateElementByDeclaration, "
18423 "validating the attribute 'xsi:type'", NULL);;
18424 FREE_AND_NULL(attrValue)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018425 FREE_AND_NULL(nsName)
18426 FREE_AND_NULL(local)
18427 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018428 } else if (ret == 1) {
18429 xmlSchemaVSimpleTypeErr(ctxt,
18430 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
18431 (xmlNodePtr) attr, attrValue,
18432 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME));
18433 } else if (ret == 2) {
18434 xmlSchemaVCustomErr(ctxt,
18435 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
18436 (xmlNodePtr) attr,
18437 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
18438 "The QName value '%s' has no "
18439 "corresponding namespace declaration in scope",
18440 attrValue);
18441 } else {
18442 /*
18443 * cvc-elt (3.3.4) : 4.2
18444 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018445 actualType = xmlSchemaGetType(ctxt->schema, local, nsName);
18446 if (actualType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018447 xmlChar *strA = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018448
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018449 xmlSchemaVCustomErr(ctxt,
18450 XML_SCHEMAV_CVC_ELT_4_2,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018451 (xmlNodePtr) attr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018452 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
18453 "The value %s does not resolve to a type "
18454 "definition",
18455 xmlSchemaFormatNsUriLocal(&strA, nsName, local));
18456 FREE_AND_NULL(strA);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018457 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018458 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018459 * URGENT TODO: cvc-elt (3.3.4) : 4.3 (Type Derivation OK)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018460 */
18461 }
18462 }
18463 FREE_AND_NULL(attrValue)
18464 FREE_AND_NULL(nsName)
18465 FREE_AND_NULL(local)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018466 }
18467 /* TODO: Change the handling of missing types according to
18468 * the spec.
18469 */
18470 if (actualType == NULL) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018471 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018472 XML_SCHEMAV_CVC_TYPE_1,
18473 elem, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018474 "The type definition is absent", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018475 /*
18476 * Evaluate IDCs even if an error occured.
18477 */
18478#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018479 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018480 return (-1);
18481#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018482 return (XML_SCHEMAV_CVC_TYPE_1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018483 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018484
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018485 /*
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018486 * Remember the actual-type definition.
18487 */
18488#ifdef ELEM_INFO_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018489 ctxt->nodeInfo->typeDef = actualType;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018490#endif
18491
18492 /*
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018493 * TODO: Since this should be already checked by the content model automaton,
18494 * and we want to get rid of the XML_SCHEMAS_ERR... types, the error code
18495 * has been changed to XML_SCHEMAV_INTERNAL.
18496 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018497 /*
Daniel Veillard4255d502002-04-16 15:50:10 +000018498 if (child == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000018499 if (decl->minOccurs > 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018500 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018501 XML_SCHEMAS_ERR_MISSING,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018502 "Element %s: missing child %s\n",
18503 node->name, decl->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018504 }
18505 return (ctxt->err);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018506 }
18507 */
Daniel Veillard4255d502002-04-16 15:50:10 +000018508 /*
18509 * Verify the element matches
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018510 * TODO, FIXME: Can this still happen here? Isn't this already checked
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018511 * by the content model automaton?
Daniel Veillardc0826a72004-08-10 14:17:33 +000018512 if (!xmlStrEqual(child->name, decl->name)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018513 xmlSchemaVErr3(ctxt, node, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018514 XML_SCHEMAS_ERR_WRONGELEM,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018515 "Element %s: missing child %s found %s\n",
18516 node->name, decl->name, child->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018517 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000018518 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018519 */
18520 if (elemHasContent == -1)
18521 elemHasContent = xmlSchemaHasElemOrCharContent(elem);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018522
18523 /*
18524 * IDC: Register identity-constraint XPath matchers.
18525 */
18526#ifdef IDC_ENABLED
18527 if (elemDecl->idcs != NULL)
18528 xmlSchemaIDCRegisterMatchers(ctxt, elemDecl);
18529 /*
18530 * Evaluate IDCs.
18531 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018532 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018533 return (-1);
18534#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018535 /*
18536 * cvc-elt (3.3.4) : 5
18537 * The appropriate case among the following must be true:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018538 */
Daniel Veillard4255d502002-04-16 15:50:10 +000018539 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018540 * cvc-elt (3.3.4) : 5.1
18541 * If the declaration has a {value constraint},
18542 * the item has neither element nor character [children] and
18543 * clause 3.2 has not applied, then all of the following must be true:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018544 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018545 if ((elemHasContent == 0) && (nilled == 0) && (elemDecl->value != NULL)) {
18546 /*
18547 * cvc-elt (3.3.4) : 5.1.1
18548 * If the ·actual type definition· is a ·local type definition·
18549 * then the canonical lexical representation of the {value constraint}
18550 * value must be a valid default for the ·actual type definition· as
18551 * defined in Element Default Valid (Immediate) (§3.3.6).
18552 */
18553 /*
18554 * NOTE: 'local' above means types aquired by xsi:type.
18555 */
18556 ret = 0;
18557 if (actualType != elemDecl->subtypes) {
18558 xmlSchemaCreatePCtxtOnVCtxt(ctxt);
18559 ret = xmlSchemaCheckCOSValidDefault(ctxt->pctxt, ctxt, actualType,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018560 elemDecl->value, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018561 if (ret < 0) {
18562 xmlSchemaVCustomErr(ctxt,
18563 XML_SCHEMAV_INTERNAL,
18564 elem, actualType,
18565 "Internal error: xmlSchemaValidateElementByDeclaration, "
18566 "validating a default value", NULL);
18567 return (-1);
18568 }
18569 }
18570 /*
18571 * cvc-elt (3.3.4) : 5.1.2
18572 * The element information item with the canonical lexical
18573 * representation of the {value constraint} value used as its
18574 * ·normalized value· must be ·valid· with respect to the
18575 * ·actual type definition· as defined by Element Locally Valid (Type)
18576 * (§3.3.4).
18577 */
18578 /*
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018579 * Disable validation of the simple content, if it was already
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018580 * done above.
18581 */
18582 if (ret == 0) {
18583 if (actualType != elemDecl->subtypes)
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018584 ret = xmlSchemaValidateElementByType(ctxt, actualType, 0, 0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018585 else
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018586 ret = xmlSchemaValidateElementByType(ctxt, actualType, 0, 1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018587 ctxt->node = elem;
18588 if (ret < 0) {
18589 xmlSchemaVCustomErr(ctxt,
18590 XML_SCHEMAV_INTERNAL,
18591 elem, actualType,
18592 "Internal error: xmlSchemaValidateElementByDeclaration, "
18593 "validating against the type", NULL);
18594 return (-1);
18595 }
18596 /*
18597 * PSVI: Create a text node on the instance element.
18598 */
18599 if (ctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
18600 xmlNodePtr textChild;
18601
18602 textChild = xmlNewText(elemDecl->value);
18603 if (textChild == NULL) {
18604 xmlSchemaVCustomErr(ctxt,
18605 XML_SCHEMAV_INTERNAL,
18606 elem, actualType,
18607 "Internal error: xmlSchemaValidateElementByDeclaration, "
18608 "could not create a default text node for the instance",
18609 NULL);
18610 } else
18611 xmlAddChild(elem, textChild);
18612 }
18613 }
18614
18615 } else {
18616 /*
18617 * 5.2.1 The element information item must be ·valid· with respect
18618 * to the ·actual type definition· as defined by Element Locally
18619 * Valid (Type) (§3.3.4).
18620 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018621 ret = xmlSchemaValidateElementByType(ctxt, actualType, nilled, 1);
18622 /*
18623 * Consume the computed value for IDCs, ect. Note that default
18624 * values are not supported yet.
18625 */
18626#ifdef ELEM_INFO_ENABLED
18627 if (ctxt->value != NULL) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018628 ctxt->nodeInfo->value = ctxt->value;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018629 ctxt->value = NULL;
18630 }
18631#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018632 ctxt->node = elem;
18633 if (ret < 0) {
18634 xmlSchemaVCustomErr(ctxt,
18635 XML_SCHEMAV_INTERNAL,
18636 elem, actualType,
18637 "Internal error: xmlSchemaValidateElementByDeclaration, "
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000018638 "calling validation by type", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018639 return (-1);
18640 }
18641 /*
18642 * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
18643 * not applied, all of the following must be true:
18644 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018645 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) && (nilled == 0)) {
18646 /*
18647 * 5.2.2.1 The element information item must have no element
18648 * information item [children].
18649 *
18650 * TODO REDUNDANT: If the actual type exists, the above call to
18651 * xmlSchemaValidateElementByType will already check for element
18652 * nodes.
18653 */
18654 if (xmlSchemaHasElemContent(elem)) {
18655 xmlSchemaVCustomErr(ctxt,
18656 XML_SCHEMAV_CVC_ELT_5_2_2_1,
18657 elem, (xmlSchemaTypePtr) elemDecl,
18658 "Elements in the content are not allowed if it is "
18659 "constrained by a fixed value", NULL);
18660 } else {
18661 /*
18662 * 5.2.2.2 The appropriate case among the following must
18663 * be true:
18664 */
18665
18666 if (actualType->contentType == XML_SCHEMA_CONTENT_MIXED) {
18667 xmlChar *value;
18668 /*
18669 * 5.2.2.2.1 If the {content type} of the ·actual type
18670 * definition· is mixed, then the *initial value* of the
18671 * item must match the canonical lexical representation
18672 * of the {value constraint} value.
18673 *
18674 * ... the *initial value* of an element information
18675 * item is the string composed of, in order, the
18676 * [character code] of each character information item in
18677 * the [children] of that element information item.
18678 */
18679 value = xmlNodeListGetString(elem->doc, elem->children, 1);
18680 if (! xmlStrEqual(BAD_CAST value, elemDecl->value)) {
18681 /*
18682 * TODO: Report invalid & expected values as well.
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018683 * TODO: Implement the canonical stuff.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018684 */
18685 xmlSchemaVCustomErr(ctxt,
18686 XML_SCHEMAV_CVC_ELT_5_2_2_2_1,
18687 elem, (xmlSchemaTypePtr) elemDecl,
18688 "The value does not match the cononical "
18689 "lexical representation of the fixed constraint",
18690 NULL);
18691 }
18692 if (value != NULL)
18693 xmlFree(value);
18694 } else if ((actualType->contentType ==
18695 XML_SCHEMA_CONTENT_SIMPLE) ||
18696 (actualType->contentType == XML_SCHEMA_CONTENT_BASIC)) {
18697 xmlChar *value;
18698
18699 /*
18700 * 5.2.2.2.2 If the {content type} of the ·actual type
18701 * definition· is a simple type definition, then the
18702 * *actual value* of the item must match the canonical
18703 * lexical representation of the {value constraint} value.
18704 */
18705 /*
18706 * TODO: *actual value* is the normalized value, impl. this.
18707 * TODO: Report invalid & expected values as well.
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018708 * TODO: Implement the canonical stuff.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018709 *
18710 */
18711 value = xmlNodeListGetString(elem->doc, elem->children, 1);
18712 if (! xmlStrEqual(BAD_CAST value, elemDecl->value)) {
18713 xmlSchemaVCustomErr(ctxt,
18714 XML_SCHEMAV_CVC_ELT_5_2_2_2_2,
18715 elem, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018716 "The normalized value does not match the canonical "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018717 "lexical representation of the fixed constraint",
18718 NULL);
18719 }
18720 if (value != NULL)
18721 xmlFree(value);
18722
18723 }
18724 /*
18725 * TODO: What if the content type is not 'mixed' or simple?
18726 */
18727
18728 }
18729
18730 }
18731 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018732 /*
18733 * TODO: 7 If the element information item is the ·validation root·, it must be
18734 * ·valid· per Validation Root Valid (ID/IDREF) (§3.3.4).
18735 */
18736
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018737 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000018738}
18739
Daniel Veillard4255d502002-04-16 15:50:10 +000018740/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018741 * xmlSchemaValidateElementByWildcardInternal:
Daniel Veillardc0826a72004-08-10 14:17:33 +000018742 * @ctxt: a schema validation context
18743 * @node: the top node.
18744 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018745 * Represents the recursive portion of xmlSchemaValidateElementByWildcard.
18746 * Not intended to be used by other functions.
Daniel Veillardc0826a72004-08-10 14:17:33 +000018747 *
18748 * Returns 0 if the element is valid, a positive error code
18749 * number otherwise and -1 in case of an internal error.
18750 */
18751static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018752xmlSchemaValidateElementByWildcardInternal(xmlSchemaValidCtxtPtr ctxt,
18753 xmlSchemaWildcardPtr wild,
18754 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +000018755{
18756 const xmlChar *uri;
18757 int ret = 0;
18758 xmlNodePtr child;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018759
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018760 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018761 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
18762 if (ret == -1) {
18763 xmlSchemaVCustomErr(ctxt,
18764 XML_SCHEMAV_INTERNAL,
18765 ctxt->node, NULL,
18766 "Internal error: xmlSchemaValidateElement, "
18767 "assembling schema by xsi", NULL);
18768 return (-1);
18769 }
18770 /*
18771 * NOTE: We won't react on schema parser errors here.
18772 * TODO: But a warning would be nice.
18773 */
18774 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000018775 if (wild->processContents != XML_SCHEMAS_ANY_SKIP) {
18776 xmlSchemaElementPtr decl = NULL;
18777
18778 if (node->ns != NULL)
18779 decl = xmlHashLookup3(ctxt->schema->elemDecl,
18780 node->name, node->ns->href, NULL);
18781 else
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018782 decl = xmlHashLookup3(ctxt->schema->elemDecl, node->name,
18783 NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018784 if (decl != NULL) {
18785 ctxt->node = node;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018786 ret = xmlSchemaValidateElementByDeclaration(ctxt, decl);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018787 if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018788 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000018789 "Internal error: xmlSchemaValidateAnyInternal, "
18790 "validating an element in the context of a wildcard.",
18791 NULL, NULL);
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +000018792 }
18793 return (ret);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018794 } else if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
18795 /* TODO: Change to proper error code. */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018796 xmlSchemaVWildcardErr(ctxt, XML_SCHEMAV_CVC_ELT_1,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018797 node, wild, "No matching global declaration available");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018798 /*
18799 * Evaluate IDCs even if a validation error occured.
18800 */
18801#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018802 if (xmlSchemaXPathEvaluate(ctxt,XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018803 return(-1);
18804#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +000018805 return (ctxt->err);
18806 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018807 /*
18808 * Evaluate IDCs; we need to know if an IDC field resolves to
18809 * such a node. This node has no type definition and will
18810 * definitely result in an IDC validation error if an IDC field
18811 * resolves.
18812 */
18813#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018814 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018815 return(-1);
18816#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +000018817 }
18818 if (node->children != NULL) {
18819 child = node->children;
18820 do {
18821 if (child->type == XML_ELEMENT_NODE) {
18822 if (child->ns != NULL)
18823 uri = child->ns->href;
18824 else
18825 uri = NULL;
18826 if (xmlSchemaMatchesWildcardNs(wild, uri) == 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018827 /* TODO: error code. */
18828 xmlSchemaVWildcardErr(ctxt, XML_SCHEMAV_ELEMENT_CONTENT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000018829 child, wild,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018830 "The namespace of the element is not allowed");
Daniel Veillardc0826a72004-08-10 14:17:33 +000018831 return (ctxt->err);
18832 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018833#ifdef ELEM_INFO_ENABLED
18834 ctxt->node = child;
18835 xmlSchemaBeginElement(ctxt);
18836#endif
18837 /*
18838 * Recurse over the children.
18839 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018840 ret = xmlSchemaValidateElementByWildcardInternal(ctxt,
18841 wild, child);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018842 if (ret == -1)
18843 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018844#ifdef ELEM_INFO_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018845 if (xmlSchemaEndElement(ctxt) == -1)
18846 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018847#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +000018848 if (ret != 0)
18849 return (ret);
18850 }
18851 child = child->next;
18852 } while (child != NULL);
18853 }
18854 return (0);
18855}
18856
18857/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018858 * xmlSchemaValidateElementContByWildcard:
Daniel Veillardc0826a72004-08-10 14:17:33 +000018859 * @ctxt: a schema validation context
18860 *
18861 * Returns 0 if the element is valid, a positive error code
18862 * number otherwise and -1 in case of an internal or API error.
18863 */
18864static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018865xmlSchemaValidateElementByWildcard(xmlSchemaValidCtxtPtr ctxt,
18866 xmlSchemaTypePtr type)
Daniel Veillardc0826a72004-08-10 14:17:33 +000018867{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018868 if ((type == NULL) || (type->type != XML_SCHEMA_TYPE_ANY) ||
18869 (ctxt->node == NULL)) {
18870 xmlSchemaVCustomErr(ctxt,
18871 XML_SCHEMAV_INTERNAL, ctxt->node, NULL,
18872 "Internal error: xmlSchemaValidateElementByWildcard, "
18873 "bad arguments", NULL);
18874 return (-1);
18875 }
18876 return(xmlSchemaValidateElementByWildcardInternal(ctxt,
18877 type->attributeWildcard, ctxt->node));
Daniel Veillardc0826a72004-08-10 14:17:33 +000018878}
18879
18880/**
William M. Brack2f2a6632004-08-20 23:09:47 +000018881 * xmlSchemaValidateAnyTypeContent:
18882 * @ctxt: a schema validation context
18883 * @node: the current element
18884 *
18885 * This one validates the content of an element of the type
18886 * 'anyType'. The process contents of the wildcard of 'anyType' is "lax",
18887 * thus elements in the subtree will be validated, if a corresponding
18888 * declaration in the schema exists.
18889 *
18890 * Returns 0 if the element and its subtree is valid, a positive error code
18891 * otherwise and -1 in case of an internal or API error.
18892 */
18893static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018894xmlSchemaValidateElementByAnyType(xmlSchemaValidCtxtPtr ctxt,
18895 xmlSchemaTypePtr type)
William M. Brack2f2a6632004-08-20 23:09:47 +000018896{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018897 xmlSchemaTypePtr oldtype;
18898 xmlNodePtr top, cur;
18899 xmlSchemaElementPtr decl;
William M. Brack2f2a6632004-08-20 23:09:47 +000018900 int skipContent, ret;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018901
18902 if ((type == NULL) || (ctxt->node == NULL))
18903 return (-1);
18904
18905 if (ctxt->node->children == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +000018906 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018907
18908 oldtype = ctxt->type;
18909 top = ctxt->node;
18910 /*
18911 * STREAM: Child nodes are processed.
18912 */
18913 cur = ctxt->node->children;
18914 while (cur != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +000018915 skipContent = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018916 if (cur->type == XML_ELEMENT_NODE) {
William M. Brack2f2a6632004-08-20 23:09:47 +000018917 /*
18918 * The process contents of the wildcard is "lax", thus
18919 * we need to validate the element if a declaration
18920 * exists.
18921 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018922 if (cur->ns != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +000018923 decl = xmlHashLookup3(ctxt->schema->elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018924 cur->name, cur->ns->href, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000018925 else
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018926 decl = xmlHashLookup3(ctxt->schema->elemDecl, cur->name, NULL, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000018927 if (decl != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018928 ctxt->node = cur;
18929 ret = xmlSchemaValidateElementByDeclaration(ctxt, decl);
18930 ctxt->node = top;
William M. Brack2f2a6632004-08-20 23:09:47 +000018931 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018932 xmlSchemaVErr(ctxt, cur, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000018933 "Internal error: xmlSchemaValidateAnyTypeContent, "
18934 "validating an element in the context of a wildcard.",
18935 NULL, NULL);
18936 return (ret);
18937 } else if (ret > 0)
18938 return (ret);
18939 skipContent = 1;
18940 }
18941 }
18942 /*
18943 * Browse the full subtree, deep first.
18944 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018945 if ((skipContent == 0) && (cur->children != NULL)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000018946 /* deep first */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018947 cur = cur->children;
18948 } else if ((cur != top) && (cur->next != NULL)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000018949 /* then siblings */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018950 cur = cur->next;
18951 } else if (cur != top) {
William M. Brack2f2a6632004-08-20 23:09:47 +000018952 /* go up to parents->next if needed */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018953 while (cur != top) {
18954 if (cur->parent != NULL)
18955 cur = cur->parent;
18956 if ((cur != top) && (cur->next != NULL)) {
18957 cur = cur->next;
William M. Brack2f2a6632004-08-20 23:09:47 +000018958 break;
18959 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018960 if (cur->parent == NULL) {
18961 cur = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000018962 break;
18963 }
18964 }
18965 /* exit condition */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018966 if (cur == top)
18967 cur = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000018968 } else
18969 break;
18970 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018971 ctxt->type = oldtype;
William M. Brack2f2a6632004-08-20 23:09:47 +000018972 return (0);
18973}
18974
18975/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018976 * xmlSchemaValidateElementByComplexType:
Daniel Veillard4255d502002-04-16 15:50:10 +000018977 * @ctxt: a schema validation context
18978 * @node: the top node.
18979 *
18980 * Validate the content of an element expected to be a complex type type
18981 * xmlschema-1.html#cvc-complex-type
18982 * Validation Rule: Element Locally Valid (Complex Type)
18983 *
18984 * Returns 0 if the element is schemas valid, a positive error code
Daniel Veillard01fa6152004-06-29 17:04:39 +000018985 * number otherwise and -1 in case of internal or API error.
18986 * Note on reported errors: Although it might be nice to report
18987 * the name of the simple/complex type, used to validate the content
18988 * of a node, it is quite unnecessary: for global defined types
18989 * the local name of the element is equal to the NCName of the type,
18990 * for local defined types it makes no sense to output the internal
18991 * computed name of the type. TODO: Instead, one should attach the
18992 * struct of the type involved to the error handler - this allows
18993 * the report of any additional information by the user.
Daniel Veillard4255d502002-04-16 15:50:10 +000018994 */
18995static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018996xmlSchemaValidateElementByComplexType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018997 xmlSchemaTypePtr type,
18998 int valSimpleContent)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018999{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019000 xmlSchemaTypePtr oldtype;
19001 xmlNodePtr elem, child;
Daniel Veillard01fa6152004-06-29 17:04:39 +000019002 int ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +000019003 const xmlChar *nsUri;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019004 xmlSchemaAttrStatePtr attrs = NULL, attrTop = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000019005
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019006 if ((ctxt == NULL) || (type->type != XML_SCHEMA_TYPE_COMPLEX))
19007 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000019008
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019009 oldtype = ctxt->type;
19010 ctxt->type = type;
19011 elem = ctxt->node;
19012
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019013 /*
19014 * Verify the attributes
19015 */
19016 /*
19017 * TODO: This "attrTop" thing is not needed any more.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019018 */
19019 /* NOTE: removed, since a check for abstract is
19020 * done in the cvc-type constraint.
19021 *
19022 *
19023 * if (type->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
19024 * xmlSchemaVComplexTypeErr(ctxt,
19025 * XML_SCHEMAV_CVC_COMPLEX_TYPE_1,
19026 * elem, type,
19027 * "The type definition is abstract");
19028 * return (XML_SCHEMAV_CVC_COMPLEX_TYPE_1);
19029 *}
19030 */
19031
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019032 attrs = ctxt->attr;
19033 attrTop = ctxt->attrTop;
19034 /*
19035 * STREAM: Attribute nodes are processed.
19036 */
19037 xmlSchemaRegisterAttributes(ctxt, elem->properties);
19038 xmlSchemaValidateAttributes(ctxt, elem, type);
19039 if (ctxt->attr != NULL)
19040 xmlSchemaFreeAttributeStates(ctxt->attr);
19041 ctxt->attr = attrs;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019042 ctxt->attrTop = attrTop;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019043
19044 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019045 * TODO: This one creates a regexp even if no content
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019046 * model was defined. Somehow ->contModel is always not NULL
19047 * for complex types, even if they are empty.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019048 * TODO: Check if the obove still occurs.
19049 */
Daniel Veillard4255d502002-04-16 15:50:10 +000019050 switch (type->contentType) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000019051 case XML_SCHEMA_CONTENT_EMPTY: {
19052 /*
19053 * 1 If the {content type} is empty, then the element information
19054 * item has no character or element information item [children].
Daniel Veillard3646d642004-06-02 19:19:14 +000019055 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000019056 /*
19057 * TODO: Is the entity stuff correct?
19058 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019059 if (xmlSchemaHasElemOrCharContent(elem) == 1) {
William M. Brack2f2a6632004-08-20 23:09:47 +000019060 xmlSchemaVComplexTypeErr(ctxt,
19061 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019062 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000019063 "Character or element content is not allowed, "
19064 "because the content type is empty");
Daniel Veillard01fa6152004-06-29 17:04:39 +000019065 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019066 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000019067 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019068 case XML_SCHEMA_CONTENT_MIXED:
19069 if ((type->subtypes == NULL) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019070 (type->baseType->builtInType == XML_SCHEMAS_ANYTYPE)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019071 /*
19072 * The type has 'anyType' as its base and no content model
19073 * is defined -> use 'anyType' as the type to validate
19074 * against.
19075 */
19076 ret = xmlSchemaValidateElementByAnyType(ctxt, type->baseType);
19077 /* TODO: Handle -1. */
19078 break;
19079 }
19080 /* No break on purpose. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000019081 case XML_SCHEMA_CONTENT_ELEMENTS:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019082 {
19083 xmlRegExecCtxtPtr oldregexp = NULL;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019084 xmlChar *values[10];
19085 int terminal, nbval = 10, nbneg;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019086
19087 /*
19088 * Content model check initialization.
19089 */
19090 if (type->contModel != NULL) {
19091 oldregexp = ctxt->regexp;
19092 ctxt->regexp = xmlRegNewExecCtxt(type->contModel,
19093 (xmlRegExecCallbacks)
19094 xmlSchemaValidateCallback, ctxt);
19095#ifdef DEBUG_AUTOMATA
19096 xmlGenericError(xmlGenericErrorContext, "====> %s\n", elem->name);
19097#endif
19098 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019099 /*
19100 * STREAM: Children are processed.
19101 */
19102 child = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000019103 while (child != NULL) {
19104 if (child->type == XML_ELEMENT_NODE) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000019105 if (child->ns != NULL)
19106 nsUri = child->ns->href;
19107 else
19108 nsUri = NULL;
19109 ret = xmlRegExecPushString2(ctxt->regexp,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019110 child->name, nsUri, child);
19111 if (ctxt->err == XML_SCHEMAV_INTERNAL)
19112 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019113 /*
19114 * URGENT TODO: Could we anchor an error report
19115 * here to notify of invalid elements?
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019116 * TODO: Perhaps it would be better to report
19117 * only the first erroneous element and then break.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019118 */
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019119#ifdef DEBUG_AUTOMATA
Daniel Veillard01fa6152004-06-29 17:04:39 +000019120 if (ret < 0)
19121 xmlGenericError(xmlGenericErrorContext,
19122 " --> %s Error\n", child->name);
William M. Bracke7091952004-05-11 15:09:58 +000019123 else
19124 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard01fa6152004-06-29 17:04:39 +000019125 " --> %s\n", child->name);
19126#endif
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019127 if (ret < 0) {
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019128 xmlRegExecErrInfo(ctxt->regexp, NULL, &nbval, &nbneg,
19129 &values[0], &terminal);
19130 xmlSchemaVComplexTypeElemErr(ctxt,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019131 XML_SCHEMAV_ELEMENT_CONTENT,
19132 child, NULL/* type */,
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019133 "This element is not expected",
19134 nbval, nbneg, values);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019135 ret = 1;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019136 /*
19137 * Note that this will skip further validation of the
19138 * content.
19139 */
19140 break;
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019141 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000019142 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) &&
19143 /*
19144 * TODO: Ask Daniel if this are all character nodes.
19145 */
19146 (((child->type == XML_TEXT_NODE) && (!IS_BLANK_NODE(child))) ||
19147 (child->type == XML_ENTITY_NODE) ||
19148 (child->type == XML_ENTITY_REF_NODE) ||
19149 (child->type == XML_CDATA_SECTION_NODE))) {
19150 /*
19151 * 2.3 If the {content type} is element-only, then the
19152 * element information item has no character information
19153 * item [children] other than those whose [character
19154 * code] is defined as a white space in [XML 1.0 (Second
19155 * Edition)].
19156 */
William M. Brack2f2a6632004-08-20 23:09:47 +000019157 xmlSchemaVComplexTypeErr(ctxt,
19158 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019159 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000019160 "Character content is not allowed, "
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019161 "because the content type is element-only");
19162 ret = 1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000019163 break;
19164 }
19165 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019166 }
19167 /*
19168 * Content model check finalization.
19169 */
19170 if (type->contModel != NULL) {
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019171 if (ret == 0) {
19172 xmlRegExecNextValues(ctxt->regexp, &nbval, &nbneg,
19173 &values[0], &terminal);
19174 if (nbval + nbneg != 0) {
19175 /*
19176 * If a next value still exists, I does not have to
19177 * mean that there's an element missing, since it
19178 * might be an optional element. So double check it.
19179 */
19180 ret = xmlRegExecPushString(ctxt->regexp,
19181 NULL, NULL);
19182 if (ret <= 0) {
19183 ret = 1;
19184 xmlSchemaVComplexTypeElemErr(ctxt,
19185 XML_SCHEMAV_ELEMENT_CONTENT,
19186 elem, type, "Missing child element(s)",
19187 nbval, nbneg, values);
19188 } else
19189 ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019190#ifdef DEBUG_AUTOMATA
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019191 xmlGenericError(xmlGenericErrorContext,
19192 "====> %s : %d\n", elem->name, ret);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019193#endif
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019194 }
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019195#ifdef DEBUG_CONTENT
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019196 if (ret == 0)
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019197 xmlGenericError(xmlGenericErrorContext,
19198 "Element %s content check succeeded\n",
19199 elem->name);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019200#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019201 }
19202 xmlRegFreeExecCtxt(ctxt->regexp);
19203 ctxt->regexp = oldregexp;
19204 }
19205 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000019206 break;
19207 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019208 case XML_SCHEMA_CONTENT_BASIC:
19209 /*
19210 * If the simple content was already validated
19211 * (e.g. a default value), the content need not
19212 * to be validated again.
19213 */
19214 if (valSimpleContent == 1) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000019215 xmlChar *value = NULL;
19216 /*
19217 * We hit a complexType with a simpleContent resolving
19218 * to a user derived or built-in simple type.
William M. Brack2f2a6632004-08-20 23:09:47 +000019219 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000019220 /*
19221 * 2.2 If the {content type} is a simple type definition,
19222 * then the element information item has no element
19223 * information item [children], and the ·normalized value·
19224 * of the element information item is ·valid· with respect
19225 * to that simple type definition as defined by String
19226 * Valid (§3.14.4).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019227 */
19228 /*
19229 * STREAM: Children are processed.
19230 */
19231 child = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000019232 while (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019233 /*
19234 * TODO: Could the entity stuff produce elements
19235 * as well?
19236 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000019237 if (child->type == XML_ELEMENT_NODE) {
William M. Brack2f2a6632004-08-20 23:09:47 +000019238 xmlSchemaVComplexTypeErr(ctxt,
19239 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019240 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000019241 "Element content is not allowed, because "
19242 "the content type is a simple type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000019243 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
19244 break;
19245 }
19246 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019247 }
19248 ctxt->node = elem;
19249 ctxt->cur = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000019250 if (ret == 0) {
19251 /*
19252 * Validate the character content against a simple type.
Daniel Veillard3646d642004-06-02 19:19:14 +000019253 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019254 /*
19255 * STREAM: Children are processed.
19256 */
19257 if (elem->children == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000019258 value = NULL;
19259 else
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019260 value = xmlNodeGetContent(elem);
19261 /*
19262 * URGENT TODO: Should facets for the simple type validation be
19263 * disabled, if the derivation of facets for complex types
19264 * is implemented?
19265 */
19266 /*
19267 * NOTE: This call won't check the correct types of the
19268 * content nodes, since this should be done here.
19269 */
19270 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type, value, 1, 1, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000019271 if (ret > 0) {
19272 /*
19273 * NOTE: Although an error will be reported by
19274 * xmlSchemaValidateSimpleTypeValue, the spec wants
19275 * a specific complex type error to be reported
19276 * additionally.
19277 */
19278 xmlSchemaVComplexTypeErr(ctxt,
19279 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019280 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000019281 "The character content is not valid");
Daniel Veillard01fa6152004-06-29 17:04:39 +000019282 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
19283 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019284 xmlSchemaVErr(ctxt, elem, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000019285 "Internal error: xmlSchemaValidateComplexType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000019286 "Element '%s': Error while validating character "
19287 "content against complex type '%s'.\n",
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019288 elem->name, type->name);
19289 if (value != NULL)
19290 xmlFree(value);
19291 ctxt->type = oldtype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000019292 return (-1);
19293 }
William M. Brack2f2a6632004-08-20 23:09:47 +000019294 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000019295 if (ret == 0) {
19296 /*
19297 * Apply facets of the complexType. Be sure to pass the
19298 * built-in type to xmlSchemaValidateFacetsInternal.
19299 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019300 /* URGENT TODO: I don't know yet if the facets of the simple type
Daniel Veillard01fa6152004-06-29 17:04:39 +000019301 * are used, or if the facets, defined by this complex type,
19302 * are to be used only. This here applies both facet sets.
19303 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000019304
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019305 ret = xmlSchemaValidateFacetsInternal(ctxt,
19306 type, value, 0, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000019307 if (ret > 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +000019308 xmlSchemaVComplexTypeErr(ctxt,
19309 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019310 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000019311 "The character content is not valid");
Daniel Veillard01fa6152004-06-29 17:04:39 +000019312 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
19313 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019314 xmlSchemaVErr(ctxt, elem, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000019315 "Internal error: xmlSchemaValidateComplexType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000019316 "Element '%s': Error while validating character "
19317 "content against complex type '%s'; failed to "
Daniel Veillard01fa6152004-06-29 17:04:39 +000019318 "apply facets.\n",
19319 type->name, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019320 if (value != NULL)
19321 xmlFree(value);
19322 ctxt->type = oldtype;
19323 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000019324 }
19325 }
19326 if (value != NULL)
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019327 xmlFree(value);
19328
Daniel Veillard01fa6152004-06-29 17:04:39 +000019329 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019330 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019331 default:
19332 TODO xmlGenericError(xmlGenericErrorContext,
19333 "unimplemented content type %d\n",
19334 type->contentType);
Daniel Veillard4255d502002-04-16 15:50:10 +000019335 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019336 ctxt->type = oldtype;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019337 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000019338}
19339
19340/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019341 * xmlSchemaValidateElementByType:
Daniel Veillard4255d502002-04-16 15:50:10 +000019342 * @ctxt: a schema validation context
19343 * @elem: an element
19344 * @type: the list of type declarations
19345 *
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019346 * Validation Rule: Element Locally Valid (Type).
Daniel Veillard4255d502002-04-16 15:50:10 +000019347 *
19348 * Returns 0 if the element is schemas valid, a positive error code
19349 * number otherwise and -1 in case of internal or API error.
19350 */
19351static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019352xmlSchemaValidateElementByType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019353 xmlSchemaTypePtr type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019354 int isNil,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019355 int valSimpleContent)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019356{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019357 int ret;
Daniel Veillard4255d502002-04-16 15:50:10 +000019358
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019359
19360 if ((ctxt == NULL) || (type == NULL)) {
19361 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_INTERNAL, NULL, NULL,
19362 "Internal error: xmlSchemaValidateElementByType, "
19363 "bad arguments", NULL);
19364 return (-1);
19365 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019366 /*
19367 * This one is called by "xmlSchemaValidateElementByDeclaration".
19368 * It will forward to the proper validation
19369 * procedures for the given type.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019370 */
19371 if (type == NULL) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019372 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019373 XML_SCHEMAV_CVC_TYPE_1,
19374 ctxt->node, NULL,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019375 "The type definition is absent", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019376 return (XML_SCHEMAV_CVC_TYPE_1);
19377 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019378
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019379 if (type->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019380 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019381 XML_SCHEMAV_CVC_TYPE_2,
19382 ctxt->node, type,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019383 "The type definition is abstract", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019384 return (XML_SCHEMAV_CVC_TYPE_2);
19385 }
19386
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019387 switch (type->type) {
19388 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019389 ret = xmlSchemaValidateElementByComplexType(ctxt, type,
19390 valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019391 break;
19392 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019393 ret = xmlSchemaValidateElementBySimpleType(ctxt, type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019394 isNil, valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019395 break;
19396 case XML_SCHEMA_TYPE_BASIC:
19397 if (type->builtInType == XML_SCHEMAS_ANYTYPE)
19398 ret = xmlSchemaValidateElementByAnyType(ctxt, type);
19399 else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019400 ret = xmlSchemaValidateElementBySimpleType(ctxt, type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019401 isNil, valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019402 break;
19403 default:
19404 ret = -1;
19405 break;
19406 }
19407 if (ret == -1)
19408 return (-1);
19409 else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019410 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000019411}
19412
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019413static int
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019414xmlSchemaPostCreateVal(xmlSchemaValidCtxtPtr vctxt,
19415 const xmlChar *value,
19416 xmlSchemaValPtr *val)
19417{
19418 xmlSchemaTypePtr prim;
19419
19420 if (val == NULL) {
19421 xmlSchemaVErr(vctxt, vctxt->nodeInfo->node,
19422 XML_SCHEMAV_INTERNAL,
19423 "Internal error: xmlSchemaPostCreateVal, "
19424 "bad arguments", NULL, NULL);
19425 return (-1);
19426 }
19427 /*
19428 * Only string or anySimpleType values are expected to be post-created.
19429 */
19430 prim = xmlSchemaGetPrimitiveType(vctxt->nodeInfo->typeDef);
19431 if ((prim->builtInType == XML_SCHEMAS_STRING) ||
19432 (prim->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
19433 {
19434#if 0
19435 builtIn = xmlSchemaGetBuiltInTypeAncestor(vctxt->nodeInfo->typeDef);
19436#endif
19437 if (value == NULL)
19438 /* TODO: Can this happen at all? */
19439 *val = xmlSchemaNewStringValue(XML_SCHEMAS_STRING,
19440 xmlStrdup(BAD_CAST ""));
19441 else
19442 *val = xmlSchemaNewStringValue(XML_SCHEMAS_STRING, value);
19443 if ((*val) == NULL) {
19444 xmlSchemaVErr(vctxt, vctxt->nodeInfo->node,
19445 XML_SCHEMAV_INTERNAL,
19446 "Internal error: xmlSchemaPostCreateVal, "
19447 "failed to create the value", NULL, NULL);
19448 return (-1);
19449 }
19450 return (0);
19451 }
19452 xmlSchemaVErr(vctxt, vctxt->nodeInfo->node,
19453 XML_SCHEMAV_INTERNAL,
19454 "Internal error: xmlSchemaPostCreateVal, "
19455 "the given type is not supported", NULL, NULL);
19456 return (-1);
19457}
19458
19459static int
19460xmlSchemaCheckAttrLocallyValid(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019461 xmlSchemaAttrStatePtr state)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019462{
19463 xmlChar *value;
19464 const xmlChar *defValue;
19465 xmlSchemaValPtr defVal;
19466 int fixed;
19467 int ret;
19468
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019469 if (vctxt->attrInfo->typeDef == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019470 state->state = XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED;
19471 return (XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED);
19472 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019473 vctxt->node = vctxt->attrInfo->node;
19474 vctxt->cur = vctxt->node->children;
19475 /* STREAM */
19476 value = xmlNodeListGetString(vctxt->node->doc, vctxt->cur, 1);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019477
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019478 /*
19479 * NOTE: This call also checks the content nodes for correct type.
19480 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019481 ret = xmlSchemaValidateSimpleTypeValue(vctxt, vctxt->attrInfo->typeDef,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019482 value, 1, 1, 1, 1);
19483
19484 /*
19485 * Handle 'fixed' attributes.
19486 */
19487 if (ret > 0) {
19488 state->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
19489 /*
19490 * NOTE: Fixed value constraints will be not
19491 * applied if the value was invalid, because:
19492 * 1. The validation process does not return a precomputed
19493 * value.
19494 * 2. An invalid value implies a violation of a fixed
19495 * value constraint.
19496 */
19497 } else if (ret == 0) {
19498 state->state = XML_SCHEMAS_ATTR_CHECKED;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019499 if (xmlSchemaGetEffectiveValueConstraint(
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019500 (xmlSchemaAttributePtr) vctxt->attrInfo->decl,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019501 &fixed, &defValue, &defVal) && (fixed == 1)) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000019502
19503 int ws = xmlSchemaGetWhiteSpaceFacetValue(
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019504 vctxt->nodeInfo->typeDef);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019505 /*
19506 * cvc-au : Attribute Locally Valid (Use)
19507 * For an attribute information item to be·valid·
19508 * with respect to an attribute use its ·normalized
19509 * value· must match the canonical lexical representation
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019510 * of the attribute use's {value constraint} value, if it
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019511 * is present and fixed.
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019512 *
19513 * TODO: Use somehow the *normalized* value and the *canonical*
19514 * fixed value. This here compares the canonical values of both.
19515 * The normalized value of, for example, a float type can differ
19516 * from its canonical representation. This all means that a fixed
19517 * value can only be OK, if it's present in the canonical form in
19518 * the instance.
19519 * NOTE: Since the value for string and anySimpleType is not always
19520 * precomputed during validation, we need to do it now.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019521 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019522 if (vctxt->value == NULL) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000019523 /*
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019524 * Post-create the value.
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000019525 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019526 if (xmlSchemaPostCreateVal(vctxt, value, &(vctxt->value)) == -1) {
19527 ret = -1;
19528 goto exit;
19529 }
19530 value = NULL;
19531 }
19532 if (defVal == NULL) {
19533 xmlChar *str;
19534
19535 /*
19536 * Post-create the default/fixed value.
19537 */
19538 if (defValue == NULL)
19539 str = xmlStrdup(BAD_CAST "");
19540 else
19541 str = xmlStrdup(defValue);
19542 if (xmlSchemaPostCreateVal(vctxt, str, &defVal) == -1) {
19543 ret = -1;
19544 FREE_AND_NULL(str)
19545 goto exit;
19546 }
19547 ((xmlSchemaAttributePtr) vctxt->attrInfo->decl)->defVal = defVal;
19548 }
19549 if (xmlSchemaCompareValuesWhtsp(vctxt->value,
19550 (xmlSchemaWhitespaceValueType) ws,
19551 defVal,
19552 (xmlSchemaWhitespaceValueType) ws) != 0)
19553 {
19554 state->state = XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019555 }
19556 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019557 }
19558exit:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019559 if (value != NULL) {
19560 xmlFree(value);
19561 }
19562 return (ret);
19563}
19564
Daniel Veillard4255d502002-04-16 15:50:10 +000019565/**
19566 * xmlSchemaValidateAttributes:
19567 * @ctxt: a schema validation context
19568 * @elem: an element
Daniel Veillard3646d642004-06-02 19:19:14 +000019569 * @type: the complexType holding the attribute uses
Daniel Veillard4255d502002-04-16 15:50:10 +000019570 *
19571 * Validate the attributes of an element.
19572 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000019573 * 1. Existent, invalid attributes are reported in the form
19574 * "prefix:localName".
19575 * Reason: readability - it is easier to find the actual XML
19576 * representation of the attributes QName.
19577 * 2. Missing attributes are reported in the form
19578 * {"URI", "localName"}.
19579 * This is necessary, since the the prefix need not to be declared
19580 * at all, and thus is not computable.
19581 *
Daniel Veillard4255d502002-04-16 15:50:10 +000019582 * Returns 0 if the element is schemas valid, a positive error code
19583 * number otherwise and -1 in case of internal or API error.
19584 */
19585static int
Daniel Veillard3646d642004-06-02 19:19:14 +000019586xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem, xmlSchemaTypePtr type)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019587{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019588 const xmlChar *nsURI;
Daniel Veillard3646d642004-06-02 19:19:14 +000019589 int ret;
19590 xmlAttrPtr attr; /* An attribute on the element. */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019591 const xmlChar *defValue;
19592 xmlSchemaValPtr defVal;
19593 int fixed;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019594 xmlSchemaAttributeLinkPtr attrUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000019595 xmlSchemaAttributePtr attrDecl;
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000019596 int found;
William M. Brack803812b2004-06-03 02:11:24 +000019597 xmlSchemaAttrStatePtr curState, reqAttrStates = NULL, reqAttrStatesTop = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019598 xmlSchemaAttrStatePtr defAttrStates = NULL, defAttrStatesTop = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019599 xmlNodePtr oldnode;
Daniel Veillard3646d642004-06-02 19:19:14 +000019600#ifdef DEBUG_ATTR_VALIDATION
19601 int redundant = 0;
19602#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000019603
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019604
Daniel Veillardc0826a72004-08-10 14:17:33 +000019605 /*
19606 * Allow all attributes if the type is anyType.
19607 */
19608 if (type == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE))
19609 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019610
19611 oldnode = ctxt->node;
19612 if (type != NULL)
19613 attrUse = type->attributeUses;
Daniel Veillard3646d642004-06-02 19:19:14 +000019614 while (attrUse != NULL) {
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000019615 found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000019616 attrDecl = attrUse->attr;
19617#ifdef DEBUG_ATTR_VALIDATION
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019618 printf("attr use - name: %s\n", xmlSchemaGetAttrName(attrDecl));
Daniel Veillard3646d642004-06-02 19:19:14 +000019619 printf("attr use - use: %d\n", attrDecl->occurs);
19620#endif
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019621 for (curState = ctxt->attr; curState != NULL; curState = curState->next) {
Daniel Veillard3646d642004-06-02 19:19:14 +000019622
19623 if (curState->decl == attrUse->attr) {
19624#ifdef DEBUG_ATTR_VALIDATION
19625 redundant = 1;
19626#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019627 }
Daniel Veillard3646d642004-06-02 19:19:14 +000019628 attr = curState->attr;
19629#ifdef DEBUG_ATTR_VALIDATION
19630 printf("attr - name: %s\n", attr->name);
19631 if (attr->ns != NULL)
19632 printf("attr - ns: %s\n", attr->ns->href);
19633 else
19634 printf("attr - ns: none\n");
19635#endif
19636 /* TODO: Can this ever happen? */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019637 if (attr == NULL)
19638 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000019639 if (attrDecl->ref != NULL) {
19640 if (!xmlStrEqual(attr->name, attrDecl->ref))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019641 continue;
19642 if (attr->ns != NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000019643 if ((attrDecl->refNs == NULL) ||
19644 (!xmlStrEqual(attr->ns->href, attrDecl->refNs)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019645 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000019646 } else if (attrDecl->refNs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019647 continue;
19648 }
19649 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000019650 if (!xmlStrEqual(attr->name, attrDecl->name))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019651 continue;
19652 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +000019653 * handle the namespaces checks here
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019654 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000019655 if (attr->ns == NULL) {
19656 /*
William M. Bracke7091952004-05-11 15:09:58 +000019657 * accept an unqualified attribute only if the target
19658 * namespace of the declaration is absent.
Daniel Veillardbe9c6322003-11-22 20:37:51 +000019659 */
Daniel Veillard3646d642004-06-02 19:19:14 +000019660 if (attrDecl->targetNamespace != NULL)
William M. Bracke7091952004-05-11 15:09:58 +000019661 /*
19662 * This check was removed, since the target namespace
19663 * was evaluated during parsing and already took
19664 * "attributeFormDefault" into account.
19665 */
19666 /* ((attributes->flags & XML_SCHEMAS_ATTR_NSDEFAULT) == 0)) */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000019667 continue;
19668 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000019669 if (attrDecl->targetNamespace == NULL)
Daniel Veillardbe9c6322003-11-22 20:37:51 +000019670 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000019671 if (!xmlStrEqual(attrDecl->targetNamespace,
Daniel Veillardbe9c6322003-11-22 20:37:51 +000019672 attr->ns->href))
19673 continue;
19674 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019675 }
Daniel Veillard3646d642004-06-02 19:19:14 +000019676#ifdef DEBUG_ATTR_VALIDATION
19677 printf("found\n");
19678#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019679 found = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +000019680 curState->decl = attrDecl;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019681 curState->state = XML_SCHEMAS_ATTR_VALIDATE_VALUE;
19682 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019683 ret = xmlSchemaCheckAttrLocallyValid(ctxt, attrDecl, curState, attr);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019684 */
Daniel Veillard3646d642004-06-02 19:19:14 +000019685 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019686 if (!found) {
19687 if (attrDecl->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
19688 xmlSchemaAttrStatePtr tmp;
19689
Daniel Veillard3646d642004-06-02 19:19:14 +000019690#ifdef DEBUG_ATTR_VALIDATION
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019691 printf("required attr not found\n");
Daniel Veillard3646d642004-06-02 19:19:14 +000019692#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019693 /*
19694 * Add a new dummy attribute state.
19695 */
19696 tmp = (xmlSchemaAttrStatePtr) xmlMalloc(sizeof(xmlSchemaAttrState));
19697 if (tmp == NULL) {
19698 xmlSchemaVErrMemory(ctxt, "registering required attributes", NULL);
19699 ctxt->node = oldnode;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019700 goto fatal_exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019701 }
19702 tmp->attr = NULL;
19703 tmp->state = XML_SCHEMAS_ATTR_MISSING;
19704 tmp->decl = attrDecl;
19705 tmp->next = NULL;
19706
19707 if (reqAttrStates == NULL) {
19708 reqAttrStates = tmp;
19709 reqAttrStatesTop = tmp;
19710 } else {
19711 reqAttrStatesTop->next = tmp;
19712 reqAttrStatesTop = tmp;
19713 }
19714 } else if ((attrDecl->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
19715 (xmlSchemaGetEffectiveValueConstraint(attrDecl,
19716 &fixed, &defValue, &defVal))) {
19717 xmlSchemaAttrStatePtr tmp;
19718 /*
19719 * Handle non existent default/fixed attributes.
19720 */
19721 tmp = (xmlSchemaAttrStatePtr)
19722 xmlMalloc(sizeof(xmlSchemaAttrState));
19723 if (tmp == NULL) {
19724 xmlSchemaVErrMemory(ctxt,
19725 "registering schema specified attributes", NULL);
19726 ctxt->node = oldnode;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019727 goto fatal_exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019728 }
19729 tmp->attr = NULL;
19730 tmp->state = XML_SCHEMAS_ATTR_DEFAULT;
19731 tmp->decl = attrDecl;
19732 tmp->value = defValue;
19733 tmp->next = NULL;
19734
19735 if (defAttrStates == NULL) {
19736 defAttrStates = tmp;
19737 defAttrStates = tmp;
19738 } else {
19739 defAttrStates->next = tmp;
19740 defAttrStatesTop = tmp;
19741 }
19742 }
Daniel Veillard3646d642004-06-02 19:19:14 +000019743 }
19744 attrUse = attrUse->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000019745 }
Daniel Veillard3646d642004-06-02 19:19:14 +000019746 /*
19747 * Add required attributes to the attribute states of the context.
19748 */
19749 if (reqAttrStates != NULL) {
19750 if (ctxt->attr == NULL) {
19751 ctxt->attr = reqAttrStates;
19752 } else {
19753 ctxt->attrTop->next = reqAttrStates;
19754 }
19755 ctxt->attrTop = reqAttrStatesTop;
Daniel Veillardc0826a72004-08-10 14:17:33 +000019756 }
Daniel Veillard3646d642004-06-02 19:19:14 +000019757 /*
19758 * Process wildcards.
19759 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019760
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019761 if ((type != NULL) && (type->attributeWildcard != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000019762#ifdef DEBUG_ATTR_VALIDATION
19763 xmlSchemaWildcardNsPtr ns;
19764 printf("matching wildcard: [%d] of complexType: %s\n", type->attributeWildcard, type->name);
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019765 if (type->attributeWildcard->processContents ==
19766 XML_SCHEMAS_ANY_LAX)
19767 printf("processContents: lax\n");
19768 else if (type->attributeWildcard->processContents ==
19769 XML_SCHEMAS_ANY_STRICT)
19770 printf("processContents: strict\n");
19771 else
19772 printf("processContents: skip\n");
Daniel Veillard3646d642004-06-02 19:19:14 +000019773 if (type->attributeWildcard->any)
19774 printf("type: any\n");
19775 else if (type->attributeWildcard->negNsSet != NULL) {
19776 printf("type: negated\n");
19777 if (type->attributeWildcard->negNsSet->value == NULL)
19778 printf("ns: (absent)\n");
19779 else
19780 printf("ns: %s\n", type->attributeWildcard->negNsSet->value);
19781 } else if (type->attributeWildcard->nsSet != NULL) {
19782 printf("type: set\n");
19783 ns = type->attributeWildcard->nsSet;
19784 while (ns != NULL) {
19785 if (ns->value == NULL)
19786 printf("ns: (absent)\n");
19787 else
19788 printf("ns: %s\n", ns->value);
19789 ns = ns->next;
19790 }
19791 } else
19792 printf("empty\n");
19793
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019794
19795#endif
Daniel Veillard3646d642004-06-02 19:19:14 +000019796 curState = ctxt->attr;
19797 while (curState != NULL) {
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019798 if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
19799 if (curState->attr->ns != NULL)
19800 nsURI = curState->attr->ns->href;
19801 else
19802 nsURI = NULL;
19803 if (xmlSchemaMatchesWildcardNs(type->attributeWildcard,
19804 nsURI)) {
19805 /*
19806 * Handle processContents.
19807 */
19808 if ((type->attributeWildcard->processContents ==
19809 XML_SCHEMAS_ANY_LAX) ||
19810 (type->attributeWildcard->processContents ==
19811 XML_SCHEMAS_ANY_STRICT)) {
19812
19813 attr = curState->attr;
19814 attrDecl = xmlSchemaGetAttribute(ctxt->schema,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019815 attr->name, nsURI);
19816 curState->decl = attrDecl;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019817 if (attrDecl != NULL) {
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019818 curState->decl = attrDecl;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019819 curState->state = XML_SCHEMAS_ATTR_VALIDATE_VALUE;
19820 /* TODO
19821 ret = xmlSchemaCheckAttrLocallyValid(ctxt, attrDecl, curState, attr);
19822 */
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019823 } else if (type->attributeWildcard->processContents ==
19824 XML_SCHEMAS_ANY_LAX) {
19825 curState->state = XML_SCHEMAS_ATTR_CHECKED;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019826 } else
19827 curState->state = XML_SCHEMAS_ATTR_WILD_NO_DECL;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019828 } else
Daniel Veillard3646d642004-06-02 19:19:14 +000019829 curState->state = XML_SCHEMAS_ATTR_CHECKED;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019830 }
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019831 }
Daniel Veillard3646d642004-06-02 19:19:14 +000019832 curState = curState->next;
19833 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019834 }
19835
Daniel Veillardc0826a72004-08-10 14:17:33 +000019836 if (ctxt->attr != NULL) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019837 int valueNeeded;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019838
19839 /*
19840 * Validate the value of the attribute.
19841 */
19842 if (ctxt->value != NULL) {
19843 xmlSchemaFreeValue(ctxt->value);
19844 ctxt->value = NULL;
19845 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000019846 curState = ctxt->attr;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019847 while ((curState != NULL) && (curState != ctxt->attrTop->next)) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019848 valueNeeded = 0;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019849 switch (curState->state) {
19850 case XML_SCHEMAS_ATTR_VALIDATE_VALUE:
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019851
19852 /*
19853 * Create an attribute info if needed.
19854 */
19855 if (ctxt->attrInfo == NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019856 ctxt->attrInfo = (xmlSchemaNodeInfoPtr)
19857 xmlMalloc(sizeof(xmlSchemaNodeInfo));
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019858 if (ctxt->attrInfo == NULL) {
19859 xmlSchemaVErrMemory(ctxt,
19860 "allocating an attribute info", NULL);
19861 goto fatal_exit;
19862 }
19863 }
19864 /*
19865 * Init the attribute info.
19866 */
19867 ctxt->attrInfo->flags = 0;
19868 ctxt->attrInfo->node = (xmlNodePtr) curState->attr;
19869 ctxt->attrInfo->decl = (xmlSchemaTypePtr) curState->decl;
19870 ctxt->attrInfo->value = NULL;
19871 if (curState->decl != NULL)
19872 ctxt->attrInfo->typeDef = curState->decl->subtypes;
19873 else
19874 ctxt->attrInfo->typeDef = NULL;
19875 if (curState->attr->ns != NULL)
19876 ctxt->attrInfo->namespaceName =
19877 curState->attr->ns->href;
19878 else
19879 ctxt->attrInfo->namespaceName = NULL;
19880 ctxt->attrInfo->localName = curState->attr->name;
19881
19882 ctxt->nodeInfo = ctxt->attrInfo;
19883
19884#ifdef IDC_ENABLED
19885 /*
19886 * Evaluate IDCs.
19887 */
19888 if (ctxt->xpathStates != NULL) {
19889 ret = xmlSchemaXPathEvaluate(ctxt,
19890 XML_ATTRIBUTE_NODE);
19891 if (ret == -1)
19892 goto fatal_exit;
19893 }
19894
19895#endif
19896 ret = xmlSchemaCheckAttrLocallyValid(ctxt, curState);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019897 if (ret == -1)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019898 goto fatal_exit;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019899 if ((ret != 0) && (ctxt->value != NULL)) {
19900 xmlSchemaFreeValue(ctxt->value);
19901 ctxt->value = NULL;
19902 }
19903 /* No break on purpose. */
19904 case XML_SCHEMAS_ATTR_CHECKED:
19905#ifdef IDC_ENABLED
19906 if (ctxt->xpathStates != NULL) {
19907 /*
19908 * Evaluate IDCs.
19909 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019910 if (ctxt->value != NULL) {
19911 ctxt->attrInfo->value = ctxt->value;
19912 ctxt->value = NULL;
19913 }
19914 if (xmlSchemaXPathProcessHistory(ctxt, ctxt->depth +1) == -1)
19915 goto fatal_exit;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019916 }
19917 break;
19918#endif
19919 default:
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019920 break;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019921 }
19922 curState = curState->next;
19923 }
19924
19925 /*
19926 * Report missing and illegal attributes.
19927 */
19928 curState = ctxt->attr;
19929 while ((curState != NULL) && (curState != ctxt->attrTop->next)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000019930 if (curState->state != XML_SCHEMAS_ATTR_CHECKED) {
19931 attr = curState->attr;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019932 if (curState->decl != NULL) {
19933 if (curState->decl->ref != NULL)
19934 attrDecl = curState->decl->refDecl;
19935 else
19936 attrDecl = curState->decl;
19937 } else
19938 attrDecl = NULL;
19939 if (curState->state == XML_SCHEMAS_ATTR_MISSING) {
19940 xmlSchemaVMissingAttrErr(ctxt, elem, attrDecl);
19941 } else if (curState->state ==
19942 XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED) {
19943 xmlSchemaVCustomErr(ctxt,
19944 XML_SCHEMAV_CVC_ATTRIBUTE_2,
19945 (xmlNodePtr) attr,
19946 (xmlSchemaTypePtr) attrDecl,
19947 "The type definition is absent",
19948 NULL);
19949 } else if (curState->state ==
19950 XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE) {
19951 xmlSchemaVCustomErr(ctxt,
19952 XML_SCHEMAV_CVC_AU,
19953 (xmlNodePtr) attr, (xmlSchemaTypePtr) attrDecl,
19954 "The value does not match the fixed value "
19955 "constraint", NULL);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019956 } else if (curState->state == XML_SCHEMAS_ATTR_WILD_NO_DECL) {
19957 xmlSchemaVWildcardErr(ctxt,
19958 XML_SCHEMAV_CVC_WILDCARD,
19959 (xmlNodePtr) attr,
19960 type->attributeWildcard,
19961 "No global attribute declaration found, but "
19962 "stipulated by the strict processContents of "
19963 "the wildcard");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019964 } else if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000019965 /* TODO: "prohibited" won't ever be touched here!.
19966 (curState->state == XML_SCHEMAS_ATTR_PROHIBITED))
19967 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019968 /*
19969 * TODO: One might report different error messages
19970 * for the following errors.
19971 */
19972 if ((type == NULL) || (type->attributeWildcard == NULL)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000019973 xmlSchemaVIllegalAttrErr(ctxt,
19974 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, attr);
19975 } else {
19976 xmlSchemaVIllegalAttrErr(ctxt,
19977 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, attr);
19978 }
19979 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000019980 }
19981 curState = curState->next;
19982 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019983 }
19984
19985 /*
19986 * Add missing default/fixed attributes.
19987 */
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000019988 if (defAttrStates != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019989 curState = defAttrStates;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000019990
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019991 while (curState != NULL) {
19992 attrDecl = curState->decl;
19993 if (attrDecl->ref != NULL)
19994 attrDecl = attrDecl->refDecl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019995
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000019996#ifdef IDC_ENABLED
19997 /*
19998 * Evaluate IDCs on default attributes.
19999 */
20000 if (ctxt->xpathStates != NULL) {
20001 /*
20002 * Create an attribute info if needed.
20003 */
20004 if (ctxt->attrInfo == NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020005 ctxt->attrInfo = (xmlSchemaNodeInfoPtr)
20006 xmlMalloc(sizeof(xmlSchemaNodeInfo));
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000020007 if (ctxt->attrInfo == NULL) {
20008 xmlSchemaVErrMemory(ctxt,
20009 "allocating an attribute info", NULL);
20010 goto fatal_exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020011 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020012 ctxt->attrInfo->value = NULL;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000020013 }
20014 /*
20015 * Init the attribute info.
Kasimier T. Buchcik285ebab2005-03-04 18:04:59 +000020016 * TODO: Hmm, maby a bit oversized this all.
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000020017 */
20018 ctxt->attrInfo->flags = 0;
20019 ctxt->attrInfo->decl = (xmlSchemaTypePtr) attrDecl;
20020 ctxt->attrInfo->node = NULL;
20021 ctxt->attrInfo->typeDef = attrDecl->subtypes;
20022 ctxt->attrInfo->namespaceName = attrDecl->targetNamespace;
20023 ctxt->attrInfo->localName = attrDecl->name;
20024
20025 ctxt->nodeInfo = ctxt->attrInfo;
20026
20027 ret = xmlSchemaXPathEvaluate(ctxt,
20028 XML_ATTRIBUTE_NODE);
20029 if (ret == -1)
20030 goto fatal_exit;
20031 if (ctxt->attrInfo->value != NULL) {
20032 xmlSchemaFreeValue(ctxt->attrInfo->value);
20033 ctxt->attrInfo->value = NULL;
20034 }
20035 if (ret > 0) {
Kasimier T. Buchcik285ebab2005-03-04 18:04:59 +000020036 /*
20037 * IDCs will consume the precomputed default value,
20038 * so we need to clone it somehow.
20039 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020040 /*
20041 * string or anySimpleType does not create a precomputed value
20042 * by default, so it will be created here on demand.
20043 * TODO: default/fixed attributes are a bit unoptimized:
20044 * the string value will be hold by ->defValue and inside
20045 * the precomputed value.
20046 */
20047 if (attrDecl->defVal == NULL) {
20048 xmlChar *str = xmlStrdup(attrDecl->defValue);
20049
20050 if (xmlSchemaPostCreateVal(ctxt,
20051 str,
20052 &(attrDecl->defVal)) == -1) {
20053 FREE_AND_NULL(str)
20054 goto fatal_exit;
20055 }
20056 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000020057 ctxt->attrInfo->value = xmlSchemaCopyValue(attrDecl->defVal);
20058 /* TODO: error on NULL return. */
20059 }
Kasimier T. Buchcik285ebab2005-03-04 18:04:59 +000020060
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000020061 if (xmlSchemaXPathProcessHistory(ctxt, ctxt->depth +1) == -1)
20062 goto fatal_exit;
20063 }
20064#endif
20065
20066 if (ctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
20067 /*
20068 * PSVI: Add a new attribute node to the current element.
20069 */
20070 if (attrDecl->targetNamespace == NULL) {
20071 xmlNewProp(elem, attrDecl->name, curState->value);
20072 } else {
20073 xmlNsPtr ns;
20074
20075 ns = xmlSearchNsByHref(elem->doc, elem,
20076 attrDecl->targetNamespace);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020077 if (ns == NULL) {
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000020078 xmlChar prefix[12];
20079 int counter = 1;
20080
20081 attr = curState->attr;
20082 /*
20083 * Create a namespace declaration on the validation
20084 * root node if no namespace declaration is in scope.
20085 */
20086 snprintf((char *) prefix, sizeof(prefix), "p");
20087 /*
20088 * This is somehow not performant, since the ancestor
20089 * axis beyond @elem will be searched as well.
20090 */
20091 ns = xmlSearchNs(elem->doc, elem, BAD_CAST prefix);
20092 while (ns != NULL) {
20093 if (counter > 1000) {
20094 xmlSchemaVErr(ctxt, (xmlNodePtr) attr,
20095 XML_SCHEMAV_INTERNAL,
20096 "Internal error: xmlSchemaValidateAttributes, "
20097 "could not compute a ns prefix for "
20098 "default/fixed attribute '%s'.\n",
20099 attrDecl->name, NULL);
20100
20101 break;
20102 }
20103 snprintf((char *) prefix,
20104 sizeof(prefix), "p%d", counter++);
20105 ns = xmlSearchNs(elem->doc, elem,
20106 BAD_CAST prefix);
20107 }
20108 if (ns == NULL) {
20109 ns = xmlNewNs(ctxt->validationRoot,
20110 attrDecl->targetNamespace, BAD_CAST prefix);
20111 xmlNewNsProp(elem, ns, attrDecl->name,
20112 curState->value);
20113 }
20114 } else {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020115 xmlNewNsProp(elem, ns, attrDecl->name,
20116 curState->value);
20117 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020118 }
20119 }
20120 curState = curState->next;
20121 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000020122 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020123 ret = ctxt->err;
20124 goto exit;
20125
20126fatal_exit:
20127 ret = -1;
20128
20129exit:
20130
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020131 if (defAttrStates != NULL)
20132 xmlSchemaFreeAttributeStates(defAttrStates);
20133
Daniel Veillard3646d642004-06-02 19:19:14 +000020134#ifdef DEBUG_ATTR_VALIDATION
20135 if (redundant)
20136 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020137 "xmlSchemaValidateAttributes: redundant call by "
20138 "type: %s\n", type->name);
Daniel Veillard3646d642004-06-02 19:19:14 +000020139#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020140 ctxt->nodeInfo = ctxt->elemInfos[ctxt->depth];
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020141 ctxt->node = oldnode;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020142 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000020143}
20144
20145/**
20146 * xmlSchemaValidateElement:
20147 * @ctxt: a schema validation context
20148 * @elem: an element
20149 *
20150 * Validate an element in a tree
20151 *
20152 * Returns 0 if the element is schemas valid, a positive error code
20153 * number otherwise and -1 in case of internal or API error.
20154 */
20155static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020156xmlSchemaValidateElement(xmlSchemaValidCtxtPtr ctxt)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020157{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020158 xmlSchemaElementPtr elemDecl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020159 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000020160
Daniel Veillardc0826a72004-08-10 14:17:33 +000020161 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020162 * This one is called by xmlSchemaValidateDocument and
20163 * xmlSchemaValidateOneElement.
20164 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020165 if (ctxt->schema == NULL) {
20166 /*
20167 * No schema was specified at time of creation of the validation
20168 * context. Use xsi:schemaLocation and xsi:noNamespaceSchemaLocation
20169 * of the instance to build a schema.
20170 */
20171 if (ctxt->pctxt == NULL)
20172 ctxt->pctxt = xmlSchemaNewParserCtxt("*");
20173 if (ctxt->pctxt == NULL)
20174 return (-1);
20175 ctxt->schema = xmlSchemaNewSchema(ctxt->pctxt);
20176 if (ctxt->schema == NULL)
20177 return (-1);
20178 /* TODO: assign user data. */
20179 ctxt->pctxt->error = ctxt->error;
20180 ctxt->pctxt->warning = ctxt->warning;
20181 ctxt->xsiAssemble = 1;
20182 } else
20183 ctxt->xsiAssemble = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020184 /*
20185 * Assemble new schemata using xsi.
Daniel Veillardc0826a72004-08-10 14:17:33 +000020186 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020187 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020188 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
20189 if (ret == -1) {
20190 xmlSchemaVCustomErr(ctxt,
20191 XML_SCHEMAV_INTERNAL,
20192 ctxt->node, NULL,
20193 "Internal error: xmlSchemaValidateElement, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020194 "assembling schema by xsi", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020195 }
20196 /*
20197 * NOTE: We won't react on schema parser errors here.
20198 * TODO: But a warning would be nice.
20199 */
20200 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020201 if (ret != -1) {
20202 if (ctxt->node->ns != NULL)
20203 elemDecl = xmlSchemaGetElem(ctxt->schema, ctxt->node->name,
20204 ctxt->node->ns->href);
20205 else
20206 elemDecl = xmlSchemaGetElem(ctxt->schema, ctxt->node->name, NULL);
20207
20208 if (elemDecl == NULL) {
20209 xmlSchemaVCustomErr(ctxt,
20210 XML_SCHEMAV_CVC_ELT_1,
20211 ctxt->node, NULL,
20212 "No matching global declaration available", NULL);
20213 ret = XML_SCHEMAV_CVC_ELT_1;
20214 } else {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020215#ifdef IDC_ENABLED
20216 /*
20217 * Augment the IDC definitions.
20218 */
20219 if (ctxt->schema->idcDef != NULL) {
20220 xmlHashScan(ctxt->schema->idcDef,
20221 (xmlHashScanner) xmlSchemaAugmentIDC, ctxt);
20222 }
20223#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020224#ifdef ELEM_INFO_ENABLED
20225 ctxt->depth = -1;
20226 xmlSchemaBeginElement(ctxt);
20227#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020228 ret = xmlSchemaValidateElementByDeclaration(ctxt, elemDecl);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020229#ifdef ELEM_INFO_ENABLED
20230 xmlSchemaEndElement(ctxt);
20231#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020232 if (ret < 0) {
20233 xmlSchemaVCustomErr(ctxt,
20234 XML_SCHEMAV_INTERNAL, ctxt->node, NULL,
20235 "Internal error: xmlSchemaValidateElement, "
20236 "calling validation by declaration", NULL);
20237 }
20238 }
20239 }
20240 /* ctxt->xsiAssemble = 0; */
20241 if (ctxt->xsiAssemble) {
20242 if (ctxt->schema != NULL) {
20243 xmlSchemaFree(ctxt->schema);
20244 ctxt->schema = NULL;
20245 }
Daniel Veillard4255d502002-04-16 15:50:10 +000020246 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020247 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000020248}
20249
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020250
Daniel Veillard4255d502002-04-16 15:50:10 +000020251/**
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000020252 * xmlSchemaValidateOneElement:
20253 * @ctxt: a schema validation context
20254 * @elem: an element node
20255 *
20256 * Validate a branch of a tree, starting with the given @elem.
20257 *
20258 * Returns 0 if the element and its subtree is valid, a positive error
20259 * code number otherwise and -1 in case of an internal or API error.
20260 */
20261int
20262xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
20263{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020264 if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000020265 return (-1);
20266
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020267 if (ctxt->schema == NULL) {
20268 xmlSchemaVErr(ctxt, NULL,
20269 XML_SCHEMAV_INTERNAL,
20270 "API error: xmlSchemaValidateOneElement, "
20271 "no schema specified.\n", NULL, NULL);
20272 return (-1);
20273 }
20274
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000020275 ctxt->doc = elem->doc;
20276 ctxt->err = 0;
20277 ctxt->nberrors = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020278 ctxt->node = elem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020279 ctxt->validationRoot = elem;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020280 return (xmlSchemaValidateElement(ctxt));
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000020281}
20282
20283/**
Daniel Veillard4255d502002-04-16 15:50:10 +000020284 * xmlSchemaValidateDocument:
20285 * @ctxt: a schema validation context
20286 * @doc: a parsed document tree
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020287 * @xsiAssemble: should schemata be added if requested by the instance?
Daniel Veillard4255d502002-04-16 15:50:10 +000020288 *
20289 * Validate a document tree in memory.
20290 *
20291 * Returns 0 if the document is schemas valid, a positive error code
20292 * number otherwise and -1 in case of internal or API error.
20293 */
20294static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020295xmlSchemaValidateDocument(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
20296{
Daniel Veillard4255d502002-04-16 15:50:10 +000020297 xmlNodePtr root;
Daniel Veillard01fa6152004-06-29 17:04:39 +000020298
Daniel Veillard4255d502002-04-16 15:50:10 +000020299 root = xmlDocGetRootElement(doc);
20300 if (root == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000020301 xmlSchemaVCustomErr(ctxt,
20302 XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
20303 (xmlNodePtr) doc, NULL,
20304 "The document has no document element", NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020305 return (ctxt->err);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020306 }
Daniel Veillard4255d502002-04-16 15:50:10 +000020307 /*
20308 * Okay, start the recursive validation
20309 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020310 ctxt->node = root;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020311 ctxt->validationRoot = root;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020312 xmlSchemaValidateElement(ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000020313
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020314 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000020315}
20316
20317/************************************************************************
20318 * *
20319 * SAX Validation code *
20320 * *
20321 ************************************************************************/
20322
20323/************************************************************************
20324 * *
20325 * Validation interfaces *
20326 * *
20327 ************************************************************************/
20328
20329/**
20330 * xmlSchemaNewValidCtxt:
20331 * @schema: a precompiled XML Schemas
20332 *
20333 * Create an XML Schemas validation context based on the given schema
20334 *
20335 * Returns the validation context or NULL in case of error
20336 */
20337xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020338xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
20339{
Daniel Veillard4255d502002-04-16 15:50:10 +000020340 xmlSchemaValidCtxtPtr ret;
20341
20342 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
20343 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020344 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000020345 return (NULL);
20346 }
20347 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
Daniel Veillardc0826a72004-08-10 14:17:33 +000020348 ret->schema = schema;
Daniel Veillard3646d642004-06-02 19:19:14 +000020349 ret->attrTop = NULL;
20350 ret->attr = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000020351 return (ret);
20352}
20353
20354/**
20355 * xmlSchemaFreeValidCtxt:
20356 * @ctxt: the schema validation context
20357 *
20358 * Free the resources associated to the schema validation context
20359 */
20360void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020361xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
20362{
Daniel Veillard4255d502002-04-16 15:50:10 +000020363 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020364 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000020365 if (ctxt->attr != NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000020366 xmlSchemaFreeAttributeStates(ctxt->attr);
Daniel Veillard88c58912002-04-23 07:12:20 +000020367 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020368 xmlSchemaFreeValue(ctxt->value);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020369 if (ctxt->pctxt != NULL) {
20370 xmlSchemaFreeParserCtxt(ctxt->pctxt);
20371 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020372
20373#ifdef IDC_ENABLED
20374 if (ctxt->idcNodes != NULL) {
20375 int i;
20376 xmlSchemaPSVIIDCNodePtr item;
20377
20378 for (i = 0; i < ctxt->nbIdcNodes; i++) {
20379 item = ctxt->idcNodes[i];
20380 xmlFree(item->keys);
20381 xmlFree(item);
20382 }
20383 xmlFree(ctxt->idcNodes);
20384 }
20385
20386 if (ctxt->idcKeys != NULL) {
20387 int i;
20388 for (i = 0; i < ctxt->nbIdcKeys; i++)
20389 xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
20390 xmlFree(ctxt->idcKeys);
20391 }
20392
20393 if (ctxt->xpathStates != NULL)
20394 xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
20395 if (ctxt->xpathStatePool != NULL)
20396 xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
20397
20398 /*
20399 * Augmented IDC information.
20400 */
20401 if (ctxt->aidcs != NULL) {
20402 xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
20403 do {
20404 next = cur->next;
20405 xmlFree(cur);
20406 cur = next;
20407 } while (cur != NULL);
20408 }
20409#endif /* IDC_ENABLED */
20410#ifdef ELEM_INFO_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020411 if (ctxt->attrInfo != NULL) {
20412 if (ctxt->attrInfo->value != NULL)
20413 xmlSchemaFreeValue(ctxt->attrInfo->value);
20414 xmlFree(ctxt->attrInfo);
20415 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020416 if (ctxt->elemInfos != NULL) {
20417 int i;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020418 xmlSchemaNodeInfoPtr info;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020419
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020420 for (i = 0; i < ctxt->sizeElemInfos; i++) {
20421 info = ctxt->elemInfos[i];
20422 if (info == NULL)
20423 continue;
20424 if (info->value != NULL)
20425 xmlSchemaFreeValue(info->value);
20426#ifdef IDC_ENABLED
20427 if (info->idcMatchers != NULL)
20428 xmlSchemaIDCFreeMatcherList(info->idcMatchers);
20429#endif
20430 /*
20431 * TODO: Free the IDC table if still existent.
20432 */
20433
20434 /*
20435 xmlFree(info->localName);
20436 if (info->namespaceName != NULL)
20437 xmlFree(info->namespaceName);
20438 */
20439 xmlFree(info);
20440 }
20441 xmlFree(ctxt->elemInfos);
20442 }
20443#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000020444 xmlFree(ctxt);
20445}
20446
20447/**
20448 * xmlSchemaSetValidErrors:
20449 * @ctxt: a schema validation context
20450 * @err: the error function
20451 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +000020452 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +000020453 *
William M. Brack2f2a6632004-08-20 23:09:47 +000020454 * Set the error and warning callback informations
Daniel Veillard4255d502002-04-16 15:50:10 +000020455 */
20456void
20457xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020458 xmlSchemaValidityErrorFunc err,
20459 xmlSchemaValidityWarningFunc warn, void *ctx)
20460{
Daniel Veillard4255d502002-04-16 15:50:10 +000020461 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020462 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000020463 ctxt->error = err;
20464 ctxt->warning = warn;
20465 ctxt->userData = ctx;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020466 if (ctxt->pctxt != NULL)
20467 xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
Daniel Veillard4255d502002-04-16 15:50:10 +000020468}
20469
20470/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000020471 * xmlSchemaGetValidErrors:
20472 * @ctxt: a XML-Schema validation context
20473 * @err: the error function result
20474 * @warn: the warning function result
20475 * @ctx: the functions context result
20476 *
20477 * Get the error and warning callback informations
20478 *
20479 * Returns -1 in case of error and 0 otherwise
20480 */
20481int
20482xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
20483 xmlSchemaValidityErrorFunc * err,
20484 xmlSchemaValidityWarningFunc * warn, void **ctx)
20485{
20486 if (ctxt == NULL)
20487 return (-1);
20488 if (err != NULL)
20489 *err = ctxt->error;
20490 if (warn != NULL)
20491 *warn = ctxt->warning;
20492 if (ctx != NULL)
20493 *ctx = ctxt->userData;
20494 return (0);
20495}
20496
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020497
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020498/**
Daniel Veillard6927b102004-10-27 17:29:04 +000020499 * xmlSchemaSetValidOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020500 * @ctxt: a schema validation context
20501 * @options: a combination of xmlSchemaValidOption
20502 *
20503 * Sets the options to be used during the validation.
20504 *
20505 * Returns 0 in case of success, -1 in case of an
20506 * API error.
20507 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020508int
20509xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
20510 int options)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020511
20512{
20513 int i;
20514
20515 if (ctxt == NULL)
20516 return (-1);
20517 /*
20518 * WARNING: Change the start value if adding to the
20519 * xmlSchemaValidOption.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020520 * TODO: Is there an other, more easy to maintain,
20521 * way?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020522 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020523 for (i = 1; i < (int) sizeof(int) * 8; i++) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020524 if (options & 1<<i) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020525 xmlSchemaVErr(ctxt, NULL,
20526 XML_SCHEMAV_INTERNAL,
20527 "Internal error: xmlSchemaSetValidOptions, "
20528 "invalid option argument.\n", NULL, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020529 return (-1);
20530 }
20531 }
20532 ctxt->options = options;
20533 return (0);
20534}
20535
20536/**
Daniel Veillard6927b102004-10-27 17:29:04 +000020537 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020538 * @ctxt: a schema validation context
20539 *
William M. Brack21e4ef22005-01-02 09:53:13 +000020540 * Get the validation context options.
20541 *
20542 * Returns the option combination or -1 on error.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020543 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020544int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020545xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
20546
20547{
20548 if (ctxt == NULL)
20549 return (-1);
20550 else
20551 return (ctxt->options);
20552}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020553
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020554
Daniel Veillard259f0df2004-08-18 09:13:18 +000020555/**
Daniel Veillard4255d502002-04-16 15:50:10 +000020556 * xmlSchemaValidateDoc:
20557 * @ctxt: a schema validation context
20558 * @doc: a parsed document tree
20559 *
20560 * Validate a document tree in memory.
20561 *
20562 * Returns 0 if the document is schemas valid, a positive error code
20563 * number otherwise and -1 in case of internal or API error.
20564 */
20565int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020566xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
20567{
Daniel Veillard4255d502002-04-16 15:50:10 +000020568 int ret;
20569
20570 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020571 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000020572
20573 ctxt->doc = doc;
William M. Brack2f2a6632004-08-20 23:09:47 +000020574 ctxt->err = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020575 ctxt->nberrors = 0;
20576
20577 /*
20578 if (ctxt->schema == NULL) {
20579 xmlSchemaVErr(ctxt, NULL,
20580 XML_SCHEMAV_INTERNAL,
20581 "API error: xmlSchemaValidateDoc, "
20582 "no schema specified and assembling of schemata "
20583 "using xsi:schemaLocation and xsi:noNamespaceSchemaLocation "
20584 "is not enabled.\n", NULL, NULL);
20585 return (-1);
20586 }
20587 */
Daniel Veillard4255d502002-04-16 15:50:10 +000020588 ret = xmlSchemaValidateDocument(ctxt, doc);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020589 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000020590}
20591
20592/**
20593 * xmlSchemaValidateStream:
20594 * @ctxt: a schema validation context
20595 * @input: the input to use for reading the data
20596 * @enc: an optional encoding information
20597 * @sax: a SAX handler for the resulting events
20598 * @user_data: the context to provide to the SAX handler.
20599 *
20600 * Validate a document tree in memory.
20601 *
20602 * Returns 0 if the document is schemas valid, a positive error code
20603 * number otherwise and -1 in case of internal or API error.
20604 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020605int
Daniel Veillard4255d502002-04-16 15:50:10 +000020606xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020607 xmlParserInputBufferPtr input, xmlCharEncoding enc,
20608 xmlSAXHandlerPtr sax, void *user_data)
20609{
Daniel Veillard4255d502002-04-16 15:50:10 +000020610 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020611 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000020612 ctxt->input = input;
20613 ctxt->enc = enc;
20614 ctxt->sax = sax;
20615 ctxt->user_data = user_data;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020616 TODO return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000020617}
20618
20619#endif /* LIBXML_SCHEMAS_ENABLED */