blob: a0cff137a80175b09018f8aa5526d0510398a8b1 [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;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +0000199 const xmlChar **localImports; /* list of locally imported namespaces */
200 int sizeLocalImports;
201 int nbLocalImports;
Daniel Veillard4255d502002-04-16 15:50:10 +0000202};
203
204
205#define XML_SCHEMAS_ATTR_UNKNOWN 1
206#define XML_SCHEMAS_ATTR_CHECKED 2
Daniel Veillard3646d642004-06-02 19:19:14 +0000207#define XML_SCHEMAS_ATTR_PROHIBITED 3
208#define XML_SCHEMAS_ATTR_MISSING 4
209#define XML_SCHEMAS_ATTR_INVALID_VALUE 5
210#define XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED 6
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000211#define XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE 7
212#define XML_SCHEMAS_ATTR_DEFAULT 8
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +0000213#define XML_SCHEMAS_ATTR_VALIDATE_VALUE 9
214#define XML_SCHEMAS_ATTR_WILD_NO_DECL 10
Daniel Veillard4255d502002-04-16 15:50:10 +0000215
216typedef struct _xmlSchemaAttrState xmlSchemaAttrState;
217typedef xmlSchemaAttrState *xmlSchemaAttrStatePtr;
218struct _xmlSchemaAttrState {
Daniel Veillard3646d642004-06-02 19:19:14 +0000219 xmlSchemaAttrStatePtr next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000220 xmlAttrPtr attr;
221 int state;
Daniel Veillard3646d642004-06-02 19:19:14 +0000222 xmlSchemaAttributePtr decl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000223 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000224};
225
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000226typedef struct _xmlSchemaBasicItem xmlSchemaBasicItem;
227typedef xmlSchemaBasicItem *xmlSchemaBasicItemPtr;
228struct _xmlSchemaBasicItem {
229 xmlSchemaTypeType type;
230 xmlSchemaAnnotPtr annot;
231};
232
233typedef struct _xmlSchemaItemQNRef xmlSchemaItemQNRef;
234typedef xmlSchemaItemQNRef *xmlSchemaItemQNRefPtr;
235struct _xmlSchemaItemQNRef {
236 xmlSchemaBasicItemPtr item;
237 const xmlChar *name;
238 const xmlChar *targetNamespace;
239};
240
241typedef struct _xmlSchemaIDC xmlSchemaIDC;
242typedef xmlSchemaIDC *xmlSchemaIDCPtr;
243
244/**
245 * xmlSchemaIDCSelect:
246 *
247 * The identity-constraint "field" and "selector" item, holding the
248 * XPath expression.
249 */
250typedef struct _xmlSchemaIDCSelect xmlSchemaIDCSelect;
251typedef xmlSchemaIDCSelect *xmlSchemaIDCSelectPtr;
252struct _xmlSchemaIDCSelect {
253 xmlSchemaIDCSelectPtr next;
254 xmlSchemaIDCPtr idc;
255 int index; /* an index position if significant for IDC key-sequences */
256 const xmlChar *xpath; /* the XPath expression */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000257 void *xpathComp; /* the compiled XPath expression */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000258};
259
260/**
261 * xmlSchemaIDC:
262 *
263 * The identity-constraint definition component.
264 */
265
266struct _xmlSchemaIDC {
267 xmlSchemaTypeType type;
268 xmlSchemaAnnotPtr annot;
269 xmlSchemaIDCPtr next;
270 xmlNodePtr node;
271 const xmlChar *name;
272 const xmlChar *targetNamespace;
273 xmlSchemaIDCSelectPtr selector;
274 xmlSchemaIDCSelectPtr fields;
275 int nbFields;
276 xmlSchemaItemQNRefPtr ref;
277};
278
279/**
280 * xmlSchemaIDCAug:
281 *
282 * The augmented IDC information used for validation.
283 */
284typedef struct _xmlSchemaIDCAug xmlSchemaIDCAug;
285typedef xmlSchemaIDCAug *xmlSchemaIDCAugPtr;
286struct _xmlSchemaIDCAug {
287 xmlSchemaIDCAugPtr next; /* next in a list */
288 xmlSchemaIDCPtr def; /* the IDC definition */
289 int bubbleDepth; /* the lowest level to which IDC
290 tables need to be bubbled upwards */
291};
292
293/**
294 * xmlSchemaPSVIIDCKeySequence:
295 *
296 * The key sequence of a node table item.
297 */
298typedef struct _xmlSchemaPSVIIDCKey xmlSchemaPSVIIDCKey;
299typedef xmlSchemaPSVIIDCKey *xmlSchemaPSVIIDCKeyPtr;
300struct _xmlSchemaPSVIIDCKey {
301 xmlSchemaTypePtr type;
302 xmlSchemaValPtr compValue;
303};
304
305/**
306 * xmlSchemaPSVIIDCNode:
307 *
308 * The node table item of a node table.
309 */
310typedef struct _xmlSchemaPSVIIDCNode xmlSchemaPSVIIDCNode;
311typedef xmlSchemaPSVIIDCNode *xmlSchemaPSVIIDCNodePtr;
312struct _xmlSchemaPSVIIDCNode {
313 xmlNodePtr node;
314 xmlSchemaPSVIIDCKeyPtr *keys;
315};
316
317/**
318 * xmlSchemaPSVIIDCBinding:
319 *
320 * The identity-constraint binding item of the [identity-constraint table].
321 */
322typedef struct _xmlSchemaPSVIIDCBinding xmlSchemaPSVIIDCBinding;
323typedef xmlSchemaPSVIIDCBinding *xmlSchemaPSVIIDCBindingPtr;
324struct _xmlSchemaPSVIIDCBinding {
325 xmlSchemaPSVIIDCBindingPtr next; /* next binding of a specific node */
326 xmlSchemaIDCPtr definition; /* the IDC definition */
327 xmlSchemaPSVIIDCNodePtr *nodeTable; /* array of key-sequences */
328 int nbNodes; /* number of entries in the node table */
329 int sizeNodes; /* size of the node table */
330 int nbDupls; /* number of already identified duplicates in the node
331 table */
332 /* int nbKeys; number of keys in each key-sequence */
333};
334
335#define XPATH_STATE_OBJ_TYPE_IDC_SELECTOR 1
336#define XPATH_STATE_OBJ_TYPE_IDC_FIELD 2
337
338#define XPATH_STATE_OBJ_MATCHES -2
339#define XPATH_STATE_OBJ_BLOCKED -3
340
341typedef struct _xmlSchemaIDCMatcher xmlSchemaIDCMatcher;
342typedef xmlSchemaIDCMatcher *xmlSchemaIDCMatcherPtr;
343
344/**
345 * xmlSchemaIDCStateObj:
346 *
347 * The state object used to evaluate XPath expressions.
348 */
349typedef struct _xmlSchemaIDCStateObj xmlSchemaIDCStateObj;
350typedef xmlSchemaIDCStateObj *xmlSchemaIDCStateObjPtr;
351struct _xmlSchemaIDCStateObj {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000352 int type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000353 xmlSchemaIDCStateObjPtr next; /* next if in a list */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000354 int depth; /* depth of creation */
355 int *history; /* list of (depth, state-id) tuples */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000356 int nbHistory;
357 int sizeHistory;
358 xmlSchemaIDCMatcherPtr matcher; /* the correspondent field/selector
359 matcher */
360 xmlSchemaIDCSelectPtr sel;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000361 void *xpathCtxt;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000362};
363
364#define IDC_MATCHER 0
365
366/**
367 * xmlSchemaIDCMatcher:
368 *
369 * Used to IDC selectors (and fields) successively.
370 */
371struct _xmlSchemaIDCMatcher {
372 int type;
373 int depth; /* the tree depth at creation time */
374 xmlSchemaIDCMatcherPtr next; /* next in the list */
375 xmlSchemaIDCAugPtr aidc; /* the augmented IDC item */
376 xmlSchemaPSVIIDCKeyPtr **keySeqs; /* the key-sequences of the target
377 elements */
378 int sizeKeySeqs;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000379 int targetDepth;
380};
381
382/*
383* Element info flags.
384*/
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000385#define XML_SCHEMA_ELEM_INFO_VALUE_NEEDED 1
386/* #define XML_SCHEMA_ELEM_INFO_ATTR 2 */
387/* #define XML_SCHEMA_ELEM_INFO_ELEM 4 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000388
389/**
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000390 * xmlSchemaNodeInfo:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000391 *
392 * Holds information of an element node.
393 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000394typedef struct _xmlSchemaNodeInfo xmlSchemaNodeInfo;
395typedef xmlSchemaNodeInfo *xmlSchemaNodeInfoPtr;
396struct _xmlSchemaNodeInfo {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000397 int depth;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000398 int flags; /* combination of node info flags */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000399 xmlNodePtr node;
400 const xmlChar *localName;
401 const xmlChar *namespaceName;
402 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +0000403 xmlSchemaTypePtr decl; /* the element/attribute declaration */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000404 xmlSchemaValPtr value; /* the pre-computed value if any */
405 xmlSchemaPSVIIDCBindingPtr idcTable; /* the table of PSVI IDC bindings
406 for the scope element*/
407 xmlSchemaIDCMatcherPtr idcMatchers; /* the IDC matchers for the scope
408 element */
409};
410
Daniel Veillard4255d502002-04-16 15:50:10 +0000411/**
412 * xmlSchemaValidCtxt:
413 *
414 * A Schemas validation context
415 */
416
417struct _xmlSchemaValidCtxt {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000418 void *userData; /* user specific data block */
419 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000420 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000421 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000422
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000423 xmlSchemaPtr schema; /* The schema in use */
424 xmlDocPtr doc;
Daniel Veillard4255d502002-04-16 15:50:10 +0000425 xmlParserInputBufferPtr input;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000426 xmlCharEncoding enc;
427 xmlSAXHandlerPtr sax;
428 void *user_data;
Daniel Veillard4255d502002-04-16 15:50:10 +0000429
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000430 xmlDocPtr myDoc;
431 int err;
432 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +0000433
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000434 xmlNodePtr node;
435 xmlNodePtr cur;
436 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +0000437
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000438 xmlRegExecCtxtPtr regexp;
439 xmlSchemaValPtr value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000440
Daniel Veillard3646d642004-06-02 19:19:14 +0000441 xmlSchemaAttrStatePtr attrTop;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000442 xmlSchemaAttrStatePtr attr;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000443 /* xmlNodePtr scope; not used */
Daniel Veillardc0826a72004-08-10 14:17:33 +0000444 int valueWS;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000445 int options;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000446 xmlNodePtr validationRoot;
447 xmlSchemaParserCtxtPtr pctxt;
448 int xsiAssemble;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000449#ifdef ELEM_INFO_ENABLED
450 int depth;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000451 xmlSchemaNodeInfoPtr *elemInfos; /* array of element informations */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000452 int sizeElemInfos;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000453 xmlSchemaNodeInfoPtr nodeInfo; /* the current element information */
454 xmlSchemaNodeInfoPtr attrInfo; /* node infor for the current attribute */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000455#endif
456#ifdef IDC_ENABLED
457 xmlSchemaIDCAugPtr aidcs; /* a list of augmented IDC informations */
458
459 xmlSchemaIDCStateObjPtr xpathStates; /* first active state object. */
460 xmlSchemaIDCStateObjPtr xpathStatePool; /* first stored state object. */
461
462 xmlSchemaPSVIIDCNodePtr *idcNodes; /* list of all IDC node-table entries*/
463 int nbIdcNodes;
464 int sizeIdcNodes;
465
466 xmlSchemaPSVIIDCKeyPtr *idcKeys; /* list of all IDC node-table entries */
467 int nbIdcKeys;
468 int sizeIdcKeys;
469#endif
Daniel Veillard4255d502002-04-16 15:50:10 +0000470};
471
Daniel Veillard1d913862003-11-21 00:28:39 +0000472/*
473 * These are the entries in the schemas importSchemas hash table
474 */
475typedef struct _xmlSchemaImport xmlSchemaImport;
476typedef xmlSchemaImport *xmlSchemaImportPtr;
477struct _xmlSchemaImport {
478 const xmlChar *schemaLocation;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000479 xmlSchemaPtr schema; /* not used any more */
William M. Brack2f2a6632004-08-20 23:09:47 +0000480 xmlDocPtr doc;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000481 int isMain;
Daniel Veillard1d913862003-11-21 00:28:39 +0000482};
Daniel Veillard4255d502002-04-16 15:50:10 +0000483
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000484/*
485 * These are the entries associated to includes in a schemas
486 */
487typedef struct _xmlSchemaInclude xmlSchemaInclude;
488typedef xmlSchemaInclude *xmlSchemaIncludePtr;
489struct _xmlSchemaInclude {
490 xmlSchemaIncludePtr next;
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000491 const xmlChar *schemaLocation;
492 xmlDocPtr doc;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +0000493 const xmlChar *origTargetNamespace;
494 const xmlChar *targetNamespace;
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000495};
496
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000497typedef struct _xmlSchemaParticle xmlSchemaParticle;
498typedef xmlSchemaParticle *xmlSchemaParticlePtr;
499struct _xmlSchemaParticle {
500 xmlSchemaTypeType type;
501 xmlSchemaParticlePtr next; /* the next particle if in a list */
502 int minOccurs;
503 int maxOccurs;
504 xmlSchemaTypePtr term;
505};
506
507
508typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup;
509typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr;
510struct _xmlSchemaModelGroup {
511 xmlSchemaTypeType type;
512 int compositor; /* one of all, choice or sequence */
513 xmlSchemaParticlePtr particles; /* list of particles */
514 xmlSchemaAnnotPtr annot;
515};
516
517typedef struct _xmlSchemaModelGroupDef xmlSchemaModelGroupDef;
518typedef xmlSchemaModelGroupDef *xmlSchemaModelGroupDefPtr;
519struct _xmlSchemaModelGroupDef {
520 xmlSchemaTypeType type;
521 const xmlChar *name;
522 const xmlChar *targetNamespace;
523 xmlSchemaModelGroupPtr modelGroup;
524 xmlSchemaAnnotPtr annot;
525};
526
Daniel Veillard4255d502002-04-16 15:50:10 +0000527/************************************************************************
528 * *
529 * Some predeclarations *
530 * *
531 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000532
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000533static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
534 xmlSchemaPtr schema,
535 xmlNodePtr node);
Daniel Veillard01fa6152004-06-29 17:04:39 +0000536static void
537xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
538 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +0000539static const xmlChar *
Daniel Veillard01fa6152004-06-29 17:04:39 +0000540xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
541static int
542xmlSchemaValidateSimpleTypeValue(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000543 xmlSchemaTypePtr type,
Daniel Veillard01fa6152004-06-29 17:04:39 +0000544 const xmlChar *value,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000545 int fireErrors,
Daniel Veillardc0826a72004-08-10 14:17:33 +0000546 int applyFacets,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000547 int normalize,
548 int checkNodes);
549static int
550xmlSchemaValidateElementByDeclaration(xmlSchemaValidCtxtPtr ctxt,
551 xmlSchemaElementPtr elemDecl);
552static int
553xmlSchemaValidateElementByWildcard(xmlSchemaValidCtxtPtr ctxt,
554 xmlSchemaTypePtr type);
555static int
556xmlSchemaHasElemOrCharContent(xmlNodePtr node);
William M. Brack2f2a6632004-08-20 23:09:47 +0000557static int
558xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
559 xmlNodePtr node);
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +0000560static void
561xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
562 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +0000563static void
564xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt);
William M. Brack87640d52004-04-17 14:58:15 +0000565
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000566/************************************************************************
567 * *
568 * Datatype error handlers *
569 * *
570 ************************************************************************/
571
572/**
573 * xmlSchemaPErrMemory:
574 * @node: a context node
575 * @extra: extra informations
576 *
577 * Handle an out of memory condition
578 */
579static void
580xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
581 const char *extra, xmlNodePtr node)
582{
583 if (ctxt != NULL)
584 ctxt->nberrors++;
585 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
586 extra);
587}
588
589/**
590 * xmlSchemaPErr:
591 * @ctxt: the parsing context
592 * @node: the context node
593 * @error: the error code
594 * @msg: the error message
595 * @str1: extra data
596 * @str2: extra data
597 *
598 * Handle a parser error
599 */
600static void
601xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
602 const char *msg, const xmlChar * str1, const xmlChar * str2)
603{
604 xmlGenericErrorFunc channel = NULL;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000605 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000606 void *data = NULL;
607
608 if (ctxt != NULL) {
609 ctxt->nberrors++;
610 channel = ctxt->error;
611 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000612 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000613 }
Daniel Veillard659e71e2003-10-10 14:10:40 +0000614 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000615 error, XML_ERR_ERROR, NULL, 0,
616 (const char *) str1, (const char *) str2, NULL, 0, 0,
617 msg, str1, str2);
618}
619
620/**
621 * xmlSchemaPErr2:
622 * @ctxt: the parsing context
623 * @node: the context node
624 * @node: the current child
625 * @error: the error code
626 * @msg: the error message
627 * @str1: extra data
628 * @str2: extra data
629 *
630 * Handle a parser error
631 */
632static void
633xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
634 xmlNodePtr child, int error,
635 const char *msg, const xmlChar * str1, const xmlChar * str2)
636{
637 if (child != NULL)
638 xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
639 else
640 xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
641}
642
Daniel Veillard01fa6152004-06-29 17:04:39 +0000643
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000644/**
Daniel Veillard3646d642004-06-02 19:19:14 +0000645 * xmlSchemaPErrExt:
646 * @ctxt: the parsing context
647 * @node: the context node
648 * @error: the error code
649 * @strData1: extra data
650 * @strData2: extra data
651 * @strData3: extra data
652 * @msg: the message
653 * @str1: extra parameter for the message display
654 * @str2: extra parameter for the message display
655 * @str3: extra parameter for the message display
656 * @str4: extra parameter for the message display
657 * @str5: extra parameter for the message display
658 *
659 * Handle a parser error
660 */
661static void
662xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
663 const xmlChar * strData1, const xmlChar * strData2,
664 const xmlChar * strData3, const char *msg, const xmlChar * str1,
665 const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
666 const xmlChar * str5)
667{
668
669 xmlGenericErrorFunc channel = NULL;
670 xmlStructuredErrorFunc schannel = NULL;
671 void *data = NULL;
672
673 if (ctxt != NULL) {
674 ctxt->nberrors++;
675 channel = ctxt->error;
676 data = ctxt->userData;
677 schannel = ctxt->serror;
678 }
679 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
680 error, XML_ERR_ERROR, NULL, 0,
681 (const char *) strData1, (const char *) strData2,
William M. Brack803812b2004-06-03 02:11:24 +0000682 (const char *) strData3, 0, 0, msg, str1, str2,
683 str3, str4, str5);
Daniel Veillard3646d642004-06-02 19:19:14 +0000684}
Daniel Veillard01fa6152004-06-29 17:04:39 +0000685
Daniel Veillard3646d642004-06-02 19:19:14 +0000686
687/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000688 * xmlSchemaVTypeErrMemory:
689 * @node: a context node
690 * @extra: extra informations
691 *
692 * Handle an out of memory condition
693 */
694static void
695xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
696 const char *extra, xmlNodePtr node)
697{
698 if (ctxt != NULL) {
699 ctxt->nberrors++;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000700 ctxt->err = XML_SCHEMAV_INTERNAL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000701 }
702 __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
703 extra);
704}
705
706/**
707 * xmlSchemaVErr3:
708 * @ctxt: the validation context
709 * @node: the context node
710 * @error: the error code
711 * @msg: the error message
712 * @str1: extra data
713 * @str2: extra data
714 * @str3: extra data
715 *
716 * Handle a validation error
717 */
718static void
719xmlSchemaVErr3(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
720 const char *msg, const xmlChar *str1, const xmlChar *str2,
721 const xmlChar *str3)
722{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000723 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000724 xmlGenericErrorFunc channel = NULL;
725 void *data = NULL;
726
727 if (ctxt != NULL) {
728 ctxt->nberrors++;
729 ctxt->err = error;
730 channel = ctxt->error;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000731 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000732 data = ctxt->userData;
733 }
734 /* reajust to global error numbers */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000735 /* Removed, since the old schema error codes have been
736 * substituted for the global error codes.
737 *
738 * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
739 */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000740 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000741 error, XML_ERR_ERROR, NULL, 0,
742 (const char *) str1, (const char *) str2,
743 (const char *) str3, 0, 0,
744 msg, str1, str2, str3);
745}
Daniel Veillardc0826a72004-08-10 14:17:33 +0000746
747/**
748 * xmlSchemaVErrExt:
749 * @ctxt: the validation context
750 * @node: the context node
751 * @error: the error code
752 * @msg: the message
753 * @str1: extra parameter for the message display
754 * @str2: extra parameter for the message display
755 * @str3: extra parameter for the message display
756 * @str4: extra parameter for the message display
757 * @str5: extra parameter for the message display
758 *
759 * Handle a validation error
760 */
761static void
762xmlSchemaVErrExt(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
763 const char *msg, const xmlChar * str1,
764 const xmlChar * str2, const xmlChar * str3,
765 const xmlChar * str4, const xmlChar * str5)
766{
767 xmlStructuredErrorFunc schannel = NULL;
768 xmlGenericErrorFunc channel = NULL;
769 void *data = NULL;
770
771 if (ctxt != NULL) {
772 ctxt->nberrors++;
773 ctxt->err = error;
774 channel = ctxt->error;
775 schannel = ctxt->serror;
776 data = ctxt->userData;
777 }
778 /* reajust to global error numbers */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000779 /* Removed, since the old schema error codes have been
780 * substituted for the global error codes.
781 *
782 * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
783 */
Daniel Veillardc0826a72004-08-10 14:17:33 +0000784 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
785 error, XML_ERR_ERROR, NULL, 0, NULL, NULL, NULL, 0, 0,
786 msg, str1, str2, str3, str4, str5);
787}
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000788/**
789 * xmlSchemaVErr:
790 * @ctxt: the validation context
791 * @node: the context node
792 * @error: the error code
793 * @msg: the error message
794 * @str1: extra data
795 * @str2: extra data
796 *
797 * Handle a validation error
798 */
799static void
800xmlSchemaVErr(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
801 const char *msg, const xmlChar * str1, const xmlChar * str2)
802{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000803 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000804 xmlGenericErrorFunc channel = NULL;
805 void *data = NULL;
806
807 if (ctxt != NULL) {
808 ctxt->nberrors++;
809 ctxt->err = error;
810 channel = ctxt->error;
811 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000812 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000813 }
814 /* reajust to global error numbers */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000815 /* Removed, since the old schema error codes have been
816 * substituted for the global error codes.
817 *
818 * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
819 */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000820 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000821 error, XML_ERR_ERROR, NULL, 0,
822 (const char *) str1, (const char *) str2, NULL, 0, 0,
823 msg, str1, str2);
824}
Daniel Veillard4255d502002-04-16 15:50:10 +0000825
Daniel Veillardc0826a72004-08-10 14:17:33 +0000826/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000827 * xmlSchemaGetAttrName:
Daniel Veillardc0826a72004-08-10 14:17:33 +0000828 * @attr: the attribute declaration/use
829 *
830 * Returns the name of the attribute; if the attribute
831 * is a reference, the name of the referenced global type will be returned.
832 */
833static const xmlChar *
834xmlSchemaGetAttrName(xmlSchemaAttributePtr attr)
835{
836 if (attr->ref != NULL)
837 return(attr->ref);
838 else
839 return(attr->name);
840}
841
842/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000843 * xmlSchemaGetAttrTargetNsURI:
Daniel Veillardc0826a72004-08-10 14:17:33 +0000844 * @type: the type (element or attribute)
845 *
846 * Returns the target namespace URI of the type; if the type is a reference,
847 * the target namespace of the referenced type will be returned.
848 */
849static const xmlChar *
850xmlSchemaGetAttrTargetNsURI(xmlSchemaAttributePtr attr)
851{
852 if (attr->ref != NULL)
853 return (attr->refNs);
854 else
855 return(attr->targetNamespace);
856}
857
858/**
859 * xmlSchemaFormatNsUriLocal:
860 * @buf: the string buffer
861 * @uri: the namespace URI
862 * @local: the local name
863 *
864 * Returns a representation of the given URI used
865 * for error reports.
866 *
867 * Returns an empty string, if @ns is NULL, a formatted
868 * string otherwise.
869 */
870static const xmlChar*
871xmlSchemaFormatNsUriLocal(xmlChar **buf,
872 const xmlChar *uri, const xmlChar *local)
873{
874 if (*buf != NULL)
875 xmlFree(*buf);
876 if (uri == NULL) {
877 *buf = xmlStrdup(BAD_CAST "{'");
878 *buf = xmlStrcat(*buf, local);
879 } else {
880 *buf = xmlStrdup(BAD_CAST "{'");
881 *buf = xmlStrcat(*buf, uri);
882 *buf = xmlStrcat(*buf, BAD_CAST "', '");
883 *buf = xmlStrcat(*buf, local);
884 }
885 *buf = xmlStrcat(*buf, BAD_CAST "'}");
886 return ((const xmlChar *) *buf);
887}
888
889/**
890 * xmlSchemaFormatNsPrefixLocal:
891 * @buf: the string buffer
892 * @ns: the namespace
893 * @local: the local name
894 *
895 * Returns a representation of the given URI used
896 * for error reports.
897 *
898 * Returns an empty string, if @ns is NULL, a formatted
899 * string otherwise.
900 */
901static const xmlChar*
902xmlSchemaFormatNsPrefixLocal(xmlChar **buf,
903 xmlNsPtr ns, const xmlChar *local)
904{
905 if (*buf != NULL) {
906 xmlFree(*buf);
907 *buf = NULL;
908 }
909 if ((ns == NULL) || (ns->prefix == NULL))
910 return(local);
911 else {
912 *buf = xmlStrdup(ns->prefix);
913 *buf = xmlStrcat(*buf, BAD_CAST ":");
914 *buf = xmlStrcat(*buf, local);
915 }
916 return ((const xmlChar *) *buf);
917}
918
919/**
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000920 * xmlSchemaFormatQName:
921 * @buf: the string buffer
922 * @namespaceName: the namespace name
923 * @localName: the local name
924 *
925 * Returns the given QName in the format "{namespaceName}localName" or
926 * just "localName" if @namespaceName is NULL.
927 *
928 * Returns the localName if @namespaceName is NULL, a formatted
929 * string otherwise.
930 */
931static const xmlChar*
932xmlSchemaFormatQName(xmlChar **buf,
933 const xmlChar *namespaceName,
934 const xmlChar *localName)
935{
936 FREE_AND_NULL(*buf)
937 if (namespaceName == NULL)
938 return(localName);
939
940 *buf = xmlStrdup(BAD_CAST "{");
941 *buf = xmlStrcat(*buf, namespaceName);
942 *buf = xmlStrcat(*buf, BAD_CAST "}");
943 *buf = xmlStrcat(*buf, localName);
944
945 return ((const xmlChar *) *buf);
946}
947
948/**
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +0000949 * xmlSchemaWildcardPCToString:
950 * @pc: the type of processContents
951 *
952 * Returns a string representation of the type of
953 * processContents.
954 */
955static const xmlChar *
956xmlSchemaWildcardPCToString(int pc)
957{
958 switch (pc) {
959 case XML_SCHEMAS_ANY_SKIP:
960 return (BAD_CAST "skip");
961 case XML_SCHEMAS_ANY_LAX:
962 return (BAD_CAST "lax");
963 case XML_SCHEMAS_ANY_STRICT:
964 return (BAD_CAST "strict");
965 default:
966 return (BAD_CAST "invalid process contents");
967 }
968}
969
970/**
Daniel Veillardc0826a72004-08-10 14:17:33 +0000971 * xmlSchemaFormatItemForReport:
972 * @buf: the string buffer
973 * @itemDes: the designation of the item
974 * @itemName: the name of the item
975 * @item: the item as an object
976 * @itemNode: the node of the item
977 * @local: the local name
978 * @parsing: if the function is used during the parse
979 *
980 * Returns a representation of the given item used
981 * for error reports.
982 *
983 * The following order is used to build the resulting
984 * designation if the arguments are not NULL:
985 * 1a. If itemDes not NULL -> itemDes
986 * 1b. If (itemDes not NULL) and (itemName not NULL)
987 * -> itemDes + itemName
988 * 2. If the preceding was NULL and (item not NULL) -> item
989 * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
990 *
991 * If the itemNode is an attribute node, the name of the attribute
992 * will be appended to the result.
993 *
994 * Returns the formatted string and sets @buf to the resulting value.
995 */
996static xmlChar*
997xmlSchemaFormatItemForReport(xmlChar **buf,
998 const xmlChar *itemDes,
999 xmlSchemaTypePtr item,
1000 xmlNodePtr itemNode,
1001 int parsing)
1002{
1003 xmlChar *str = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00001004 int named = 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001005
1006 if (*buf != NULL) {
1007 xmlFree(*buf);
1008 *buf = NULL;
1009 }
1010
William M. Brack2f2a6632004-08-20 23:09:47 +00001011 if (itemDes != NULL) {
1012 *buf = xmlStrdup(itemDes);
1013 } else if (item != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001014 switch (item->type) {
1015 case XML_SCHEMA_TYPE_BASIC:
Daniel Veillardc0826a72004-08-10 14:17:33 +00001016 if (item->builtInType == XML_SCHEMAS_ANYTYPE)
1017 *buf = xmlStrdup(BAD_CAST "'anyType'");
1018 else if (item->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)
1019 *buf = xmlStrdup(BAD_CAST "'anySimpleType'");
1020 else {
1021 /* *buf = xmlStrdup(BAD_CAST "bi "); */
1022 /* *buf = xmlStrcat(*buf, xmlSchemaElemDesST); */
1023 *buf = xmlStrdup(BAD_CAST "'");
1024 *buf = xmlStrcat(*buf, item->name);
1025 *buf = xmlStrcat(*buf, BAD_CAST "'");
1026 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001027 break;
1028 case XML_SCHEMA_TYPE_SIMPLE:
Daniel Veillardc0826a72004-08-10 14:17:33 +00001029 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1030 *buf = xmlStrdup(xmlSchemaElemDesST);
1031 *buf = xmlStrcat(*buf, BAD_CAST " '");
1032 *buf = xmlStrcat(*buf, item->name);
1033 *buf = xmlStrcat(*buf, BAD_CAST "'");
1034 } else {
1035 *buf = xmlStrdup(xmlSchemaElemDesST);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001036 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001037 break;
1038 case XML_SCHEMA_TYPE_COMPLEX:
Daniel Veillardc0826a72004-08-10 14:17:33 +00001039 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1040 *buf = xmlStrdup(xmlSchemaElemDesCT);
1041 *buf = xmlStrcat(*buf, BAD_CAST " '");
1042 *buf = xmlStrcat(*buf, item->name);
1043 *buf = xmlStrcat(*buf, BAD_CAST "'");
1044 } else {
1045 *buf = xmlStrdup(xmlSchemaElemDesCT);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001046 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001047 break;
1048 case XML_SCHEMA_TYPE_ATTRIBUTE: {
1049 xmlSchemaAttributePtr attr;
1050
1051 attr = (xmlSchemaAttributePtr) item;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001052 if ((attr->flags & XML_SCHEMAS_ATTR_GLOBAL) ||
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001053 (attr->ref == NULL)) {
1054 *buf = xmlStrdup(xmlSchemaElemDesAttrDecl);
1055 *buf = xmlStrcat(*buf, BAD_CAST " '");
1056 *buf = xmlStrcat(*buf, attr->name);
1057 *buf = xmlStrcat(*buf, BAD_CAST "'");
1058 } else {
1059 *buf = xmlStrdup(xmlSchemaElemDesAttrRef);
1060 *buf = xmlStrcat(*buf, BAD_CAST " '");
1061 *buf = xmlStrcat(*buf, attr->refPrefix);
1062 *buf = xmlStrcat(*buf, BAD_CAST ":");
1063 *buf = xmlStrcat(*buf, attr->ref);
1064 *buf = xmlStrcat(*buf, BAD_CAST "'");
1065 }
1066 }
1067 break;
1068 case XML_SCHEMA_TYPE_ELEMENT: {
1069 xmlSchemaElementPtr elem;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001070
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001071 elem = (xmlSchemaElementPtr) item;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001072 if ((elem->flags & XML_SCHEMAS_ELEM_GLOBAL) ||
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001073 (elem->ref == NULL)) {
1074 *buf = xmlStrdup(xmlSchemaElemDesElemDecl);
1075 *buf = xmlStrcat(*buf, BAD_CAST " '");
1076 *buf = xmlStrcat(*buf, elem->name);
1077 *buf = xmlStrcat(*buf, BAD_CAST "'");
1078 } else {
1079 *buf = xmlStrdup(xmlSchemaElemDesElemRef);
1080 *buf = xmlStrcat(*buf, BAD_CAST " '");
1081 *buf = xmlStrcat(*buf, elem->refPrefix);
1082 *buf = xmlStrcat(*buf, BAD_CAST ":");
1083 *buf = xmlStrcat(*buf, elem->ref);
1084 *buf = xmlStrcat(*buf, BAD_CAST "'");
1085 }
1086 }
1087 break;
1088 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1089 case XML_SCHEMA_TYPE_IDC_KEY:
1090 case XML_SCHEMA_TYPE_IDC_KEYREF:
1091 if (item->type == XML_SCHEMA_TYPE_IDC_UNIQUE)
1092 *buf = xmlStrdup(BAD_CAST "unique '");
1093 else if (item->type == XML_SCHEMA_TYPE_IDC_KEY)
1094 *buf = xmlStrdup(BAD_CAST "key '");
1095 else
1096 *buf = xmlStrdup(BAD_CAST "keyRef '");
1097 *buf = xmlStrcat(*buf, ((xmlSchemaIDCPtr) item)->name);
1098 *buf = xmlStrcat(*buf, BAD_CAST "'");
1099 break;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00001100 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001101 *buf = xmlStrdup(xmlSchemaWildcardPCToString(
1102 ((xmlSchemaWildcardPtr) item)->processContents));
1103 *buf = xmlStrcat(*buf, BAD_CAST " wildcard");
1104 break;
1105 case XML_SCHEMA_FACET_MININCLUSIVE:
1106 case XML_SCHEMA_FACET_MINEXCLUSIVE:
1107 case XML_SCHEMA_FACET_MAXINCLUSIVE:
1108 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
1109 case XML_SCHEMA_FACET_TOTALDIGITS:
1110 case XML_SCHEMA_FACET_FRACTIONDIGITS:
1111 case XML_SCHEMA_FACET_PATTERN:
1112 case XML_SCHEMA_FACET_ENUMERATION:
1113 case XML_SCHEMA_FACET_WHITESPACE:
1114 case XML_SCHEMA_FACET_LENGTH:
1115 case XML_SCHEMA_FACET_MAXLENGTH:
1116 case XML_SCHEMA_FACET_MINLENGTH:
1117 *buf = xmlStrdup(BAD_CAST "facet '");
1118 *buf = xmlStrcat(*buf, xmlSchemaFacetTypeToString(item->type));
1119 *buf = xmlStrcat(*buf, BAD_CAST "'");
1120 break;
1121 case XML_SCHEMA_TYPE_NOTATION:
1122 *buf = xmlStrdup(BAD_CAST "notation");
1123 break;
1124 case XML_SCHEMA_TYPE_GROUP:
1125 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1126 *buf = xmlStrdup(xmlSchemaElemModelGrDef);
1127 *buf = xmlStrcat(*buf, BAD_CAST " '");
1128 *buf = xmlStrcat(*buf, item->name);
1129 *buf = xmlStrcat(*buf, BAD_CAST "'");
1130 } else {
1131 *buf = xmlStrdup(xmlSchemaElemModelGrRef);
1132 *buf = xmlStrcat(*buf, BAD_CAST " '");
1133 *buf = xmlStrcat(*buf, item->ref);
1134 *buf = xmlStrcat(*buf, BAD_CAST "'");
1135 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00001136 break;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001137 default:
William M. Brack2f2a6632004-08-20 23:09:47 +00001138 named = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001139 }
William M. Brack2f2a6632004-08-20 23:09:47 +00001140 } else
1141 named = 0;
1142
1143 if ((named == 0) && (itemNode != NULL)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00001144 xmlNodePtr elem;
1145
1146 if (itemNode->type == XML_ATTRIBUTE_NODE)
1147 elem = itemNode->parent;
1148 else
1149 elem = itemNode;
1150 *buf = xmlStrdup(BAD_CAST "Element '");
1151 if (parsing)
1152 *buf = xmlStrcat(*buf, elem->name);
1153 else
1154 *buf = xmlStrcat(*buf,
1155 xmlSchemaFormatNsPrefixLocal(&str, elem->ns, elem->name));
1156 *buf = xmlStrcat(*buf, BAD_CAST "'");
1157 }
1158 if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
1159 *buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
1160 *buf = xmlStrcat(*buf, xmlSchemaFormatNsPrefixLocal(&str,
1161 itemNode->ns, itemNode->name));
1162 *buf = xmlStrcat(*buf, BAD_CAST "'");
1163 }
1164 FREE_AND_NULL(str);
1165
1166 return (*buf);
1167}
1168
1169/**
1170 * xmlSchemaPFormatItemDes:
1171 * @buf: the string buffer
1172 * @item: the item as a schema object
1173 * @itemNode: the item as a node
1174 *
1175 * If the pointer to @buf is not NULL and @but holds no value,
1176 * the value is set to a item designation using
1177 * xmlSchemaFormatItemForReport. This one avoids adding
1178 * an attribute designation postfix.
1179 *
1180 * Returns a string of all enumeration elements.
1181 */
1182static void
1183xmlSchemaPRequestItemDes(xmlChar **buf,
1184 xmlSchemaTypePtr item,
1185 xmlNodePtr itemNode)
1186{
1187 if ((buf == 0) || (*buf != NULL))
1188 return;
1189 if (itemNode->type == XML_ATTRIBUTE_NODE)
1190 itemNode = itemNode->parent;
1191 xmlSchemaFormatItemForReport(buf, NULL, item, itemNode, 1);
1192}
1193
1194/**
1195 * xmlSchemaFormatFacetEnumSet:
1196 * @buf: the string buffer
1197 * @type: the type holding the enumeration facets
1198 *
1199 * Builds a string consisting of all enumeration elements.
1200 *
1201 * Returns a string of all enumeration elements.
1202 */
1203static const xmlChar *
1204xmlSchemaFormatFacetEnumSet(xmlChar **buf, xmlSchemaTypePtr type)
1205{
1206 xmlSchemaFacetLinkPtr link;
1207
1208 if (*buf != NULL)
1209 xmlFree(*buf);
1210 *buf = NULL;
1211 for (link = type->facetSet; link != NULL; link = link->next) {
1212 if (link->facet->type == XML_SCHEMA_FACET_ENUMERATION) {
1213 if (*buf == NULL) {
1214 *buf = xmlStrdup(BAD_CAST "'");
1215 *buf = xmlStrcat(*buf, link->facet->value);
1216 *buf = xmlStrcat(*buf, BAD_CAST "'");
1217 } else {
1218 *buf = xmlStrcat(*buf, BAD_CAST ", '");
1219 *buf = xmlStrcat(*buf, link->facet->value);
1220 *buf = xmlStrcat(*buf, BAD_CAST "'");
1221 }
1222 }
1223 }
1224 return ((const xmlChar *) *buf);
1225}
1226
1227/**
1228 * xmlSchemaVFacetErr:
1229 * @ctxt: the schema validation context
1230 * @error: the error code
1231 * @node: the node to be validated
1232 * @value: the value of the node
1233 * @type: the type holding the facet
1234 * @facet: the facet
1235 * @message: the error message of NULL
1236 * @str1: extra data
1237 * @str2: extra data
1238 * @str3: extra data
1239 *
1240 * Reports a facet validation error.
1241 * TODO: Should this report the value of an element as well?
1242 */
1243static void
1244xmlSchemaVFacetErr(xmlSchemaValidCtxtPtr ctxt,
1245 xmlParserErrors error,
1246 xmlNodePtr node,
1247 const xmlChar *value,
1248 unsigned long length,
1249 xmlSchemaTypePtr type,
1250 xmlSchemaFacetPtr facet,
1251 const char *message,
1252 const xmlChar *str1,
1253 const xmlChar *str2,
1254 const xmlChar *str3)
1255{
1256 xmlChar *str = NULL, *msg = NULL;
1257 xmlSchemaTypeType facetType;
1258
1259 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
1260 msg = xmlStrcat(msg, BAD_CAST " [");
1261 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1262 msg = xmlStrcat(msg, BAD_CAST ", facet '");
1263 if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
1264 facetType = XML_SCHEMA_FACET_ENUMERATION;
1265 /*
1266 * If enumerations are validated, one must not expect the
1267 * facet to be given.
1268 */
1269 } else
1270 facetType = facet->type;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001271 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facetType));
Daniel Veillardc0826a72004-08-10 14:17:33 +00001272 msg = xmlStrcat(msg, BAD_CAST "']: ");
1273 if (message == NULL) {
1274 /*
1275 * Use a default message.
1276 */
1277 if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
1278 (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
1279 (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
1280
1281 char len[25], actLen[25];
1282
1283 /* FIXME, TODO: What is the max expected string length of the
1284 * this value?
1285 */
1286 if (node->type == XML_ATTRIBUTE_NODE)
1287 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
1288 else
1289 msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
1290
1291 snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
1292 snprintf(actLen, 24, "%lu", length);
1293
1294 if (facetType == XML_SCHEMA_FACET_LENGTH)
1295 msg = xmlStrcat(msg,
1296 BAD_CAST "this differs from the allowed length of '%s'.\n");
1297 else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
1298 msg = xmlStrcat(msg,
1299 BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
1300 else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
1301 msg = xmlStrcat(msg,
1302 BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
1303
1304 if (node->type == XML_ATTRIBUTE_NODE)
1305 xmlSchemaVErrExt(ctxt, node, error,
1306 (const char *) msg,
1307 value, (const xmlChar *) actLen, (const xmlChar *) len,
1308 NULL, NULL);
1309 else
1310 xmlSchemaVErr(ctxt, node, error,
1311 (const char *) msg,
1312 (const xmlChar *) actLen, (const xmlChar *) len);
1313
1314 } else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
1315 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
1316 "of the set {%s}.\n");
1317 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
1318 xmlSchemaFormatFacetEnumSet(&str, type));
1319 } else if (facetType == XML_SCHEMA_FACET_PATTERN) {
1320 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
1321 "by the pattern '%s'.\n");
1322 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
1323 facet->value);
1324 } else if (node->type == XML_ATTRIBUTE_NODE) {
1325 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
1326 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value, NULL);
1327 } else {
1328 msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
1329 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
1330 }
1331 } else {
1332 msg = xmlStrcat(msg, (const xmlChar *) message);
1333 msg = xmlStrcat(msg, BAD_CAST ".\n");
1334 xmlSchemaVErr3(ctxt, node, error, (const char *) msg, str1, str2, str3);
1335 }
1336 FREE_AND_NULL(str)
1337 xmlFree(msg);
1338}
1339
1340/**
1341 * xmlSchemaVSimpleTypeErr:
1342 * @ctxt: the schema validation context
1343 * @error: the error code
1344 * @type: the type used for validation
1345 * @node: the node containing the validated value
1346 * @value: the validated value
1347 *
1348 * Reports a simple type validation error.
1349 * TODO: Should this report the value of an element as well?
1350 */
1351static void
1352xmlSchemaVSimpleTypeErr(xmlSchemaValidCtxtPtr ctxt,
1353 xmlParserErrors error,
1354 xmlNodePtr node,
1355 const xmlChar *value,
1356 xmlSchemaTypePtr type)
1357{
1358 xmlChar *str = NULL, *msg = NULL;
1359
1360 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
1361 msg = xmlStrcat(msg, BAD_CAST " [");
1362 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1363 if (node->type == XML_ATTRIBUTE_NODE) {
1364 msg = xmlStrcat(msg, BAD_CAST "]: The value '%s' is not valid.\n");
1365 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value, NULL);
1366 } else {
1367 msg = xmlStrcat(msg, BAD_CAST "]: The character content is not valid.\n");
1368 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
1369 }
1370 FREE_AND_NULL(str)
1371 xmlFree(msg);
1372}
1373
1374/**
William M. Brack2f2a6632004-08-20 23:09:47 +00001375 * xmlSchemaVComplexTypeErr:
1376 * @ctxt: the schema validation context
1377 * @error: the error code
1378 * @node: the node containing the validated value
1379 * @type: the complex type used for validation
1380 * @message: the error message
1381 *
1382 * Reports a complex type validation error.
1383 */
1384static void
1385xmlSchemaVComplexTypeErr(xmlSchemaValidCtxtPtr ctxt,
1386 xmlParserErrors error,
1387 xmlNodePtr node,
1388 xmlSchemaTypePtr type,
1389 const char *message)
1390{
1391 xmlChar *str = NULL, *msg = NULL;
1392
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00001393 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00001394 /* Specify the complex type only if it is global. */
1395 if ((type != NULL) && (type->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00001396 msg = xmlStrcat(msg, BAD_CAST " [");
1397 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1398 msg = xmlStrcat(msg, BAD_CAST "]");
1399 }
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001400 msg = xmlStrcat(msg, BAD_CAST ": %s.\n");
1401 xmlSchemaVErr(ctxt, node, error, (const char *) msg,
William M. Brack2f2a6632004-08-20 23:09:47 +00001402 (const xmlChar *) message, NULL);
1403 FREE_AND_NULL(str)
1404 xmlFree(msg);
1405}
1406
1407/**
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001408 * xmlSchemaVComplexTypeElemErr:
1409 * @ctxt: the schema validation context
1410 * @error: the error code
1411 * @node: the node containing the validated value
1412 * @type: the complex type used for validation
1413 * @message: the error message
1414 *
1415 * Reports a complex type validation error.
1416 */
1417static void
1418xmlSchemaVComplexTypeElemErr(xmlSchemaValidCtxtPtr ctxt,
1419 xmlParserErrors error,
1420 xmlNodePtr node,
1421 xmlSchemaTypePtr type,
1422 const char *message,
1423 int nbval,
1424 int nbneg,
1425 xmlChar **values)
1426{
1427 xmlChar *str = NULL, *msg = NULL;
1428 xmlChar *localName, *nsName;
1429 const xmlChar *cur, *end;
1430 int i;
1431
1432 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
1433 /* Specify the complex type only if it is global. */
1434 if ((type != NULL) && (type->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
1435 msg = xmlStrcat(msg, BAD_CAST " [");
1436 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1437 msg = xmlStrcat(msg, BAD_CAST "]");
1438 FREE_AND_NULL(str)
1439 }
1440 msg = xmlStrcat(msg, BAD_CAST ": ");
1441 msg = xmlStrcat(msg, (const xmlChar *) message);
1442 /*
1443 * Note that is does not make sense to report that we have a
1444 * wildcard here, since the wildcard might be unfolded into
1445 * multiple transitions.
1446 */
1447 if (nbval + nbneg > 0) {
1448 if (nbval + nbneg > 1) {
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00001449 str = xmlStrdup(BAD_CAST ". Expected is one of ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001450 } else
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00001451 str = xmlStrdup(BAD_CAST ". Expected is ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001452 nsName = NULL;
1453
1454 for (i = 0; i < nbval + nbneg; i++) {
1455 cur = values[i];
1456 /*
1457 * Get the local name.
1458 */
1459 localName = NULL;
1460
1461 end = cur;
1462 if (*end == '*') {
1463 localName = xmlStrdup(BAD_CAST "*");
1464 *end++;
1465 } else {
1466 while ((*end != 0) && (*end != '|'))
1467 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001468 localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001469 }
1470 if (*end != 0) {
1471 *end++;
1472 /*
1473 * Skip "*|*" if they come with negated expressions, since
1474 * they represent the same negated wildcard.
1475 */
1476 if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
1477 /*
1478 * Get the namespace name.
1479 */
1480 cur = end;
1481 if (*end == '*') {
1482 nsName = xmlStrdup(BAD_CAST "{*}");
1483 } else {
1484 while (*end != 0)
1485 end++;
1486
1487 if (i >= nbval)
1488 nsName = xmlStrdup(BAD_CAST "{##other:");
1489 else
1490 nsName = xmlStrdup(BAD_CAST "{");
1491
1492 nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
1493 nsName = xmlStrcat(nsName, BAD_CAST "}");
1494 }
1495 str = xmlStrcat(str, BAD_CAST nsName);
1496 FREE_AND_NULL(nsName)
1497 } else {
1498 FREE_AND_NULL(localName);
1499 continue;
1500 }
1501 }
1502 str = xmlStrcat(str, BAD_CAST localName);
1503 FREE_AND_NULL(localName);
1504
1505 if (i < nbval + nbneg -1)
1506 str = xmlStrcat(str, BAD_CAST ", ");
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00001507 }
1508 str = xmlStrcat(str, BAD_CAST " )");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001509 msg = xmlStrcat(msg, BAD_CAST str);
1510 FREE_AND_NULL(str)
1511 }
1512 msg = xmlStrcat(msg, BAD_CAST ".\n");
1513 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
1514 xmlFree(msg);
1515}
1516
1517/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00001518 * xmlSchemaPMissingAttrErr:
1519 * @ctxt: the schema validation context
1520 * @ownerDes: the designation of the owner
1521 * @ownerName: the name of the owner
1522 * @ownerItem: the owner as a schema object
1523 * @ownerElem: the owner as an element node
1524 * @node: the parent element node of the missing attribute node
1525 * @type: the corresponding type of the attribute node
1526 *
1527 * Reports an illegal attribute.
1528 */
1529static void
1530xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
1531 xmlParserErrors error,
1532 xmlChar **ownerDes,
1533 xmlSchemaTypePtr ownerItem,
1534 xmlNodePtr ownerElem,
1535 const char *name,
1536 const char *message)
1537{
1538 xmlChar *des = NULL;
1539
1540 if (ownerDes == NULL)
1541 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
1542 else if (*ownerDes == NULL) {
1543 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
1544 des = *ownerDes;
1545 } else
1546 des = *ownerDes;
1547 if (message != NULL)
1548 xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
1549 else
1550 xmlSchemaPErr(ctxt, ownerElem, error,
1551 "%s: The attribute '%s' is required but missing.\n",
1552 BAD_CAST des, BAD_CAST name);
1553 if (ownerDes == NULL)
1554 FREE_AND_NULL(des);
1555}
1556
William M. Brack2f2a6632004-08-20 23:09:47 +00001557/**
1558 * xmlSchemaCompTypeToString:
1559 * @type: the type of the schema item
1560 *
1561 * Returns the component name of a schema item.
1562 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001563static const char *
1564xmlSchemaCompTypeToString(xmlSchemaTypeType type)
1565{
1566 switch (type) {
1567 case XML_SCHEMA_TYPE_SIMPLE:
1568 return("simple type definition");
1569 case XML_SCHEMA_TYPE_COMPLEX:
1570 return("complex type definition");
1571 case XML_SCHEMA_TYPE_ELEMENT:
1572 return("element declaration");
1573 case XML_SCHEMA_TYPE_ATTRIBUTE:
1574 return("attribute declaration");
1575 case XML_SCHEMA_TYPE_GROUP:
1576 return("model group definition");
1577 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1578 return("attribute group definition");
1579 case XML_SCHEMA_TYPE_NOTATION:
1580 return("notation declaration");
1581 default:
1582 return("Not a schema component");
1583 }
1584}
1585/**
1586 * xmlSchemaPResCompAttrErr:
1587 * @ctxt: the schema validation context
1588 * @error: the error code
1589 * @ownerDes: the designation of the owner
1590 * @ownerItem: the owner as a schema object
1591 * @ownerElem: the owner as an element node
1592 * @name: the name of the attribute holding the QName
1593 * @refName: the referenced local name
1594 * @refURI: the referenced namespace URI
1595 * @message: optional message
1596 *
1597 * Used to report QName attribute values that failed to resolve
1598 * to schema components.
1599 */
1600static void
1601xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
1602 xmlParserErrors error,
1603 xmlChar **ownerDes,
1604 xmlSchemaTypePtr ownerItem,
1605 xmlNodePtr ownerElem,
1606 const char *name,
1607 const xmlChar *refName,
1608 const xmlChar *refURI,
1609 xmlSchemaTypeType refType,
1610 const char *refTypeStr)
1611{
1612 xmlChar *des = NULL, *strA = NULL;
1613
1614 if (ownerDes == NULL)
1615 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
1616 else if (*ownerDes == NULL) {
1617 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
1618 des = *ownerDes;
1619 } else
1620 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001621 if (refTypeStr == NULL)
1622 refTypeStr = xmlSchemaCompTypeToString(refType);
1623 xmlSchemaPErrExt(ctxt, ownerElem, error,
1624 NULL, NULL, NULL,
1625 "%s, attribute '%s': The QName value %s does not resolve to a(n) "
1626 "%s.\n", BAD_CAST des, BAD_CAST name,
1627 xmlSchemaFormatNsUriLocal(&strA, refURI, refName),
1628 BAD_CAST refTypeStr, NULL);
1629 if (ownerDes == NULL)
1630 FREE_AND_NULL(des)
1631 FREE_AND_NULL(strA)
1632}
1633
William M. Brack2f2a6632004-08-20 23:09:47 +00001634/**
1635 * xmlSchemaPCustomAttrErr:
1636 * @ctxt: the schema parser context
1637 * @error: the error code
1638 * @ownerDes: the designation of the owner
1639 * @ownerItem: the owner as a schema object
1640 * @attr: the illegal attribute node
1641 *
1642 * Reports an illegal attribute during the parse.
1643 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001644static void
1645xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00001646 xmlParserErrors error,
1647 xmlChar **ownerDes,
1648 xmlSchemaTypePtr ownerItem,
1649 xmlAttrPtr attr,
1650 const char *msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001651{
1652 xmlChar *des = NULL;
1653
1654 if (ownerDes == NULL)
1655 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
1656 else if (*ownerDes == NULL) {
1657 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
1658 des = *ownerDes;
1659 } else
1660 des = *ownerDes;
1661 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
1662 "%s, attribute '%s': %s.\n",
1663 BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
1664 if (ownerDes == NULL)
1665 FREE_AND_NULL(des);
1666}
1667
1668/**
1669 * xmlSchemaPIllegalAttrErr:
William M. Brack2f2a6632004-08-20 23:09:47 +00001670 * @ctxt: the schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00001671 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00001672 * @ownerDes: the designation of the attribute's owner
1673 * @ownerItem: the attribute's owner item
Daniel Veillardc0826a72004-08-10 14:17:33 +00001674 * @attr: the illegal attribute node
1675 *
William M. Brack2f2a6632004-08-20 23:09:47 +00001676 * Reports an illegal attribute during the parse.
Daniel Veillardc0826a72004-08-10 14:17:33 +00001677 */
1678static void
1679xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
1680 xmlParserErrors error,
1681 xmlChar **ownerDes,
1682 xmlSchemaTypePtr ownerItem,
1683 xmlAttrPtr attr)
1684{
1685 xmlChar *des = NULL, *strA = NULL;
1686
1687 if (ownerDes == NULL)
1688 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
1689 else if (*ownerDes == NULL) {
1690 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
1691 des = *ownerDes;
1692 } else
1693 des = *ownerDes;
1694 xmlSchemaPErr(ctxt, (xmlNodePtr) attr, error,
1695 "%s: The attribute '%s' is not allowed.\n", BAD_CAST des,
1696 xmlSchemaFormatNsPrefixLocal(&strA, attr->ns, attr->name));
1697 if (ownerDes == NULL)
1698 FREE_AND_NULL(des);
1699 FREE_AND_NULL(strA);
1700}
1701
William M. Brack2f2a6632004-08-20 23:09:47 +00001702/**
1703 * xmlSchemaPAquireDes:
1704 * @des: the first designation
1705 * @itemDes: the second designation
1706 * @item: the schema item
1707 * @itemElem: the node of the schema item
1708 *
1709 * Creates a designation for an item.
1710 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001711static void
1712xmlSchemaPAquireDes(xmlChar **des,
1713 xmlChar **itemDes,
1714 xmlSchemaTypePtr item,
1715 xmlNodePtr itemElem)
1716{
1717 if (itemDes == NULL)
1718 xmlSchemaFormatItemForReport(des, NULL, item, itemElem, 1);
1719 else if (*itemDes == NULL) {
1720 xmlSchemaFormatItemForReport(itemDes, NULL, item, itemElem, 1);
1721 *des = *itemDes;
1722 } else
1723 *des = *itemDes;
1724}
1725
William M. Brack2f2a6632004-08-20 23:09:47 +00001726/**
1727 * xmlSchemaPCustomErr:
1728 * @ctxt: the schema parser context
1729 * @error: the error code
1730 * @itemDes: the designation of the schema item
1731 * @item: the schema item
1732 * @itemElem: the node of the schema item
1733 * @message: the error message
1734 * @str1: an optional param for the error message
1735 * @str2: an optional param for the error message
1736 * @str3: an optional param for the error message
1737 *
1738 * Reports an error during parsing.
1739 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001740static void
1741xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
1742 xmlParserErrors error,
1743 xmlChar **itemDes,
1744 xmlSchemaTypePtr item,
1745 xmlNodePtr itemElem,
1746 const char *message,
1747 const xmlChar *str1,
1748 const xmlChar *str2,
1749 const xmlChar *str3)
1750{
1751 xmlChar *des = NULL, *msg = NULL;
1752
1753 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
1754 msg = xmlStrdup(BAD_CAST "%s: ");
1755 msg = xmlStrcat(msg, (const xmlChar *) message);
1756 msg = xmlStrcat(msg, BAD_CAST ".\n");
1757 if ((itemElem == NULL) && (item != NULL))
1758 itemElem = item->node;
1759 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
1760 (const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
1761 if (itemDes == NULL)
1762 FREE_AND_NULL(des);
1763 FREE_AND_NULL(msg);
1764}
1765
William M. Brack2f2a6632004-08-20 23:09:47 +00001766/**
1767 * xmlSchemaPCustomErr:
1768 * @ctxt: the schema parser context
1769 * @error: the error code
1770 * @itemDes: the designation of the schema item
1771 * @item: the schema item
1772 * @itemElem: the node of the schema item
1773 * @message: the error message
1774 * @str1: the optional param for the error message
1775 *
1776 * Reports an error during parsing.
1777 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001778static void
1779xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
1780 xmlParserErrors error,
1781 xmlChar **itemDes,
1782 xmlSchemaTypePtr item,
1783 xmlNodePtr itemElem,
1784 const char *message,
1785 const xmlChar *str1)
1786{
1787 xmlSchemaPCustomErrExt(ctxt, error, itemDes, item, itemElem, message,
1788 str1, NULL, NULL);
1789}
1790
William M. Brack2f2a6632004-08-20 23:09:47 +00001791/**
1792 * xmlSchemaPAttrUseErr:
1793 * @ctxt: the schema parser context
1794 * @error: the error code
1795 * @itemDes: the designation of the schema type
1796 * @item: the schema type
1797 * @itemElem: the node of the schema type
1798 * @attr: the invalid schema attribute
1799 * @message: the error message
1800 * @str1: the optional param for the error message
1801 *
1802 * Reports an attribute use error during parsing.
1803 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001804static void
1805xmlSchemaPAttrUseErr(xmlSchemaParserCtxtPtr ctxt,
1806 xmlParserErrors error,
1807 xmlChar **itemDes,
1808 xmlSchemaTypePtr item,
1809 xmlNodePtr itemElem,
1810 const xmlSchemaAttributePtr attr,
1811 const char *message,
1812 const xmlChar *str1)
1813{
1814 xmlChar *des = NULL, *strA = NULL, *msg = NULL;
1815
1816 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
1817 xmlSchemaFormatNsUriLocal(&strA, xmlSchemaGetAttrTargetNsURI(attr),
1818 xmlSchemaGetAttrName(attr));
1819 msg = xmlStrdup(BAD_CAST "%s, attr. use %s: ");
1820 msg = xmlStrcat(msg, (const xmlChar *) message);
1821 msg = xmlStrcat(msg, BAD_CAST ".\n");
1822 if ((itemElem == NULL) && (item != NULL))
1823 itemElem = item->node;
1824 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
1825 (const char *) msg, BAD_CAST des, BAD_CAST strA, str1, NULL, NULL);
1826 if (itemDes == NULL)
1827 FREE_AND_NULL(des);
1828 FREE_AND_NULL(strA);
1829 xmlFree(msg);
1830}
1831
William M. Brack2f2a6632004-08-20 23:09:47 +00001832/**
1833 * xmlSchemaPIllegalFacetAtomicErr:
1834 * @ctxt: the schema parser context
1835 * @error: the error code
1836 * @itemDes: the designation of the type
1837 * @item: the schema type
1838 * @baseItem: the base type of type
1839 * @facet: the illegal facet
1840 *
1841 * Reports an illegal facet for atomic simple types.
1842 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001843static void
1844xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
1845 xmlParserErrors error,
1846 xmlChar **itemDes,
1847 xmlSchemaTypePtr item,
1848 xmlSchemaTypePtr baseItem,
1849 xmlSchemaFacetPtr facet)
1850{
1851 xmlChar *des = NULL, *strT = NULL;
1852
1853 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
1854 xmlSchemaPErrExt(ctxt, item->node, error, NULL, NULL, NULL,
1855 "%s: The facet '%s' is not allowed on types derived from the "
1856 "type %s.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001857 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type),
Daniel Veillardc0826a72004-08-10 14:17:33 +00001858 xmlSchemaFormatItemForReport(&strT, NULL, baseItem, NULL, 1),
1859 NULL, NULL);
1860 if (itemDes == NULL)
1861 FREE_AND_NULL(des);
1862 FREE_AND_NULL(strT);
1863}
1864
William M. Brack2f2a6632004-08-20 23:09:47 +00001865/**
1866 * xmlSchemaPIllegalFacetListUnionErr:
1867 * @ctxt: the schema parser context
1868 * @error: the error code
1869 * @itemDes: the designation of the schema item involved
1870 * @item: the schema item involved
1871 * @facet: the illegal facet
1872 *
1873 * Reports an illegal facet for <list> and <union>.
1874 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001875static void
1876xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
1877 xmlParserErrors error,
1878 xmlChar **itemDes,
1879 xmlSchemaTypePtr item,
1880 xmlSchemaFacetPtr facet)
1881{
1882 xmlChar *des = NULL, *strT = NULL;
1883
1884 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
1885 xmlSchemaPErr(ctxt, item->node, error,
1886 "%s: The facet '%s' is not allowed.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001887 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +00001888 if (itemDes == NULL)
1889 FREE_AND_NULL(des);
1890 FREE_AND_NULL(strT);
1891}
1892
1893/**
1894 * xmlSchemaPMutualExclAttrErr:
1895 * @ctxt: the schema validation context
1896 * @error: the error code
1897 * @elemDes: the designation of the parent element node
1898 * @attr: the bad attribute node
1899 * @type: the corresponding type of the attribute node
1900 *
1901 * Reports an illegal attribute.
1902 */
1903static void
1904xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
1905 xmlParserErrors error,
1906 xmlChar **ownerDes,
1907 xmlSchemaTypePtr ownerItem,
1908 xmlAttrPtr attr,
1909 const char *name1,
1910 const char *name2)
1911{
1912 xmlChar *des = NULL;
1913
1914 if (ownerDes == NULL)
1915 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
1916 else if (*ownerDes == NULL) {
1917 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
1918 des = *ownerDes;
1919 } else
1920 des = *ownerDes;
1921 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
1922 "%s: The attributes '%s' and '%s' are mutually exclusive.\n",
1923 BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
1924 if (ownerDes == NULL)
1925 FREE_AND_NULL(des)
1926}
1927
1928/**
1929 * xmlSchemaPSimpleTypeErr:
1930 * @ctxt: the schema validation context
1931 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00001932 * @type: the type specifier
Daniel Veillardc0826a72004-08-10 14:17:33 +00001933 * @ownerDes: the designation of the owner
1934 * @ownerItem: the schema object if existent
1935 * @node: the validated node
1936 * @value: the validated value
1937 *
1938 * Reports a simple type validation error.
1939 * TODO: Should this report the value of an element as well?
1940 */
1941static void
1942xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
1943 xmlParserErrors error,
1944 xmlChar **ownerDes,
1945 xmlSchemaTypePtr ownerItem,
1946 xmlNodePtr node,
William M. Brack2f2a6632004-08-20 23:09:47 +00001947 xmlSchemaTypePtr type,
Daniel Veillardc0826a72004-08-10 14:17:33 +00001948 const char *typeDes,
1949 const xmlChar *value,
1950 const char *message,
1951 const xmlChar *str1,
1952 const xmlChar *str2)
1953{
William M. Brack2f2a6632004-08-20 23:09:47 +00001954 xmlChar *des = NULL, *strA = NULL, *strT = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001955
1956 if (ownerDes == NULL)
1957 xmlSchemaPRequestItemDes(&des, ownerItem, node);
1958 else if (*ownerDes == NULL) {
1959 xmlSchemaPRequestItemDes(ownerDes, ownerItem, node);
1960 des = *ownerDes;
1961 } else
1962 des = *ownerDes;
William M. Brack2f2a6632004-08-20 23:09:47 +00001963 if (type != NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001964 typeDes = (const char *) xmlSchemaFormatItemForReport(&strT, NULL, type, NULL, 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001965 if (message == NULL) {
1966 /*
1967 * Use default messages.
1968 */
1969 if (node->type == XML_ATTRIBUTE_NODE) {
1970 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
1971 "%s, attribute '%s' [%s]: The value '%s' is not "
1972 "valid.\n",
1973 BAD_CAST des, xmlSchemaFormatNsPrefixLocal(&strA, node->ns,
1974 node->name), BAD_CAST typeDes, value, NULL);
1975 } else {
1976 xmlSchemaPErr(ctxt, node, error,
1977 "%s [%s]: The character content is not valid.\n",
1978 BAD_CAST des, BAD_CAST typeDes);
1979 }
1980 } else {
1981 xmlChar *msg;
1982
1983 msg = xmlStrdup(BAD_CAST "%s");
1984 if (node->type == XML_ATTRIBUTE_NODE)
1985 msg = xmlStrcat(msg, BAD_CAST ", attribute '%s'");
1986 msg = xmlStrcat(msg, BAD_CAST " [%s]: ");
1987 msg = xmlStrcat(msg, (const xmlChar *) message);
1988 msg = xmlStrcat(msg, BAD_CAST ".\n");
1989 if (node->type == XML_ATTRIBUTE_NODE) {
1990 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
1991 (const char *) msg,
1992 BAD_CAST des, xmlSchemaFormatNsPrefixLocal(&strA,
1993 node->ns, node->name), BAD_CAST typeDes, str1, str2);
1994 } else {
1995 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
1996 (const char *) msg,
1997 BAD_CAST des, BAD_CAST typeDes, str1, str2, NULL);
1998 }
1999 xmlFree(msg);
2000 }
2001 /* Cleanup. */
2002 FREE_AND_NULL(strA)
2003 FREE_AND_NULL(strT)
2004 if (ownerDes == NULL)
2005 FREE_AND_NULL(des)
2006}
2007
William M. Brack2f2a6632004-08-20 23:09:47 +00002008/**
2009 * xmlSchemaPContentErr:
2010 * @ctxt: the schema parser context
2011 * @error: the error code
2012 * @onwerDes: the designation of the holder of the content
2013 * @ownerItem: the owner item of the holder of the content
2014 * @ownerElem: the node of the holder of the content
2015 * @child: the invalid child node
2016 * @message: the optional error message
2017 * @content: the optional string describing the correct content
2018 *
2019 * Reports an error concerning the content of a schema element.
2020 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002021static void
2022xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
2023 xmlParserErrors error,
2024 xmlChar **ownerDes,
2025 xmlSchemaTypePtr ownerItem,
2026 xmlNodePtr ownerElem,
2027 xmlNodePtr child,
2028 const char *message,
2029 const char *content)
2030{
2031 xmlChar *des = NULL;
2032
2033 if (ownerDes == NULL)
2034 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
2035 else if (*ownerDes == NULL) {
2036 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
2037 des = *ownerDes;
2038 } else
2039 des = *ownerDes;
2040 if (message != NULL)
2041 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2042 "%s: %s.\n",
2043 BAD_CAST des, BAD_CAST message);
2044 else {
2045 if (content != NULL) {
2046 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2047 "%s: The content is not valid. Expected is %s.\n",
2048 BAD_CAST des, BAD_CAST content);
2049 } else {
2050 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2051 "%s: The content is not valid.\n",
2052 BAD_CAST des, NULL);
2053 }
2054 }
2055 if (ownerDes == NULL)
2056 FREE_AND_NULL(des)
2057}
2058
2059/**
2060 * xmlSchemaVIllegalAttrErr:
2061 * @ctxt: the schema validation context
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002062 * @error: the error code
Daniel Veillardc0826a72004-08-10 14:17:33 +00002063 * @attr: the illegal attribute node
2064 *
2065 * Reports an illegal attribute.
2066 */
2067static void
2068xmlSchemaVIllegalAttrErr(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002069 xmlParserErrors error,
William M. Brack2f2a6632004-08-20 23:09:47 +00002070 xmlAttrPtr attr)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002071{
2072 xmlChar *strE = NULL, *strA = NULL;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002073
2074 xmlSchemaVErr(ctxt, (xmlNodePtr) attr,
2075 error,
2076 /* XML_SCHEMAS_ERR_ATTRUNKNOWN, */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002077 "%s: The attribute '%s' is not allowed.\n",
2078 xmlSchemaFormatItemForReport(&strE, NULL, NULL, attr->parent, 0),
2079 xmlSchemaFormatNsPrefixLocal(&strA, attr->ns, attr->name));
2080 FREE_AND_NULL(strE)
2081 FREE_AND_NULL(strA)
2082}
2083
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002084
2085static int
2086xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
2087{
2088 switch (item->type) {
2089 case XML_SCHEMA_TYPE_COMPLEX:
2090 case XML_SCHEMA_TYPE_SIMPLE:
2091 case XML_SCHEMA_TYPE_GROUP:
2092 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
2093 return(1);
2094 break;
2095 case XML_SCHEMA_TYPE_ELEMENT:
2096 if ( ((xmlSchemaElementPtr) item)->flags &
2097 XML_SCHEMAS_ELEM_GLOBAL)
2098 return(1);
2099 break;
2100 case XML_SCHEMA_TYPE_ATTRIBUTE:
2101 if ( ((xmlSchemaAttributePtr) item)->flags &
2102 XML_SCHEMAS_ATTR_GLOBAL)
2103 return(1);
2104 break;
2105 /* Note that attribute groups are always global. */
2106 default:
2107 return(1);
2108 }
2109 return (0);
2110}
2111
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002112
2113static void
2114xmlSchemaStreamVCustomErr(xmlSchemaValidCtxtPtr vctxt,
2115 xmlParserErrors error,
2116 xmlSchemaNodeInfoPtr nodeInfo,
2117 xmlSchemaTypePtr type,
2118 const char *message,
2119 const xmlChar *str1,
2120 const xmlChar *str2)
2121{
2122 xmlChar *msg = NULL, *str = NULL;
2123
2124 msg = xmlStrdup(BAD_CAST "Element '");
2125
2126 if (vctxt->elemInfos[vctxt->depth] != nodeInfo) {
2127 xmlSchemaNodeInfoPtr elemInfo;
2128 /*
2129 * The node info is an attribute info.
2130 */
2131 elemInfo = vctxt->elemInfos[vctxt->depth];
2132 msg = xmlStrcat(msg, xmlSchemaFormatQName(&str,
2133 elemInfo->namespaceName, elemInfo->localName));
2134 msg = xmlStrcat(msg, BAD_CAST "', ");
2135 msg = xmlStrcat(msg, BAD_CAST "attribute '");
2136 }
2137 msg = xmlStrcat(msg, xmlSchemaFormatQName(&str,
2138 nodeInfo->namespaceName, nodeInfo->localName));
2139 msg = xmlStrcat(msg, BAD_CAST "'");
2140
2141 if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
2142 msg = xmlStrcat(msg, BAD_CAST " [");
2143 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str,
2144 NULL, type, NULL, 0));
2145 msg = xmlStrcat(msg, BAD_CAST "]");
2146 }
2147 msg = xmlStrcat(msg, BAD_CAST ": ");
2148
2149 msg = xmlStrcat(msg, (const xmlChar *) message);
2150 msg = xmlStrcat(msg, BAD_CAST ".\n");
2151 xmlSchemaVErr(vctxt, nodeInfo->node, error, (const char *) msg,
2152 str1, str2);
2153 FREE_AND_NULL(msg)
2154 FREE_AND_NULL(str)
2155}
2156
William M. Brack2f2a6632004-08-20 23:09:47 +00002157/**
2158 * xmlSchemaVCustomErr:
2159 * @ctxt: the schema validation context
2160 * @error: the error code
2161 * @node: the validated node
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002162 * @type: the schema type of the validated node
William M. Brack2f2a6632004-08-20 23:09:47 +00002163 * @message: the error message
2164 * @str1: the optional param for the message
2165 *
2166 * Reports a validation error.
2167 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002168static void
2169xmlSchemaVCustomErr(xmlSchemaValidCtxtPtr ctxt,
2170 xmlParserErrors error,
2171 xmlNodePtr node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002172 xmlSchemaTypePtr type,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002173 const char *message,
2174 const xmlChar *str1)
2175{
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002176 xmlChar *msg = NULL, *str = NULL;
2177
2178 if (node == NULL) {
2179 xmlSchemaVErr(ctxt, NULL,
2180 XML_SCHEMAV_INTERNAL,
2181 "Internal error: xmlSchemaVCustomErr, no node "
2182 "given.\n", NULL, NULL);
2183 return;
2184 }
2185 /* TODO: Are the HTML and DOCB doc nodes expected here? */
2186 if (node->type != XML_DOCUMENT_NODE) {
2187 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002188 if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002189 msg = xmlStrcat(msg, BAD_CAST " [");
2190 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
2191 msg = xmlStrcat(msg, BAD_CAST "]");
2192 }
2193 msg = xmlStrcat(msg, BAD_CAST ": ");
2194 } else
2195 msg = xmlStrdup((const xmlChar *) "");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002196 msg = xmlStrcat(msg, (const xmlChar *) message);
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002197 msg = xmlStrcat(msg, BAD_CAST ".\n");
2198 xmlSchemaVErr(ctxt, node, error, (const char *) msg, str1, NULL);
2199 FREE_AND_NULL(msg)
2200 FREE_AND_NULL(str)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002201}
2202
William M. Brack2f2a6632004-08-20 23:09:47 +00002203/**
William M. Brack2f2a6632004-08-20 23:09:47 +00002204 * xmlSchemaVWildcardErr:
2205 * @ctxt: the schema validation context
2206 * @error: the error code
2207 * @node: the validated node
2208 * @wild: the wildcard used
2209 * @message: the error message
2210 *
2211 * Reports an validation-by-wildcard error.
2212 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002213static void
2214xmlSchemaVWildcardErr(xmlSchemaValidCtxtPtr ctxt,
2215 xmlParserErrors error,
2216 xmlNodePtr node,
2217 xmlSchemaWildcardPtr wild,
2218 const char *message)
2219{
2220 xmlChar *des = NULL, *msg = NULL;
2221
2222 xmlSchemaFormatItemForReport(&des, NULL, NULL, node, 0);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00002223 msg = xmlStrdup(BAD_CAST "%s [");
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00002224 msg = xmlStrcat(msg, xmlSchemaWildcardPCToString(wild->processContents));
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002225 msg = xmlStrcat(msg, BAD_CAST " wildcard]: ");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002226 msg = xmlStrcat(msg, (const xmlChar *) message);
2227 msg = xmlStrcat(msg, BAD_CAST ".\n");
2228 xmlSchemaVErr(ctxt, node, error, (const char *) msg, BAD_CAST des, NULL);
2229 FREE_AND_NULL(des);
2230 FREE_AND_NULL(msg);
2231}
2232
2233/**
2234 * xmlSchemaVMissingAttrErr:
2235 * @ctxt: the schema validation context
2236 * @node: the parent element node of the missing attribute node
2237 * @type: the corresponding type of the attribute node
2238 *
2239 * Reports an illegal attribute.
2240 */
2241static void
2242xmlSchemaVMissingAttrErr(xmlSchemaValidCtxtPtr ctxt,
2243 xmlNodePtr elem,
2244 xmlSchemaAttributePtr type)
2245{
2246 const xmlChar *name, *uri;
2247 xmlChar *strE = NULL, *strA = NULL;
2248
2249 if (type->ref != NULL) {
2250 name = type->ref;
2251 uri = type->refNs;
2252 } else {
2253 name = type->name;
2254 uri = type->targetNamespace;
2255 }
2256 xmlSchemaVErr(ctxt, elem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002257 XML_SCHEMAV_CVC_COMPLEX_TYPE_4,
2258 /* XML_SCHEMAS_ERR_MISSING, */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002259 "%s: The attribute %s is required but missing.\n",
2260 xmlSchemaFormatItemForReport(&strE, NULL, NULL, elem, 0),
2261 xmlSchemaFormatNsUriLocal(&strA, uri, name));
2262 FREE_AND_NULL(strE)
2263 FREE_AND_NULL(strA)
2264}
2265
Daniel Veillard4255d502002-04-16 15:50:10 +00002266/************************************************************************
2267 * *
2268 * Allocation functions *
2269 * *
2270 ************************************************************************/
2271
2272/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002273 * xmlSchemaNewSchemaForParserCtxt:
William M. Brack08171912003-12-29 02:52:11 +00002274 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00002275 *
2276 * Allocate a new Schema structure.
2277 *
2278 * Returns the newly allocated structure or NULL in case or error
2279 */
2280static xmlSchemaPtr
2281xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
2282{
2283 xmlSchemaPtr ret;
2284
2285 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
2286 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002287 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002288 return (NULL);
2289 }
2290 memset(ret, 0, sizeof(xmlSchema));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002291 ret->dict = ctxt->dict;
Daniel Veillard500a1de2004-03-22 15:22:58 +00002292 xmlDictReference(ret->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00002293
2294 return (ret);
2295}
2296
2297/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002298 * xmlSchemaNewSchema:
2299 * @ctxt: a schema validation context
2300 *
2301 * Allocate a new Schema structure.
2302 *
2303 * Returns the newly allocated structure or NULL in case or error
2304 */
2305static xmlSchemaAssemblePtr
2306xmlSchemaNewAssemble(void)
2307{
2308 xmlSchemaAssemblePtr ret;
2309
2310 ret = (xmlSchemaAssemblePtr) xmlMalloc(sizeof(xmlSchemaAssemble));
2311 if (ret == NULL) {
2312 /* xmlSchemaPErrMemory(ctxt, "allocating assemble info", NULL); */
2313 return (NULL);
2314 }
2315 memset(ret, 0, sizeof(xmlSchemaAssemble));
2316 ret->items = NULL;
2317 return (ret);
2318}
2319
2320/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002321 * xmlSchemaNewFacet:
Daniel Veillard4255d502002-04-16 15:50:10 +00002322 *
2323 * Allocate a new Facet structure.
2324 *
2325 * Returns the newly allocated structure or NULL in case or error
2326 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00002327xmlSchemaFacetPtr
2328xmlSchemaNewFacet(void)
Daniel Veillard4255d502002-04-16 15:50:10 +00002329{
2330 xmlSchemaFacetPtr ret;
2331
2332 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
2333 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002334 return (NULL);
2335 }
2336 memset(ret, 0, sizeof(xmlSchemaFacet));
2337
2338 return (ret);
2339}
2340
2341/**
2342 * xmlSchemaNewAnnot:
William M. Brack08171912003-12-29 02:52:11 +00002343 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00002344 * @node: a node
2345 *
2346 * Allocate a new annotation structure.
2347 *
2348 * Returns the newly allocated structure or NULL in case or error
2349 */
2350static xmlSchemaAnnotPtr
2351xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
2352{
2353 xmlSchemaAnnotPtr ret;
2354
2355 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
2356 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002357 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
Daniel Veillard4255d502002-04-16 15:50:10 +00002358 return (NULL);
2359 }
2360 memset(ret, 0, sizeof(xmlSchemaAnnot));
2361 ret->content = node;
2362 return (ret);
2363}
2364
2365/**
Daniel Veillardfdc91562002-07-01 21:52:03 +00002366 * xmlSchemaFreeAnnot:
2367 * @annot: a schema type structure
2368 *
2369 * Deallocate a annotation structure
2370 */
2371static void
2372xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
2373{
2374 if (annot == NULL)
2375 return;
2376 xmlFree(annot);
2377}
2378
2379/**
Daniel Veillard1d913862003-11-21 00:28:39 +00002380 * xmlSchemaFreeImport:
2381 * @import: a schema import structure
2382 *
2383 * Deallocate an import structure
2384 */
2385static void
2386xmlSchemaFreeImport(xmlSchemaImportPtr import)
2387{
2388 if (import == NULL)
2389 return;
2390
2391 xmlSchemaFree(import->schema);
William M. Brack2f2a6632004-08-20 23:09:47 +00002392 xmlFreeDoc(import->doc);
Daniel Veillard1d913862003-11-21 00:28:39 +00002393 xmlFree(import);
2394}
2395
2396/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002397 * xmlSchemaFreeInclude:
2398 * @include: a schema include structure
2399 *
2400 * Deallocate an include structure
2401 */
2402static void
2403xmlSchemaFreeInclude(xmlSchemaIncludePtr include)
2404{
2405 if (include == NULL)
2406 return;
2407
2408 xmlFreeDoc(include->doc);
2409 xmlFree(include);
2410}
2411
2412/**
2413 * xmlSchemaFreeIncludeList:
2414 * @includes: a schema include list
2415 *
2416 * Deallocate an include structure
2417 */
2418static void
2419xmlSchemaFreeIncludeList(xmlSchemaIncludePtr includes)
2420{
2421 xmlSchemaIncludePtr next;
2422
2423 while (includes != NULL) {
2424 next = includes->next;
2425 xmlSchemaFreeInclude(includes);
2426 includes = next;
2427 }
2428}
2429
2430/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002431 * xmlSchemaFreeNotation:
2432 * @schema: a schema notation structure
2433 *
2434 * Deallocate a Schema Notation structure.
2435 */
2436static void
2437xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
2438{
2439 if (nota == NULL)
2440 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002441 xmlFree(nota);
2442}
2443
2444/**
2445 * xmlSchemaFreeAttribute:
2446 * @schema: a schema attribute structure
2447 *
2448 * Deallocate a Schema Attribute structure.
2449 */
2450static void
2451xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
2452{
2453 if (attr == NULL)
2454 return;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002455 if (attr->annot != NULL)
2456 xmlSchemaFreeAnnot(attr->annot);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002457 if (attr->defVal != NULL)
2458 xmlSchemaFreeValue(attr->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00002459 xmlFree(attr);
2460}
2461
2462/**
Daniel Veillard3646d642004-06-02 19:19:14 +00002463 * xmlSchemaFreeWildcardNsSet:
2464 * set: a schema wildcard namespace
2465 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00002466 * Deallocates a list of wildcard constraint structures.
Daniel Veillard3646d642004-06-02 19:19:14 +00002467 */
2468static void
2469xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
2470{
2471 xmlSchemaWildcardNsPtr next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002472
Daniel Veillard3646d642004-06-02 19:19:14 +00002473 while (set != NULL) {
2474 next = set->next;
2475 xmlFree(set);
2476 set = next;
2477 }
2478}
2479
2480/**
2481 * xmlSchemaFreeWildcard:
Daniel Veillard01fa6152004-06-29 17:04:39 +00002482 * @wildcard: a wildcard structure
Daniel Veillard3646d642004-06-02 19:19:14 +00002483 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00002484 * Deallocates a wildcard structure.
Daniel Veillard3646d642004-06-02 19:19:14 +00002485 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00002486void
Daniel Veillard3646d642004-06-02 19:19:14 +00002487xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
2488{
2489 if (wildcard == NULL)
2490 return;
2491 if (wildcard->annot != NULL)
2492 xmlSchemaFreeAnnot(wildcard->annot);
2493 if (wildcard->nsSet != NULL)
2494 xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
2495 if (wildcard->negNsSet != NULL)
2496 xmlFree(wildcard->negNsSet);
2497 xmlFree(wildcard);
2498}
2499
2500/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002501 * xmlSchemaFreeAttributeGroup:
2502 * @schema: a schema attribute group structure
2503 *
2504 * Deallocate a Schema Attribute Group structure.
2505 */
2506static void
2507xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attr)
2508{
2509 if (attr == NULL)
2510 return;
Daniel Veillard3646d642004-06-02 19:19:14 +00002511 if (attr->annot != NULL)
2512 xmlSchemaFreeAnnot(attr->annot);
2513 if ((attr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) &&
2514 (attr->attributeWildcard != NULL))
2515 xmlSchemaFreeWildcard(attr->attributeWildcard);
2516
Daniel Veillard4255d502002-04-16 15:50:10 +00002517 xmlFree(attr);
2518}
2519
2520/**
Daniel Veillard3646d642004-06-02 19:19:14 +00002521 * xmlSchemaFreeAttributeUseList:
Daniel Veillard01fa6152004-06-29 17:04:39 +00002522 * @attrUse: an attribute link
Daniel Veillard3646d642004-06-02 19:19:14 +00002523 *
2524 * Deallocate a list of schema attribute uses.
2525 */
2526static void
2527xmlSchemaFreeAttributeUseList(xmlSchemaAttributeLinkPtr attrUse)
2528{
2529 xmlSchemaAttributeLinkPtr next;
2530
2531 while (attrUse != NULL) {
2532 next = attrUse->next;
2533 xmlFree(attrUse);
2534 attrUse = next;
2535 }
2536}
2537
2538/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00002539 * xmlSchemaFreeTypeLinkList:
2540 * @alink: a type link
2541 *
2542 * Deallocate a list of types.
2543 */
2544static void
2545xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
2546{
2547 xmlSchemaTypeLinkPtr next;
2548
2549 while (link != NULL) {
2550 next = link->next;
2551 xmlFree(link);
2552 link = next;
2553 }
2554}
2555
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00002556#ifdef IDC_ENABLED
2557static void
2558xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
2559{
2560 xmlSchemaIDCStateObjPtr next;
2561 while (sto != NULL) {
2562 next = sto->next;
2563 if (sto->history != NULL)
2564 xmlFree(sto->history);
2565 if (sto->xpathCtxt != NULL)
2566 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
2567 xmlFree(sto);
2568 sto = next;
2569 }
2570}
2571
2572/**
2573 * xmlSchemaFreeIDC:
2574 * @idc: a identity-constraint definition
2575 *
2576 * Deallocates an identity-constraint definition.
2577 */
2578static void
2579xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)
2580{
2581 xmlSchemaIDCSelectPtr cur, prev;
2582
2583 if (idcDef == NULL)
2584 return;
2585 if (idcDef->annot != NULL)
2586 xmlSchemaFreeAnnot(idcDef->annot);
2587 if (idcDef->ref != NULL)
2588 xmlFree(idcDef->ref);
2589 /* Selector */
2590 if (idcDef->selector != NULL) {
2591 if (idcDef->selector->xpathComp != NULL)
2592 xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp);
2593 xmlFree(idcDef->selector);
2594 }
2595 /* Fields */
2596 if (idcDef->fields != NULL) {
2597 cur = idcDef->fields;
2598 do {
2599 prev = cur;
2600 cur = cur->next;
2601 if (prev->xpathComp != NULL)
2602 xmlFreePattern((xmlPatternPtr) prev->xpathComp);
2603 xmlFree(prev);
2604 } while (cur != NULL);
2605 }
2606 xmlFree(idcDef);
2607}
2608#endif /* IDC_ENABLED */
2609
Daniel Veillard01fa6152004-06-29 17:04:39 +00002610/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002611 * xmlSchemaFreeElement:
2612 * @schema: a schema element structure
2613 *
2614 * Deallocate a Schema Element structure.
2615 */
2616static void
2617xmlSchemaFreeElement(xmlSchemaElementPtr elem)
2618{
2619 if (elem == NULL)
2620 return;
Daniel Veillard32370232002-10-16 14:08:14 +00002621 if (elem->annot != NULL)
2622 xmlSchemaFreeAnnot(elem->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00002623 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002624 xmlRegFreeRegexp(elem->contModel);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002625 if (elem->defVal != NULL)
2626 xmlSchemaFreeValue(elem->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00002627 xmlFree(elem);
2628}
2629
2630/**
2631 * xmlSchemaFreeFacet:
2632 * @facet: a schema facet structure
2633 *
2634 * Deallocate a Schema Facet structure.
2635 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00002636void
Daniel Veillard4255d502002-04-16 15:50:10 +00002637xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
2638{
2639 if (facet == NULL)
2640 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002641 if (facet->val != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002642 xmlSchemaFreeValue(facet->val);
Daniel Veillard4255d502002-04-16 15:50:10 +00002643 if (facet->regexp != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002644 xmlRegFreeRegexp(facet->regexp);
Daniel Veillardfdc91562002-07-01 21:52:03 +00002645 if (facet->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002646 xmlSchemaFreeAnnot(facet->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00002647 xmlFree(facet);
2648}
2649
2650/**
2651 * xmlSchemaFreeType:
2652 * @type: a schema type structure
2653 *
2654 * Deallocate a Schema Type structure.
2655 */
2656void
2657xmlSchemaFreeType(xmlSchemaTypePtr type)
2658{
2659 if (type == NULL)
2660 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002661 if (type->annot != NULL)
Daniel Veillard32370232002-10-16 14:08:14 +00002662 xmlSchemaFreeAnnot(type->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00002663 if (type->facets != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002664 xmlSchemaFacetPtr facet, next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002665
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002666 facet = type->facets;
2667 while (facet != NULL) {
2668 next = facet->next;
2669 xmlSchemaFreeFacet(facet);
2670 facet = next;
2671 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002672 }
Daniel Veillard3646d642004-06-02 19:19:14 +00002673 if (type->type != XML_SCHEMA_TYPE_BASIC) {
2674 if (type->attributeUses != NULL)
2675 xmlSchemaFreeAttributeUseList(type->attributeUses);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002676 if ((type->attributeWildcard != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +00002677 ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002678 (type->flags & XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD))) {
2679 /*
2680 * NOTE: The only case where an attribute wildcard
2681 * is not owned, is if a complex type inherits it
2682 * from a base type.
2683 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002684 xmlSchemaFreeWildcard(type->attributeWildcard);
2685 }
2686 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00002687 if (type->memberTypes != NULL)
2688 xmlSchemaFreeTypeLinkList(type->memberTypes);
2689 if (type->facetSet != NULL) {
2690 xmlSchemaFacetLinkPtr next, link;
2691
2692 link = type->facetSet;
2693 do {
2694 next = link->next;
2695 xmlFree(link);
2696 link = next;
2697 } while (link != NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002698 }
2699 if (type->contModel != NULL)
2700 xmlRegFreeRegexp(type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00002701 xmlFree(type);
2702}
2703
2704/**
Daniel Veillardb0f397e2003-12-23 23:30:53 +00002705 * xmlSchemaFreeTypeList:
2706 * @type: a schema type structure
2707 *
2708 * Deallocate a Schema Type structure.
2709 */
2710static void
2711xmlSchemaFreeTypeList(xmlSchemaTypePtr type)
2712{
2713 xmlSchemaTypePtr next;
2714
2715 while (type != NULL) {
2716 next = type->redef;
2717 xmlSchemaFreeType(type);
2718 type = next;
2719 }
2720}
2721
2722/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002723 * xmlSchemaFree:
2724 * @schema: a schema structure
2725 *
2726 * Deallocate a Schema structure.
2727 */
2728void
2729xmlSchemaFree(xmlSchemaPtr schema)
2730{
2731 if (schema == NULL)
2732 return;
2733
Daniel Veillard4255d502002-04-16 15:50:10 +00002734 if (schema->notaDecl != NULL)
2735 xmlHashFree(schema->notaDecl,
2736 (xmlHashDeallocator) xmlSchemaFreeNotation);
2737 if (schema->attrDecl != NULL)
2738 xmlHashFree(schema->attrDecl,
2739 (xmlHashDeallocator) xmlSchemaFreeAttribute);
2740 if (schema->attrgrpDecl != NULL)
2741 xmlHashFree(schema->attrgrpDecl,
2742 (xmlHashDeallocator) xmlSchemaFreeAttributeGroup);
2743 if (schema->elemDecl != NULL)
2744 xmlHashFree(schema->elemDecl,
2745 (xmlHashDeallocator) xmlSchemaFreeElement);
2746 if (schema->typeDecl != NULL)
2747 xmlHashFree(schema->typeDecl,
Daniel Veillardb0f397e2003-12-23 23:30:53 +00002748 (xmlHashDeallocator) xmlSchemaFreeTypeList);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00002749 if (schema->groupDecl != NULL)
2750 xmlHashFree(schema->groupDecl,
2751 (xmlHashDeallocator) xmlSchemaFreeType);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00002752#ifdef IDC_ENABLED
2753 if (schema->idcDef != NULL)
2754 xmlHashFree(schema->idcDef,
2755 (xmlHashDeallocator) xmlSchemaFreeIDC);
2756#endif
Daniel Veillard1d913862003-11-21 00:28:39 +00002757 if (schema->schemasImports != NULL)
2758 xmlHashFree(schema->schemasImports,
2759 (xmlHashDeallocator) xmlSchemaFreeImport);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002760 if (schema->includes != NULL) {
2761 xmlSchemaFreeIncludeList((xmlSchemaIncludePtr) schema->includes);
2762 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002763 if (schema->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002764 xmlSchemaFreeAnnot(schema->annot);
Daniel Veillarddda22c12004-01-24 08:31:30 +00002765 if (schema->doc != NULL && !schema->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002766 xmlFreeDoc(schema->doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002767 xmlDictFree(schema->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00002768 xmlFree(schema);
2769}
2770
2771/************************************************************************
2772 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00002773 * Debug functions *
2774 * *
2775 ************************************************************************/
2776
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002777#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002778
Daniel Veillard4255d502002-04-16 15:50:10 +00002779/**
2780 * xmlSchemaElementDump:
2781 * @elem: an element
2782 * @output: the file output
2783 *
2784 * Dump the element
2785 */
2786static void
2787xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002788 const xmlChar * name ATTRIBUTE_UNUSED,
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002789 const xmlChar * namespace ATTRIBUTE_UNUSED,
2790 const xmlChar * context ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00002791{
2792 if (elem == NULL)
2793 return;
2794
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002795 if (elem->flags & XML_SCHEMAS_ELEM_REF) {
2796 fprintf(output, "Particle: %s", name);
2797 fprintf(output, ", term element: %s", elem->ref);
2798 if (elem->refNs != NULL)
2799 fprintf(output, " ns %s", elem->refNs);
2800 } else {
2801 fprintf(output, "Element");
2802 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
2803 fprintf(output, " (global)");
2804 fprintf(output, ": %s ", elem->name);
2805 if (namespace != NULL)
2806 fprintf(output, "ns %s", namespace);
2807 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002808 fprintf(output, "\n");
2809 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002810 fprintf(output, " min %d ", elem->minOccurs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002811 if (elem->maxOccurs >= UNBOUNDED)
2812 fprintf(output, "max: unbounded\n");
2813 else if (elem->maxOccurs != 1)
2814 fprintf(output, "max: %d\n", elem->maxOccurs);
2815 else
2816 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002817 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002818 /*
2819 * Misc other properties.
2820 */
2821 if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
2822 (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
2823 (elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
2824 (elem->flags & XML_SCHEMAS_ELEM_DEFAULT) ||
2825 (elem->id != NULL)) {
2826 fprintf(output, " props: ");
2827 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
2828 fprintf(output, "[fixed] ");
2829 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
2830 fprintf(output, "[default] ");
2831 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
2832 fprintf(output, "[abstract] ");
2833 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
2834 fprintf(output, "[nillable] ");
2835 if (elem->id != NULL)
2836 fprintf(output, "[id: '%s'] ", elem->id);
2837 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002838 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002839 /*
2840 * Default/fixed value.
2841 */
Daniel Veillard4255d502002-04-16 15:50:10 +00002842 if (elem->value != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002843 fprintf(output, " value: '%s'\n", elem->value);
2844 /*
2845 * Type.
2846 */
2847 if (elem->namedType != NULL) {
2848 fprintf(output, " type: %s ", elem->namedType);
2849 if (elem->namedTypeNs != NULL)
2850 fprintf(output, "ns %s\n", elem->namedTypeNs);
2851 else
2852 fprintf(output, "\n");
2853 }
2854 /*
2855 * Substitution group.
2856 */
2857 if (elem->substGroup != NULL) {
2858 fprintf(output, " substitutionGroup: %s ", elem->substGroup);
2859 if (elem->substGroupNs != NULL)
2860 fprintf(output, "ns %s\n", elem->substGroupNs);
2861 else
2862 fprintf(output, "\n");
2863 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002864}
2865
2866/**
2867 * xmlSchemaAnnotDump:
2868 * @output: the file output
2869 * @annot: a annotation
2870 *
2871 * Dump the annotation
2872 */
2873static void
2874xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
2875{
2876 xmlChar *content;
2877
2878 if (annot == NULL)
2879 return;
2880
2881 content = xmlNodeGetContent(annot->content);
2882 if (content != NULL) {
2883 fprintf(output, " Annot: %s\n", content);
2884 xmlFree(content);
2885 } else
2886 fprintf(output, " Annot: empty\n");
2887}
2888
2889/**
2890 * xmlSchemaTypeDump:
2891 * @output: the file output
2892 * @type: a type structure
2893 *
2894 * Dump a SchemaType structure
2895 */
2896static void
2897xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
2898{
2899 if (type == NULL) {
2900 fprintf(output, "Type: NULL\n");
2901 return;
2902 }
2903 fprintf(output, "Type: ");
2904 if (type->name != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002905 fprintf(output, "%s ", type->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00002906 else
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002907 fprintf(output, "no name ");
2908 if (type->targetNamespace != NULL)
2909 fprintf(output, "ns %s ", type->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00002910 switch (type->type) {
2911 case XML_SCHEMA_TYPE_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002912 fprintf(output, "[basic] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002913 break;
2914 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002915 fprintf(output, "[simple] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002916 break;
2917 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002918 fprintf(output, "[complex] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002919 break;
2920 case XML_SCHEMA_TYPE_SEQUENCE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002921 fprintf(output, "[sequence] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002922 break;
2923 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002924 fprintf(output, "[choice] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002925 break;
2926 case XML_SCHEMA_TYPE_ALL:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002927 fprintf(output, "[all] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002928 break;
2929 case XML_SCHEMA_TYPE_UR:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002930 fprintf(output, "[ur] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002931 break;
2932 case XML_SCHEMA_TYPE_RESTRICTION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002933 fprintf(output, "[restriction] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002934 break;
2935 case XML_SCHEMA_TYPE_EXTENSION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002936 fprintf(output, "[extension] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002937 break;
2938 default:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002939 fprintf(output, "[unknown type %d] ", type->type);
Daniel Veillard4255d502002-04-16 15:50:10 +00002940 break;
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002941 }
2942 fprintf(output, "content: ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002943 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002944 case XML_SCHEMA_CONTENT_UNKNOWN:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002945 fprintf(output, "[unknown] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002946 break;
2947 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002948 fprintf(output, "[empty] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002949 break;
2950 case XML_SCHEMA_CONTENT_ELEMENTS:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002951 fprintf(output, "[element] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002952 break;
2953 case XML_SCHEMA_CONTENT_MIXED:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002954 fprintf(output, "[mixed] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002955 break;
2956 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00002957 /* not used. */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002958 break;
2959 case XML_SCHEMA_CONTENT_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002960 fprintf(output, "[basic] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002961 break;
2962 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002963 fprintf(output, "[simple] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002964 break;
2965 case XML_SCHEMA_CONTENT_ANY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002966 fprintf(output, "[any] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002967 break;
Daniel Veillard4255d502002-04-16 15:50:10 +00002968 }
2969 fprintf(output, "\n");
2970 if ((type->minOccurs != 1) || (type->maxOccurs != 1)) {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002971 fprintf(output, " min: %d ", type->minOccurs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002972 if (type->maxOccurs >= UNBOUNDED)
2973 fprintf(output, "max: unbounded\n");
2974 else if (type->maxOccurs != 1)
2975 fprintf(output, "max: %d\n", type->maxOccurs);
2976 else
2977 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002978 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002979 if (type->base != NULL) {
2980 fprintf(output, " base type: %s", type->base);
2981 if (type->baseNs != NULL)
2982 fprintf(output, " ns %s\n", type->baseNs);
2983 else
2984 fprintf(output, "\n");
2985 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002986 if (type->annot != NULL)
2987 xmlSchemaAnnotDump(output, type->annot);
2988 if (type->subtypes != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002989 xmlSchemaTypePtr sub = type->subtypes;
Daniel Veillard4255d502002-04-16 15:50:10 +00002990
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002991 fprintf(output, " subtypes: ");
2992 while (sub != NULL) {
2993 fprintf(output, "%s ", sub->name);
2994 sub = sub->next;
2995 }
2996 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002997 }
2998
2999}
3000
3001/**
3002 * xmlSchemaDump:
3003 * @output: the file output
3004 * @schema: a schema structure
3005 *
3006 * Dump a Schema structure.
3007 */
3008void
3009xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
3010{
Daniel Veillardce682bc2004-11-05 17:22:25 +00003011 if (output == NULL)
3012 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003013 if (schema == NULL) {
3014 fprintf(output, "Schemas: NULL\n");
3015 return;
3016 }
3017 fprintf(output, "Schemas: ");
3018 if (schema->name != NULL)
3019 fprintf(output, "%s, ", schema->name);
3020 else
3021 fprintf(output, "no name, ");
3022 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00003023 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003024 else
3025 fprintf(output, "no target namespace");
3026 fprintf(output, "\n");
3027 if (schema->annot != NULL)
3028 xmlSchemaAnnotDump(output, schema->annot);
3029
3030 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
3031 output);
3032 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003033 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00003034}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003035
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003036#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00003037#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003038/**
3039 * xmlSchemaDebugDumpIDCTable:
3040 * @vctxt: the WXS validation context
3041 *
3042 * Displays the current IDC table for debug purposes.
3043 */
3044static void
3045xmlSchemaDebugDumpIDCTable(FILE * output,
3046 const xmlChar *namespaceName,
3047 const xmlChar *localName,
3048 xmlSchemaPSVIIDCBindingPtr bind)
3049{
3050 xmlChar *str = NULL, *value;
3051 xmlSchemaPSVIIDCNodePtr tab;
3052 xmlSchemaPSVIIDCKeyPtr key;
3053 int i, j, res;
3054
3055 fprintf(output, "IDC: TABLES on %s\n",
3056 xmlSchemaFormatNsUriLocal(&str, namespaceName, localName));
3057 FREE_AND_NULL(str)
3058
3059 if (bind == NULL)
3060 return;
3061 do {
3062 fprintf(output, "IDC: BINDING %s\n",
3063 xmlSchemaFormatNsUriLocal(&str, bind->definition->targetNamespace,
3064 bind->definition->name));
3065 FREE_AND_NULL(str)
3066 for (i = 0; i < bind->nbNodes; i++) {
3067 tab = bind->nodeTable[i];
3068 fprintf(output, " ( ");
3069 for (j = 0; j < bind->definition->nbFields; j++) {
3070 key = tab->keys[j];
3071 if ((key != NULL) && (key->compValue != NULL)) {
3072#ifdef IDC_VALUE_SUPPORT
3073 res = xmlSchemaGetCanonValue(key->compValue, &value);
3074#else
3075 value = xmlStrdup(BAD_CAST "dummy-value");
3076 res = 0;
3077#endif
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003078 if (res >= 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003079 fprintf(output, "\"%s\" ", value);
3080 else
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003081 fprintf(output, "CANON-VALUE-FAILED ");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003082 if (res == 0)
3083 FREE_AND_NULL(value)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003084 } else if (key != NULL)
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003085 fprintf(output, "(no val), ");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003086 else
3087 fprintf(output, "(key missing), ");
3088 }
3089 fprintf(output, ")\n");
3090 }
3091 bind = bind->next;
3092 } while (bind != NULL);
3093}
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00003094#endif /* DEBUG_IDC */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003095#endif /* IDC_ENABLED */
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00003096#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +00003097
3098/************************************************************************
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003099 * *
3100 * Utilities *
3101 * *
3102 ************************************************************************/
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003103
Daniel Veillardc0826a72004-08-10 14:17:33 +00003104/**
3105 * xmlSchemaGetPropNode:
3106 * @node: the element node
3107 * @name: the name of the attribute
3108 *
3109 * Seeks an attribute with a name of @name in
3110 * no namespace.
3111 *
3112 * Returns the attribute or NULL if not present.
3113 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003114static xmlAttrPtr
Daniel Veillardc0826a72004-08-10 14:17:33 +00003115xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
Daniel Veillard01fa6152004-06-29 17:04:39 +00003116{
3117 xmlAttrPtr prop;
3118
Daniel Veillardc0826a72004-08-10 14:17:33 +00003119 if ((node == NULL) || (name == NULL))
3120 return(NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003121 prop = node->properties;
3122 while (prop != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00003123 if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
3124 return(prop);
3125 prop = prop->next;
3126 }
3127 return (NULL);
3128}
3129
3130/**
3131 * xmlSchemaGetPropNodeNs:
3132 * @node: the element node
3133 * @uri: the uri
3134 * @name: the name of the attribute
3135 *
3136 * Seeks an attribute with a local name of @name and
3137 * a namespace URI of @uri.
3138 *
3139 * Returns the attribute or NULL if not present.
3140 */
3141static xmlAttrPtr
3142xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
3143{
3144 xmlAttrPtr prop;
3145
3146 if ((node == NULL) || (name == NULL))
3147 return(NULL);
3148 prop = node->properties;
3149 while (prop != NULL) {
3150 if ((prop->ns != NULL) &&
3151 xmlStrEqual(prop->name, BAD_CAST name) &&
3152 xmlStrEqual(prop->ns->href, BAD_CAST uri))
Daniel Veillard01fa6152004-06-29 17:04:39 +00003153 return(prop);
3154 prop = prop->next;
3155 }
3156 return (NULL);
3157}
3158
3159static const xmlChar *
3160xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3161{
3162 xmlChar *val;
3163 const xmlChar *ret;
3164
3165 val = xmlNodeGetContent(node);
3166 if (val == NULL)
3167 return(NULL);
3168 ret = xmlDictLookup(ctxt->dict, val, -1);
3169 xmlFree(val);
3170 return(ret);
3171}
3172
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003173/**
3174 * xmlSchemaGetProp:
3175 * @ctxt: the parser context
3176 * @node: the node
3177 * @name: the property name
3178 *
3179 * Read a attribute value and internalize the string
3180 *
3181 * Returns the string or NULL if not present.
3182 */
3183static const xmlChar *
3184xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
3185 const char *name)
3186{
3187 xmlChar *val;
3188 const xmlChar *ret;
3189
3190 val = xmlGetProp(node, BAD_CAST name);
3191 if (val == NULL)
3192 return(NULL);
3193 ret = xmlDictLookup(ctxt->dict, val, -1);
3194 xmlFree(val);
3195 return(ret);
3196}
3197
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003198/************************************************************************
Daniel Veillard4255d502002-04-16 15:50:10 +00003199 * *
3200 * Parsing functions *
3201 * *
3202 ************************************************************************/
3203
3204/**
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003205 * xmlSchemaGetElem:
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003206 * @schema: the schema context
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003207 * @name: the element name
3208 * @ns: the element namespace
3209 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003210 * Lookup a global element declaration in the schema.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003211 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003212 * Returns the element declaration or NULL if not found.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003213 */
3214static xmlSchemaElementPtr
3215xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003216 const xmlChar * namespace)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003217{
3218 xmlSchemaElementPtr ret;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003219
3220 if ((name == NULL) || (schema == NULL))
3221 return (NULL);
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003222
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003223 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003224 if ((ret != NULL) &&
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003225 (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003226 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00003227 } else
3228 ret = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00003229 /*
3230 * This one was removed, since top level element declarations have
3231 * the target namespace specified in targetNamespace of the <schema>
3232 * information element, even if elementFormDefault is "unqualified".
3233 */
3234
3235 /* else if ((schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003236 if (xmlStrEqual(namespace, schema->targetNamespace))
3237 ret = xmlHashLookup2(schema->elemDecl, name, NULL);
3238 else
3239 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003240 if ((ret != NULL) &&
3241 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003242 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003243 }
William M. Bracke7091952004-05-11 15:09:58 +00003244 */
Daniel Veillard3646d642004-06-02 19:19:14 +00003245
William M. Brack2f2a6632004-08-20 23:09:47 +00003246 /*
3247 * Removed since imported components will be hold by the main schema only.
3248 *
Daniel Veillard3646d642004-06-02 19:19:14 +00003249 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003250 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003251 else
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003252 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003253 if (import != NULL) {
Daniel Veillardf2a12832003-11-24 13:04:35 +00003254 ret = xmlSchemaGetElem(import->schema, name, namespace, level + 1);
Daniel Veillard3646d642004-06-02 19:19:14 +00003255 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
3256 return (ret);
3257 } else
3258 ret = NULL;
3259 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003260 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003261#ifdef DEBUG
3262 if (ret == NULL) {
3263 if (namespace == NULL)
3264 fprintf(stderr, "Unable to lookup type %s", name);
3265 else
3266 fprintf(stderr, "Unable to lookup type %s:%s", name,
3267 namespace);
3268 }
3269#endif
3270 return (ret);
3271}
3272
3273/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003274 * xmlSchemaGetType:
3275 * @schema: the schemas context
3276 * @name: the type name
3277 * @ns: the type namespace
3278 *
3279 * Lookup a type in the schemas or the predefined types
3280 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003281 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +00003282 */
3283static xmlSchemaTypePtr
3284xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003285 const xmlChar * namespace)
3286{
Daniel Veillard4255d502002-04-16 15:50:10 +00003287 xmlSchemaTypePtr ret;
3288
3289 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003290 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003291 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003292 ret = xmlHashLookup2(schema->typeDecl, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003293 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003294 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003295 }
3296 ret = xmlSchemaGetPredefinedType(name, namespace);
Daniel Veillard1d913862003-11-21 00:28:39 +00003297 if (ret != NULL)
3298 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00003299 /*
3300 * Removed, since the imported components will be grafted on the
3301 * main schema only.
Daniel Veillard3646d642004-06-02 19:19:14 +00003302 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003303 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003304 else
Daniel Veillard1d913862003-11-21 00:28:39 +00003305 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003306 if (import != NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00003307 ret = xmlSchemaGetType(import->schema, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003308 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
3309 return (ret);
3310 } else
3311 ret = NULL;
3312 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003313 */
Daniel Veillard4255d502002-04-16 15:50:10 +00003314#ifdef DEBUG
3315 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003316 if (namespace == NULL)
3317 fprintf(stderr, "Unable to lookup type %s", name);
3318 else
3319 fprintf(stderr, "Unable to lookup type %s:%s", name,
3320 namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003321 }
3322#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003323 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003324}
3325
Daniel Veillard3646d642004-06-02 19:19:14 +00003326/**
3327 * xmlSchemaGetAttribute:
3328 * @schema: the context of the schema
3329 * @name: the name of the attribute
3330 * @ns: the target namespace of the attribute
3331 *
3332 * Lookup a an attribute in the schema or imported schemas
3333 *
3334 * Returns the attribute declaration or NULL if not found.
3335 */
3336static xmlSchemaAttributePtr
3337xmlSchemaGetAttribute(xmlSchemaPtr schema, const xmlChar * name,
3338 const xmlChar * namespace)
3339{
3340 xmlSchemaAttributePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00003341
3342 if ((name == NULL) || (schema == NULL))
3343 return (NULL);
3344
3345
3346 ret = xmlHashLookup2(schema->attrDecl, name, namespace);
3347 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL))
3348 return (ret);
3349 else
3350 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00003351 /*
3352 * Removed, since imported components will be hold by the main schema only.
3353 *
Daniel Veillard3646d642004-06-02 19:19:14 +00003354 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003355 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003356 else
3357 import = xmlHashLookup(schema->schemasImports, namespace);
3358 if (import != NULL) {
3359 ret = xmlSchemaGetAttribute(import->schema, name, namespace);
3360 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL)) {
3361 return (ret);
3362 } else
3363 ret = NULL;
3364 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003365 */
Daniel Veillard3646d642004-06-02 19:19:14 +00003366#ifdef DEBUG
3367 if (ret == NULL) {
3368 if (namespace == NULL)
3369 fprintf(stderr, "Unable to lookup attribute %s", name);
3370 else
3371 fprintf(stderr, "Unable to lookup attribute %s:%s", name,
3372 namespace);
3373 }
3374#endif
3375 return (ret);
3376}
3377
3378/**
3379 * xmlSchemaGetAttributeGroup:
3380 * @schema: the context of the schema
3381 * @name: the name of the attribute group
3382 * @ns: the target namespace of the attribute group
3383 *
3384 * Lookup a an attribute group in the schema or imported schemas
3385 *
3386 * Returns the attribute group definition or NULL if not found.
3387 */
3388static xmlSchemaAttributeGroupPtr
3389xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
3390 const xmlChar * namespace)
3391{
3392 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00003393
3394 if ((name == NULL) || (schema == NULL))
3395 return (NULL);
3396
3397
3398 ret = xmlHashLookup2(schema->attrgrpDecl, name, namespace);
3399 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
3400 return (ret);
3401 else
3402 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00003403 /*
3404 * Removed since imported components will be hold by the main schema only.
3405 *
Daniel Veillard3646d642004-06-02 19:19:14 +00003406 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003407 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003408 else
3409 import = xmlHashLookup(schema->schemasImports, namespace);
3410 if (import != NULL) {
3411 ret = xmlSchemaGetAttributeGroup(import->schema, name, namespace);
3412 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
3413 return (ret);
3414 else
3415 ret = NULL;
3416 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003417 */
Daniel Veillard3646d642004-06-02 19:19:14 +00003418#ifdef DEBUG
3419 if (ret == NULL) {
3420 if (namespace == NULL)
3421 fprintf(stderr, "Unable to lookup attribute group %s", name);
3422 else
3423 fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
3424 namespace);
3425 }
3426#endif
3427 return (ret);
3428}
3429
3430/**
3431 * xmlSchemaGetGroup:
3432 * @schema: the context of the schema
3433 * @name: the name of the group
3434 * @ns: the target namespace of the group
3435 *
3436 * Lookup a group in the schema or imported schemas
3437 *
3438 * Returns the group definition or NULL if not found.
3439 */
3440static xmlSchemaTypePtr
3441xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
3442 const xmlChar * namespace)
3443{
3444 xmlSchemaTypePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00003445
3446 if ((name == NULL) || (schema == NULL))
3447 return (NULL);
3448
3449
3450 ret = xmlHashLookup2(schema->groupDecl, name, namespace);
3451 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
3452 return (ret);
3453 else
3454 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00003455 /*
3456 * Removed since imported components will be hold by the main schema only.
3457 *
Daniel Veillard3646d642004-06-02 19:19:14 +00003458 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003459 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003460 else
3461 import = xmlHashLookup(schema->schemasImports, namespace);
3462 if (import != NULL) {
3463 ret = xmlSchemaGetGroup(import->schema, name, namespace);
3464 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
3465 return (ret);
3466 else
3467 ret = NULL;
3468 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003469 */
Daniel Veillard3646d642004-06-02 19:19:14 +00003470#ifdef DEBUG
3471 if (ret == NULL) {
3472 if (namespace == NULL)
3473 fprintf(stderr, "Unable to lookup group %s", name);
3474 else
3475 fprintf(stderr, "Unable to lookup group %s:%s", name,
3476 namespace);
3477 }
3478#endif
3479 return (ret);
3480}
3481
Daniel Veillard4255d502002-04-16 15:50:10 +00003482/************************************************************************
3483 * *
3484 * Parsing functions *
3485 * *
3486 ************************************************************************/
3487
3488#define IS_BLANK_NODE(n) \
3489 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content)))
3490
3491/**
3492 * xmlSchemaIsBlank:
3493 * @str: a string
3494 *
3495 * Check if a string is ignorable
3496 *
3497 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
3498 */
3499static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003500xmlSchemaIsBlank(xmlChar * str)
3501{
Daniel Veillard4255d502002-04-16 15:50:10 +00003502 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003503 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003504 while (*str != 0) {
William M. Brack76e95df2003-10-18 16:20:14 +00003505 if (!(IS_BLANK_CH(*str)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003506 return (0);
3507 str++;
Daniel Veillard4255d502002-04-16 15:50:10 +00003508 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003509 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003510}
3511
3512/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003513 * xmlSchemaAddAssembledItem:
3514 * @ctxt: a schema parser context
3515 * @schema: the schema being built
3516 * @item: the item
3517 *
3518 * Add a item to the schema's list of current items.
3519 * This is used if the schema was already constructed and
3520 * new schemata need to be added to it.
3521 * *WARNING* this interface is highly subject to change.
3522 *
3523 * Returns 0 if suceeds and -1 if an internal error occurs.
3524 */
3525static int
3526xmlSchemaAddAssembledItem(xmlSchemaParserCtxtPtr ctxt,
3527 xmlSchemaTypePtr item)
3528{
3529 static int growSize = 100;
3530 xmlSchemaAssemblePtr ass;
3531
3532 ass = ctxt->assemble;
3533 if (ass->sizeItems < 0) {
3534 /* If disabled. */
3535 return (0);
3536 }
3537 if (ass->sizeItems <= 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003538 ass->items = (void **) xmlMalloc(growSize * sizeof(xmlSchemaTypePtr));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003539 if (ass->items == NULL) {
3540 xmlSchemaPErrMemory(ctxt,
3541 "allocating new item buffer", NULL);
3542 return (-1);
3543 }
3544 ass->sizeItems = growSize;
3545 } else if (ass->sizeItems <= ass->nbItems) {
3546 ass->sizeItems *= 2;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003547 ass->items = (void **) xmlRealloc(ass->items,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003548 ass->sizeItems * sizeof(xmlSchemaTypePtr));
3549 if (ass->items == NULL) {
3550 xmlSchemaPErrMemory(ctxt,
3551 "growing item buffer", NULL);
3552 ass->sizeItems = 0;
3553 return (-1);
3554 }
3555 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003556 /* ass->items[ass->nbItems++] = (void *) item; */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003557 ((xmlSchemaTypePtr *) ass->items)[ass->nbItems++] = (void *) item;
3558 return (0);
3559}
3560
3561/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003562 * xmlSchemaAddNotation:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003563 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003564 * @schema: the schema being built
3565 * @name: the item name
3566 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00003567 * Add an XML schema annotation declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00003568 * *WARNING* this interface is highly subject to change
3569 *
3570 * Returns the new struture or NULL in case of error
3571 */
3572static xmlSchemaNotationPtr
3573xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00003574 const xmlChar *name)
Daniel Veillard4255d502002-04-16 15:50:10 +00003575{
3576 xmlSchemaNotationPtr ret = NULL;
3577 int val;
3578
3579 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3580 return (NULL);
3581
3582 if (schema->notaDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003583 schema->notaDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003584 if (schema->notaDecl == NULL)
3585 return (NULL);
3586
3587 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
3588 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003589 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003590 return (NULL);
3591 }
3592 memset(ret, 0, sizeof(xmlSchemaNotation));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003593 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003594 val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
3595 ret);
3596 if (val != 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00003597 /*
3598 * TODO: This should never happen, since a unique name will be computed.
3599 * If it fails, then an other internal error must have occured.
3600 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003601 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
3602 XML_SCHEMAP_REDEFINED_NOTATION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003603 "Annotation declaration '%s' is already declared.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003604 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003605 xmlFree(ret);
3606 return (NULL);
3607 }
3608 return (ret);
3609}
3610
3611
3612/**
3613 * xmlSchemaAddAttribute:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003614 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003615 * @schema: the schema being built
3616 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003617 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00003618 *
3619 * Add an XML schema Attrribute declaration
3620 * *WARNING* this interface is highly subject to change
3621 *
3622 * Returns the new struture or NULL in case of error
3623 */
3624static xmlSchemaAttributePtr
3625xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003626 const xmlChar * name, const xmlChar * namespace,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003627 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00003628{
3629 xmlSchemaAttributePtr ret = NULL;
3630 int val;
3631
3632 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3633 return (NULL);
3634
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003635#ifdef DEBUG
3636 fprintf(stderr, "Adding attribute %s\n", name);
3637 if (namespace != NULL)
3638 fprintf(stderr, " target namespace %s\n", namespace);
3639#endif
3640
Daniel Veillard4255d502002-04-16 15:50:10 +00003641 if (schema->attrDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003642 schema->attrDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003643 if (schema->attrDecl == NULL)
3644 return (NULL);
3645
3646 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
3647 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003648 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003649 return (NULL);
3650 }
3651 memset(ret, 0, sizeof(xmlSchemaAttribute));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003652 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00003653 ret->targetNamespace = namespace;
Daniel Veillard4255d502002-04-16 15:50:10 +00003654 val = xmlHashAddEntry3(schema->attrDecl, name,
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00003655 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003656 if (val != 0) {
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003657 if (topLevel) {
3658 xmlSchemaPCustomErr(ctxt,
3659 XML_SCHEMAP_REDEFINED_ATTR,
3660 NULL, NULL, node,
3661 "A global attribute declaration with the name '%s' does "
3662 "already exist", name);
3663 xmlFree(ret);
3664 return (NULL);
3665 } else {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003666 char buf[30];
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003667 /*
3668 * Using the ctxt->container for xmlHashAddEntry3 is ambigious
3669 * in the scenario:
3670 * 1. multiple top-level complex types have different target
3671 * namespaces but have the SAME NAME; this can happen if
3672 * schemata are imported
3673 * 2. those complex types contain attributes with an equal name
3674 * 3. those attributes are in no namespace
3675 * We will compute a new context string.
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003676 */
3677 snprintf(buf, 29, "#aCont%d", ctxt->counter++ + 1);
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003678 val = xmlHashAddEntry3(schema->attrDecl, name,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00003679 namespace, xmlDictLookup(ctxt->dict, BAD_CAST buf, -1), ret);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003680
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003681 if (val != 0) {
3682 xmlSchemaPCustomErr(ctxt,
3683 XML_SCHEMAP_INTERNAL,
3684 NULL, NULL, node,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003685 "Internal error: xmlSchemaAddAttribute, "
3686 "a dublicate attribute declaration with the name '%s' "
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003687 "could not be added to the hash.", name);
3688 xmlFree(ret);
3689 return (NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003690 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003691 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003692 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003693 if (ctxt->assemble != NULL)
3694 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003695 return (ret);
3696}
3697
3698/**
3699 * xmlSchemaAddAttributeGroup:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003700 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003701 * @schema: the schema being built
3702 * @name: the item name
3703 *
3704 * Add an XML schema Attrribute Group declaration
3705 *
3706 * Returns the new struture or NULL in case of error
3707 */
3708static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003709xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00003710 xmlSchemaPtr schema, const xmlChar * name,
3711 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003712{
3713 xmlSchemaAttributeGroupPtr ret = NULL;
3714 int val;
3715
3716 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3717 return (NULL);
3718
3719 if (schema->attrgrpDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003720 schema->attrgrpDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003721 if (schema->attrgrpDecl == NULL)
3722 return (NULL);
3723
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003724 ret =
3725 (xmlSchemaAttributeGroupPtr)
3726 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00003727 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003728 xmlSchemaPErrMemory(ctxt, "allocating attribute group", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003729 return (NULL);
3730 }
3731 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003732 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003733 val = xmlHashAddEntry3(schema->attrgrpDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003734 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003735 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003736 xmlSchemaPCustomErr(ctxt,
3737 XML_SCHEMAP_REDEFINED_ATTRGROUP,
3738 NULL, NULL, node,
3739 "A global attribute group definition with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003740 xmlFree(ret);
3741 return (NULL);
3742 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003743 if (ctxt->assemble != NULL)
3744 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003745 return (ret);
3746}
3747
3748/**
3749 * xmlSchemaAddElement:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003750 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003751 * @schema: the schema being built
3752 * @name: the type name
3753 * @namespace: the type namespace
3754 *
3755 * Add an XML schema Element declaration
3756 * *WARNING* this interface is highly subject to change
3757 *
3758 * Returns the new struture or NULL in case of error
3759 */
3760static xmlSchemaElementPtr
3761xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003762 const xmlChar * name, const xmlChar * namespace,
3763 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00003764{
3765 xmlSchemaElementPtr ret = NULL;
3766 int val;
3767
3768 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3769 return (NULL);
3770
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003771#ifdef DEBUG
3772 fprintf(stderr, "Adding element %s\n", name);
3773 if (namespace != NULL)
3774 fprintf(stderr, " target namespace %s\n", namespace);
3775#endif
3776
Daniel Veillard4255d502002-04-16 15:50:10 +00003777 if (schema->elemDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003778 schema->elemDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003779 if (schema->elemDecl == NULL)
3780 return (NULL);
3781
3782 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
3783 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003784 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003785 return (NULL);
3786 }
3787 memset(ret, 0, sizeof(xmlSchemaElement));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003788 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003789 val = xmlHashAddEntry3(schema->elemDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003790 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003791 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003792 if (topLevel) {
3793 xmlSchemaPCustomErr(ctxt,
3794 XML_SCHEMAP_REDEFINED_ELEMENT,
3795 NULL, NULL, node,
3796 "A global element declaration with the name '%s' does "
3797 "already exist", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003798 xmlFree(ret);
3799 return (NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00003800 } else {
3801 char buf[30];
3802
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003803 snprintf(buf, 29, "#eCont%d", ctxt->counter++ + 1);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003804 val = xmlHashAddEntry3(schema->elemDecl, name,
3805 namespace, (xmlChar *) buf, ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00003806 if (val != 0) {
3807 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003808 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00003809 NULL, NULL, node,
3810 "Internal error: xmlSchemaAddElement, "
3811 "a dublicate element declaration with the name '%s' "
3812 "could not be added to the hash.", name);
3813 xmlFree(ret);
3814 return (NULL);
3815 }
3816 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00003817
Daniel Veillard4255d502002-04-16 15:50:10 +00003818 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003819 if (ctxt->assemble != NULL)
3820 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003821 return (ret);
3822}
3823
3824/**
3825 * xmlSchemaAddType:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003826 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003827 * @schema: the schema being built
3828 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003829 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00003830 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00003831 * Add an XML schema item
Daniel Veillard4255d502002-04-16 15:50:10 +00003832 * *WARNING* this interface is highly subject to change
3833 *
3834 * Returns the new struture or NULL in case of error
3835 */
3836static xmlSchemaTypePtr
3837xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003838 const xmlChar * name, const xmlChar * namespace,
3839 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003840{
3841 xmlSchemaTypePtr ret = NULL;
3842 int val;
3843
3844 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3845 return (NULL);
3846
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003847#ifdef DEBUG
3848 fprintf(stderr, "Adding type %s\n", name);
3849 if (namespace != NULL)
3850 fprintf(stderr, " target namespace %s\n", namespace);
3851#endif
3852
Daniel Veillard4255d502002-04-16 15:50:10 +00003853 if (schema->typeDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003854 schema->typeDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003855 if (schema->typeDecl == NULL)
3856 return (NULL);
3857
3858 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
3859 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003860 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003861 return (NULL);
3862 }
3863 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003864 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003865 ret->redef = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003866 val = xmlHashAddEntry2(schema->typeDecl, name, namespace, ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00003867 if (val != 0) {
3868 if (ctxt->includes == 0) {
3869 xmlSchemaPCustomErr(ctxt,
3870 XML_SCHEMAP_REDEFINED_TYPE,
3871 NULL, NULL, node,
3872 "A global type definition with the name '%s' does already exist", name);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003873 xmlFree(ret);
3874 return (NULL);
3875 } else {
3876 xmlSchemaTypePtr prev;
3877
3878 prev = xmlHashLookup2(schema->typeDecl, name, namespace);
3879 if (prev == NULL) {
3880 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003881 XML_ERR_INTERNAL_ERROR,
3882 "Internal error: xmlSchemaAddType, on type "
3883 "'%s'.\n",
3884 name, NULL);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003885 xmlFree(ret);
3886 return (NULL);
3887 }
3888 ret->redef = prev->redef;
3889 prev->redef = ret;
3890 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003891 }
3892 ret->minOccurs = 1;
3893 ret->maxOccurs = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +00003894 ret->attributeUses = NULL;
3895 ret->attributeWildcard = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003896 if (ctxt->assemble != NULL)
3897 xmlSchemaAddAssembledItem(ctxt,ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003898 return (ret);
3899}
3900
3901/**
3902 * xmlSchemaAddGroup:
3903 * @ctxt: a schema validation context
3904 * @schema: the schema being built
3905 * @name: the group name
3906 *
3907 * Add an XML schema Group definition
3908 *
3909 * Returns the new struture or NULL in case of error
3910 */
3911static xmlSchemaTypePtr
3912xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00003913 const xmlChar *name, const xmlChar *namespaceName,
3914 xmlNodePtr node)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003915{
3916 xmlSchemaTypePtr ret = NULL;
3917 int val;
3918
3919 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3920 return (NULL);
3921
3922 if (schema->groupDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003923 schema->groupDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003924 if (schema->groupDecl == NULL)
3925 return (NULL);
3926
3927 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
3928 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003929 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003930 return (NULL);
3931 }
3932 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003933 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003934 val =
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00003935 xmlHashAddEntry2(schema->groupDecl, name, namespaceName,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003936 ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003937 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003938 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00003939 XML_SCHEMAP_REDEFINED_GROUP,
3940 NULL, NULL, node,
3941 "A global model group definition with the name '%s' does already "
3942 "exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003943 xmlFree(ret);
3944 return (NULL);
3945 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00003946 ret->targetNamespace = namespaceName;
Daniel Veillard4255d502002-04-16 15:50:10 +00003947 ret->minOccurs = 1;
3948 ret->maxOccurs = 1;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003949 if (ctxt->assemble != NULL)
3950 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003951 return (ret);
3952}
3953
Daniel Veillard3646d642004-06-02 19:19:14 +00003954/**
3955 * xmlSchemaNewWildcardNs:
3956 * @ctxt: a schema validation context
3957 *
3958 * Creates a new wildcard namespace constraint.
3959 *
3960 * Returns the new struture or NULL in case of error
3961 */
3962static xmlSchemaWildcardNsPtr
3963xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
3964{
3965 xmlSchemaWildcardNsPtr ret;
3966
3967 ret = (xmlSchemaWildcardNsPtr)
3968 xmlMalloc(sizeof(xmlSchemaWildcardNs));
3969 if (ret == NULL) {
3970 xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
3971 return (NULL);
3972 }
3973 ret->value = NULL;
3974 ret->next = NULL;
3975 return (ret);
3976}
3977
3978/**
3979 * xmlSchemaAddWildcard:
3980 * @ctxt: a schema validation context
Daniel Veillardc0826a72004-08-10 14:17:33 +00003981 * Adds a wildcard. It corresponds to a
3982 * xsd:anyAttribute and is used as storage for namespace
3983 * constraints on a xsd:any.
Daniel Veillard3646d642004-06-02 19:19:14 +00003984 *
3985 * Returns the new struture or NULL in case of error
3986 */
3987static xmlSchemaWildcardPtr
3988xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt)
3989{
3990 xmlSchemaWildcardPtr ret = NULL;
3991
3992 if (ctxt == NULL)
3993 return (NULL);
3994
3995 ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
3996 if (ret == NULL) {
3997 xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
3998 return (NULL);
3999 }
4000 memset(ret, 0, sizeof(xmlSchemaWildcard));
4001 ret->minOccurs = 1;
4002 ret->maxOccurs = 1;
4003
4004 return (ret);
4005}
4006
Daniel Veillard4255d502002-04-16 15:50:10 +00004007/************************************************************************
4008 * *
4009 * Utilities for parsing *
4010 * *
4011 ************************************************************************/
4012
4013/**
4014 * xmlGetQNameProp:
4015 * @ctxt: a schema validation context
4016 * @node: a subtree containing XML Schema informations
4017 * @name: the attribute name
4018 * @namespace: the result namespace if any
4019 *
4020 * Extract a QName Attribute value
4021 *
4022 * Returns the NCName or NULL if not found, and also update @namespace
4023 * with the namespace URI
4024 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004025static const xmlChar *
Daniel Veillard4255d502002-04-16 15:50:10 +00004026xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004027 const char *name, const xmlChar ** namespace)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004028{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004029 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00004030 xmlNsPtr ns;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004031 const xmlChar *ret, *prefix;
4032 int len;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004033 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00004034
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004035 *namespace = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004036 attr = xmlSchemaGetPropNode(node, name);
4037 if (attr == NULL)
4038 return (NULL);
4039 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004040
Daniel Veillard4255d502002-04-16 15:50:10 +00004041 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004042 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004043
Daniel Veillardba0153a2004-04-01 10:42:31 +00004044 if (!strchr((char *) val, ':')) {
Daniel Veillardebcdebd2004-03-05 00:15:50 +00004045 ns = xmlSearchNs(node->doc, node, 0);
4046 if (ns) {
4047 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
4048 return (val);
4049 }
4050 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004051 ret = xmlSplitQName3(val, &len);
4052 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004053 return (val);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004054 }
4055 ret = xmlDictLookup(ctxt->dict, ret, -1);
4056 prefix = xmlDictLookup(ctxt->dict, val, len);
Daniel Veillard4255d502002-04-16 15:50:10 +00004057
4058 ns = xmlSearchNs(node->doc, node, prefix);
4059 if (ns == NULL) {
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004060 xmlSchemaPSimpleTypeErr(ctxt, XML_SCHEMAP_PREFIX_UNDEFINED,
4061 NULL, NULL, (xmlNodePtr) attr,
4062 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, val,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004063 "The QName value '%s' has no corresponding namespace "
4064 "declaration in scope", val, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004065 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004066 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004067 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004068 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004069}
4070
4071/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00004072 * xmlSchemaPValAttrNodeQNameValue:
4073 * @ctxt: a schema parser context
4074 * @schema: the schema context
4075 * @ownerDes: the designation of the parent element
4076 * @ownerItem: the parent as a schema object
4077 * @value: the QName value
4078 * @local: the resulting local part if found, the attribute value otherwise
4079 * @uri: the resulting namespace URI if found
4080 *
4081 * Extracts the local name and the URI of a QName value and validates it.
4082 * This one is intended to be used on attribute values that
4083 * should resolve to schema components.
4084 *
4085 * Returns 0, in case the QName is valid, a positive error code
4086 * if not valid and -1 if an internal error occurs.
4087 */
4088static int
4089xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
4090 xmlSchemaPtr schema,
4091 xmlChar **ownerDes,
4092 xmlSchemaTypePtr ownerItem,
4093 xmlAttrPtr attr,
4094 const xmlChar *value,
4095 const xmlChar **uri,
4096 const xmlChar **prefix,
4097 const xmlChar **local)
4098{
4099 const xmlChar *pref;
4100 xmlNsPtr ns;
4101 int len, ret;
4102
4103 *uri = NULL;
4104 *local = NULL;
4105 if (prefix != 0)
4106 *prefix = NULL;
4107 ret = xmlValidateQName(value, 1);
4108 if (ret > 0) {
4109 xmlSchemaPSimpleTypeErr(ctxt,
4110 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4111 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004112 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
4113 "QName", value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004114 NULL, NULL, NULL);
4115 *local = value;
4116 return (ctxt->err);
4117 } else if (ret < 0)
4118 return (-1);
4119
4120 if (!strchr((char *) value, ':')) {
4121 ns = xmlSearchNs(attr->doc, attr->parent, 0);
4122 if (ns)
4123 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
4124 else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
4125 /*
4126 * This one takes care of included schemas with no
4127 * target namespace.
4128 */
4129 *uri = schema->targetNamespace;
4130 }
4131 *local = value;
4132 return (0);
4133 }
4134 /*
4135 * At this point xmlSplitQName3 has to return a local name.
4136 */
4137 *local = xmlSplitQName3(value, &len);
4138 *local = xmlDictLookup(ctxt->dict, *local, -1);
4139 pref = xmlDictLookup(ctxt->dict, value, len);
4140 if (prefix != 0)
4141 *prefix = pref;
4142 ns = xmlSearchNs(attr->doc, attr->parent, pref);
4143 if (ns == NULL) {
4144 xmlSchemaPSimpleTypeErr(ctxt,
4145 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4146 ownerDes, ownerItem, (xmlNodePtr) attr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004147 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), "QName", value,
4148 "The QName value '%s' has no corresponding namespace "
4149 "declaration in scope", value, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004150 return (ctxt->err);
4151 } else {
4152 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
4153 }
4154 return (0);
4155}
4156
4157/**
4158 * xmlSchemaPValAttrNodeQName:
4159 * @ctxt: a schema parser context
4160 * @schema: the schema context
4161 * @ownerDes: the designation of the owner element
4162 * @ownerItem: the owner as a schema object
4163 * @attr: the attribute node
4164 * @local: the resulting local part if found, the attribute value otherwise
4165 * @uri: the resulting namespace URI if found
4166 *
4167 * Extracts and validates the QName of an attribute value.
4168 * This one is intended to be used on attribute values that
4169 * should resolve to schema components.
4170 *
4171 * Returns 0, in case the QName is valid, a positive error code
4172 * if not valid and -1 if an internal error occurs.
4173 */
4174static int
4175xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
4176 xmlSchemaPtr schema,
4177 xmlChar **ownerDes,
4178 xmlSchemaTypePtr ownerItem,
4179 xmlAttrPtr attr,
4180 const xmlChar **uri,
4181 const xmlChar **prefix,
4182 const xmlChar **local)
4183{
4184 const xmlChar *value;
4185
4186 value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4187 return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
4188 ownerDes, ownerItem, attr, value, uri, prefix, local));
4189}
4190
4191/**
4192 * xmlSchemaPValAttrQName:
4193 * @ctxt: a schema parser context
4194 * @schema: the schema context
4195 * @ownerDes: the designation of the parent element
4196 * @ownerItem: the owner as a schema object
4197 * @ownerElem: the parent node of the attribute
4198 * @name: the name of the attribute
4199 * @local: the resulting local part if found, the attribute value otherwise
4200 * @uri: the resulting namespace URI if found
4201 *
4202 * Extracts and validates the QName of an attribute value.
4203 *
4204 * Returns 0, in case the QName is valid, a positive error code
4205 * if not valid and -1 if an internal error occurs.
4206 */
4207static int
4208xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
4209 xmlSchemaPtr schema,
4210 xmlChar **ownerDes,
4211 xmlSchemaTypePtr ownerItem,
4212 xmlNodePtr ownerElem,
4213 const char *name,
4214 const xmlChar **uri,
4215 const xmlChar **prefix,
4216 const xmlChar **local)
4217{
4218 xmlAttrPtr attr;
4219
4220 attr = xmlSchemaGetPropNode(ownerElem, name);
4221 if (attr == NULL) {
4222 *local = NULL;
4223 *uri = NULL;
4224 return (0);
4225 }
4226 return (xmlSchemaPValAttrNodeQName(ctxt, schema,
4227 ownerDes, ownerItem, attr, uri, prefix, local));
4228}
4229
4230/**
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00004231 * xmlSchemaPValAttrID:
4232 * @ctxt: a schema parser context
4233 * @schema: the schema context
4234 * @ownerDes: the designation of the parent element
4235 * @ownerItem: the owner as a schema object
4236 * @ownerElem: the parent node of the attribute
4237 * @name: the name of the attribute
4238 *
4239 * Extracts and validates the ID of an attribute value.
4240 *
4241 * Returns 0, in case the ID is valid, a positive error code
4242 * if not valid and -1 if an internal error occurs.
4243 */
4244static int
4245xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,
4246 xmlChar **ownerDes,
4247 xmlSchemaTypePtr ownerItem,
4248 xmlNodePtr ownerElem,
4249 const xmlChar *name)
4250{
4251 int ret;
4252 xmlChar *value;
4253 xmlAttrPtr attr;
4254
4255 value = xmlGetNoNsProp(ownerElem, name);
4256 if (value == NULL)
4257 return (0);
4258
4259 attr = xmlSchemaGetPropNode(ownerElem, (const char *) name);
4260 if (attr == NULL)
4261 return (-1);
4262
4263 ret = xmlValidateNCName(BAD_CAST value, 1);
4264 if (ret == 0) {
4265 /*
4266 * NOTE: the IDness might have already be declared in the DTD
4267 */
4268 if (attr->atype != XML_ATTRIBUTE_ID) {
4269 xmlIDPtr res;
4270 xmlChar *strip;
4271
4272 /*
4273 * TODO: Use xmlSchemaStrip here; it's not exported at this
4274 * moment.
4275 */
4276 strip = xmlSchemaCollapseString(BAD_CAST value);
4277 if (strip != NULL)
4278 value = strip;
4279 res = xmlAddID(NULL, ownerElem->doc, BAD_CAST value, attr);
4280 if (res == NULL) {
4281 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
4282 xmlSchemaPSimpleTypeErr(ctxt,
4283 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4284 ownerDes, ownerItem, (xmlNodePtr) attr,
4285 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00004286 NULL, NULL, "The ID '%s' is already defined",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00004287 BAD_CAST value, NULL);
4288 } else
4289 attr->atype = XML_ATTRIBUTE_ID;
4290 if (strip != NULL)
4291 xmlFree(strip);
4292 }
4293 } else if (ret > 0) {
4294 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
4295 xmlSchemaPSimpleTypeErr(ctxt,
4296 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4297 ownerDes, ownerItem, (xmlNodePtr) attr,
4298 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
4299 NULL, BAD_CAST value, NULL, NULL, NULL);
4300 }
4301 xmlFree(value);
4302
4303 return (ret);
4304}
4305
4306/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004307 * xmlGetMaxOccurs:
4308 * @ctxt: a schema validation context
4309 * @node: a subtree containing XML Schema informations
4310 *
4311 * Get the maxOccurs property
4312 *
4313 * Returns the default if not found, or the value
4314 */
4315static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004316xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
4317 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004318{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004319 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00004320 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004321 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00004322
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004323 attr = xmlSchemaGetPropNode(node, "maxOccurs");
4324 if (attr == NULL)
4325 return (def);
4326 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00004327
4328 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004329 if (max != UNBOUNDED) {
4330 xmlSchemaPSimpleTypeErr(ctxt,
4331 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4332 /* XML_SCHEMAP_INVALID_MINOCCURS, */
4333 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
4334 val, NULL, NULL, NULL);
4335 return (def);
4336 } else
4337 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00004338 }
4339
4340 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00004341 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004342 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004343 if (*cur == 0) {
4344 xmlSchemaPSimpleTypeErr(ctxt,
4345 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4346 /* XML_SCHEMAP_INVALID_MINOCCURS, */
4347 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
4348 val, NULL, NULL, NULL);
4349 return (def);
4350 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004351 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004352 ret = ret * 10 + (*cur - '0');
4353 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00004354 }
William M. Brack76e95df2003-10-18 16:20:14 +00004355 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004356 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004357 /*
4358 * TODO: Restrict the maximal value to Integer.
4359 */
4360 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
4361 xmlSchemaPSimpleTypeErr(ctxt,
4362 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4363 /* XML_SCHEMAP_INVALID_MINOCCURS, */
4364 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
4365 val, NULL, NULL, NULL);
4366 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00004367 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004368 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004369}
4370
4371/**
4372 * xmlGetMinOccurs:
4373 * @ctxt: a schema validation context
4374 * @node: a subtree containing XML Schema informations
4375 *
4376 * Get the minOccurs property
4377 *
4378 * Returns the default if not found, or the value
4379 */
4380static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004381xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
4382 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004383{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004384 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00004385 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004386 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00004387
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004388 attr = xmlSchemaGetPropNode(node, "minOccurs");
4389 if (attr == NULL)
4390 return (def);
4391 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00004392 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00004393 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004394 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004395 if (*cur == 0) {
4396 xmlSchemaPSimpleTypeErr(ctxt,
4397 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4398 /* XML_SCHEMAP_INVALID_MINOCCURS, */
4399 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
4400 val, NULL, NULL, NULL);
4401 return (def);
4402 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004403 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004404 ret = ret * 10 + (*cur - '0');
4405 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00004406 }
William M. Brack76e95df2003-10-18 16:20:14 +00004407 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004408 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004409 /*
4410 * TODO: Restrict the maximal value to Integer.
4411 */
4412 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
4413 xmlSchemaPSimpleTypeErr(ctxt,
4414 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4415 /* XML_SCHEMAP_INVALID_MINOCCURS, */
4416 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
4417 val, NULL, NULL, NULL);
4418 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00004419 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004420 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004421}
4422
4423/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004424 * xmlSchemaPGetBoolNodeValue:
4425 * @ctxt: a schema validation context
4426 * @ownerDes: owner designation
4427 * @ownerItem: the owner as a schema item
4428 * @node: the node holding the value
4429 *
4430 * Converts a boolean string value into 1 or 0.
4431 *
4432 * Returns 0 or 1.
4433 */
4434static int
4435xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
4436 xmlChar **ownerDes,
4437 xmlSchemaTypePtr ownerItem,
4438 xmlNodePtr node)
4439{
4440 xmlChar *value = NULL;
4441 int res = 0;
4442
4443 value = xmlNodeGetContent(node);
4444 /*
4445 * 3.2.2.1 Lexical representation
4446 * An instance of a datatype that is defined as ·boolean·
4447 * can have the following legal literals {true, false, 1, 0}.
4448 */
4449 if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
4450 res = 1;
4451 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
4452 res = 0;
4453 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
4454 res = 1;
4455 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
4456 res = 0;
4457 else {
4458 xmlSchemaPSimpleTypeErr(ctxt,
4459 XML_SCHEMAP_INVALID_BOOLEAN,
4460 ownerDes, ownerItem, node,
4461 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
4462 "(1 | 0 | true | false)", BAD_CAST value,
4463 NULL, NULL, NULL);
4464 }
4465 if (value != NULL)
4466 xmlFree(value);
4467 return (res);
4468}
4469
4470/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004471 * xmlGetBooleanProp:
4472 * @ctxt: a schema validation context
4473 * @node: a subtree containing XML Schema informations
4474 * @name: the attribute name
4475 * @def: the default value
4476 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00004477 * Evaluate if a boolean property is set
Daniel Veillard4255d502002-04-16 15:50:10 +00004478 *
4479 * Returns the default if not found, 0 if found to be false,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004480 * 1 if found to be true
Daniel Veillard4255d502002-04-16 15:50:10 +00004481 */
4482static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00004483xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
4484 xmlChar **ownerDes,
4485 xmlSchemaTypePtr ownerItem,
4486 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004487 const char *name, int def)
4488{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004489 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00004490
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004491 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004492 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004493 return (def);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004494 /*
4495 * 3.2.2.1 Lexical representation
4496 * An instance of a datatype that is defined as ·boolean·
4497 * can have the following legal literals {true, false, 1, 0}.
4498 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004499 if (xmlStrEqual(val, BAD_CAST "true"))
4500 def = 1;
4501 else if (xmlStrEqual(val, BAD_CAST "false"))
4502 def = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004503 else if (xmlStrEqual(val, BAD_CAST "1"))
4504 def = 1;
4505 else if (xmlStrEqual(val, BAD_CAST "0"))
4506 def = 0;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00004507 else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004508 xmlSchemaPSimpleTypeErr(ctxt,
4509 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00004510 ownerDes, ownerItem,
4511 (xmlNodePtr) xmlSchemaGetPropNode(node, name),
William M. Brack2f2a6632004-08-20 23:09:47 +00004512 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
4513 "(1 | 0 | true | false)", val, NULL, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004514 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004515 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00004516}
4517
4518/************************************************************************
4519 * *
4520 * Shema extraction from an Infoset *
4521 * *
4522 ************************************************************************/
4523static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
4524 ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00004525 xmlNodePtr node,
4526 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004527static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
4528 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00004529 xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00004530 xmlNodePtr node,
4531 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004532static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
4533 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00004534 xmlSchemaPtr schema,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00004535 xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00004536static xmlSchemaTypePtr xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt,
4537 xmlSchemaPtr schema,
4538 xmlNodePtr node);
4539static xmlSchemaTypePtr xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt,
4540 xmlSchemaPtr schema,
4541 xmlNodePtr node);
4542static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
4543 ctxt,
4544 xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00004545 xmlNodePtr node,
4546 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00004547static xmlSchemaAttributeGroupPtr
4548xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00004549 xmlSchemaPtr schema, xmlNodePtr node,
4550 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00004551static xmlSchemaTypePtr xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt,
4552 xmlSchemaPtr schema,
4553 xmlNodePtr node);
4554static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
4555 xmlSchemaPtr schema,
4556 xmlNodePtr node);
Daniel Veillard3646d642004-06-02 19:19:14 +00004557static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004558xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
4559 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00004560
4561/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004562 * xmlSchemaPValAttrNodeValue:
Daniel Veillard01fa6152004-06-29 17:04:39 +00004563 *
4564 * @ctxt: a schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00004565 * @ownerDes: the designation of the parent element
4566 * @ownerItem: the schema object owner if existent
4567 * @attr: the schema attribute node being validated
4568 * @value: the value
4569 * @type: the built-in type to be validated against
Daniel Veillard01fa6152004-06-29 17:04:39 +00004570 *
4571 * Validates a value against the given built-in type.
4572 * This one is intended to be used internally for validation
4573 * of schema attribute values during parsing of the schema.
4574 *
4575 * Returns 0 if the value is valid, a positive error code
4576 * number otherwise and -1 in case of an internal or API error.
4577 */
4578static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00004579xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr ctxt,
4580 xmlChar **ownerDes,
4581 xmlSchemaTypePtr ownerItem,
4582 xmlAttrPtr attr,
4583 const xmlChar *value,
4584 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +00004585{
Daniel Veillard01fa6152004-06-29 17:04:39 +00004586
Daniel Veillardc0826a72004-08-10 14:17:33 +00004587 int ret = 0;
4588
4589 /*
4590 * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
4591 * one is really meant to be used internally, so better not.
4592 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00004593 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00004594 return (-1);
4595 if (type->type != XML_SCHEMA_TYPE_BASIC) {
4596 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004597 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004598 "Internal error: xmlSchemaPValAttrNodeValue, the given "
Daniel Veillardc0826a72004-08-10 14:17:33 +00004599 "type '%s' is not a built-in type.\n",
4600 type->name, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00004601 return (-1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004602 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00004603 switch (type->builtInType) {
4604 case XML_SCHEMAS_NCNAME:
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004605 case XML_SCHEMAS_QNAME:
4606 case XML_SCHEMAS_ANYURI:
4607 case XML_SCHEMAS_TOKEN:
4608 case XML_SCHEMAS_LANGUAGE:
4609 ret = xmlSchemaValPredefTypeNode(type, value, NULL, (xmlNodePtr) attr);
4610 break;
4611
4612 /*
4613 case XML_SCHEMAS_NCNAME:
Daniel Veillard01fa6152004-06-29 17:04:39 +00004614 ret = xmlValidateNCName(value, 1);
4615 break;
4616 case XML_SCHEMAS_QNAME:
Daniel Veillardc0826a72004-08-10 14:17:33 +00004617 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004618 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004619 "Internal error: xmlSchemaPvalueAttrNode, use "
4620 "the function xmlSchemaExtractSchemaQNamePropvalueidated "
4621 "for extracting QName valueues instead.\n",
4622 NULL, NULL);
4623 return (-1);
4624 case XML_SCHEMAS_ANYURI:
4625 if (value != NULL) {
4626 xmlURIPtr uri = xmlParseURI((const char *) value);
4627 if (uri == NULL)
4628 ret = 1;
4629 else
4630 xmlFreeURI(uri);
Daniel Veillard01fa6152004-06-29 17:04:39 +00004631 }
4632 break;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004633 case XML_SCHEMAS_TOKEN: {
4634 const xmlChar *cur = value;
4635
4636 if (IS_BLANK_CH(*cur)) {
4637 ret = 1;
4638 } else while (*cur != 0) {
4639 if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) {
4640 ret = 1;
4641 break;
4642 } else if (*cur == ' ') {
4643 cur++;
4644 if ((*cur == 0) || (*cur == ' ')) {
4645 ret = 1;
4646 break;
4647 }
4648 } else {
4649 cur++;
4650 }
4651 }
4652 }
4653 break;
4654 case XML_SCHEMAS_LANGUAGE:
4655 if (xmlCheckLanguageID(value) != 1)
4656 ret = 1;
4657 break;
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004658 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00004659 default: {
4660 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004661 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004662 "Internal error: xmlSchemaPValAttrNodeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +00004663 "valueidation using the type '%s' is not implemented "
4664 "yet.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +00004665 type->name, NULL);
4666 return (-1);
4667 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004668 }
4669 /*
4670 * TODO: Should we use the S4S error codes instead?
4671 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004672 if (ret < 0) {
4673 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
4674 XML_SCHEMAP_INTERNAL,
4675 "Internal error: xmlSchemaPValAttrNodeValue, "
4676 "failed to validate a schema attribute value.\n",
4677 NULL, NULL);
4678 return (-1);
4679 } else if (ret > 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004680 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
4681 xmlSchemaPSimpleTypeErr(ctxt,
4682 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2,
4683 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004684 type, NULL, value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004685 NULL, NULL, NULL);
4686 return(XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2);
4687 } else {
4688 xmlSchemaPSimpleTypeErr(ctxt,
4689 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
4690 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004691 type, NULL, value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004692 NULL, NULL, NULL);
4693 return(XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
4694 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00004695 }
4696 return (ret);
4697}
4698
4699/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00004700 * xmlSchemaPValAttrNode:
4701 *
4702 * @ctxt: a schema parser context
4703 * @ownerDes: the designation of the parent element
4704 * @ownerItem: the schema object owner if existent
4705 * @attr: the schema attribute node being validated
4706 * @type: the built-in type to be validated against
4707 * @value: the resulting value if any
4708 *
4709 * Extracts and validates a value against the given built-in type.
4710 * This one is intended to be used internally for validation
4711 * of schema attribute values during parsing of the schema.
4712 *
4713 * Returns 0 if the value is valid, a positive error code
4714 * number otherwise and -1 in case of an internal or API error.
4715 */
4716static int
4717xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
4718 xmlChar **ownerDes,
4719 xmlSchemaTypePtr ownerItem,
4720 xmlAttrPtr attr,
4721 xmlSchemaTypePtr type,
4722 const xmlChar **value)
4723{
4724 const xmlChar *val;
4725
4726 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
4727 return (-1);
4728
4729 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4730 if (value != NULL)
4731 *value = val;
4732
4733 return (xmlSchemaPValAttrNodeValue(ctxt, ownerDes, ownerItem, attr,
4734 val, type));
4735}
4736
4737/**
4738 * xmlSchemaPValAttr:
4739 *
4740 * @ctxt: a schema parser context
4741 * @node: the element node of the attribute
4742 * @ownerDes: the designation of the parent element
4743 * @ownerItem: the schema object owner if existent
4744 * @ownerElem: the owner element node
4745 * @name: the name of the schema attribute node
4746 * @type: the built-in type to be validated against
4747 * @value: the resulting value if any
4748 *
4749 * Extracts and validates a value against the given built-in type.
4750 * This one is intended to be used internally for validation
4751 * of schema attribute values during parsing of the schema.
4752 *
4753 * Returns 0 if the value is valid, a positive error code
4754 * number otherwise and -1 in case of an internal or API error.
4755 */
4756static int
4757xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
4758 xmlChar **ownerDes,
4759 xmlSchemaTypePtr ownerItem,
4760 xmlNodePtr ownerElem,
4761 const char *name,
4762 xmlSchemaTypePtr type,
4763 const xmlChar **value)
4764{
4765 xmlAttrPtr attr;
4766
4767 if ((ctxt == NULL) || (type == NULL)) {
4768 if (value != NULL)
4769 *value = NULL;
4770 return (-1);
4771 }
4772 if (type->type != XML_SCHEMA_TYPE_BASIC) {
4773 if (value != NULL)
4774 *value = NULL;
4775 xmlSchemaPErr(ctxt, ownerElem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004776 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004777 "Internal error: xmlSchemaPValAttr, the given "
4778 "type '%s' is not a built-in type.\n",
4779 type->name, NULL);
4780 return (-1);
4781 }
4782 attr = xmlSchemaGetPropNode(ownerElem, name);
4783 if (attr == NULL) {
4784 if (value != NULL)
4785 *value = NULL;
4786 return (0);
4787 }
4788 return (xmlSchemaPValAttrNode(ctxt, ownerDes, ownerItem, attr,
4789 type, value));
4790}
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00004791
4792static int
4793xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,
4794 xmlSchemaPtr schema,
4795 xmlNodePtr node,
4796 xmlSchemaTypePtr item,
4797 const xmlChar *namespaceName)
4798{
4799 if (xmlStrEqual(schema->targetNamespace, namespaceName))
4800 return (1);
4801 if (pctxt->localImports != NULL) {
4802 int i;
4803 for (i = 0; i < pctxt->nbLocalImports; i++)
4804 if (xmlStrEqual(namespaceName, pctxt->localImports[i]))
4805 return (1);
4806 }
4807 if (namespaceName == NULL)
4808 xmlSchemaPCustomErr(pctxt, XML_SCHEMAP_SRC_RESOLVE,
4809 NULL, item, node, "References from this schema to components in no "
4810 "namespace are not valid, since not indicated by an import "
4811 "statement", NULL);
4812 else
4813 xmlSchemaPCustomErr(pctxt, XML_SCHEMAP_SRC_RESOLVE,
4814 NULL, item, node, "References from this schema to components in the "
4815 "namespace '%s' are not valid, since not indicated by an import "
4816 "statement", namespaceName);
4817 return (0);
4818}
4819
Daniel Veillardc0826a72004-08-10 14:17:33 +00004820/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004821 * xmlSchemaParseAttrDecls:
4822 * @ctxt: a schema validation context
4823 * @schema: the schema being built
4824 * @node: a subtree containing XML Schema informations
4825 * @type: the hosting type
4826 *
4827 * parse a XML schema attrDecls declaration corresponding to
4828 * <!ENTITY % attrDecls
4829 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
4830 */
4831static xmlNodePtr
4832xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4833 xmlNodePtr child, xmlSchemaTypePtr type)
4834{
4835 xmlSchemaAttributePtr lastattr, attr;
4836
4837 lastattr = NULL;
4838 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004839 (IS_SCHEMA(child, "attributeGroup"))) {
4840 attr = NULL;
4841 if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00004842 attr = xmlSchemaParseAttribute(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004843 } else if (IS_SCHEMA(child, "attributeGroup")) {
4844 attr = (xmlSchemaAttributePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00004845 xmlSchemaParseAttributeGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004846 }
4847 if (attr != NULL) {
4848 if (lastattr == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00004849 if (type->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
4850 ((xmlSchemaAttributeGroupPtr) type)->attributes = attr;
4851 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004852 type->attributes = attr;
4853 lastattr = attr;
4854 } else {
4855 lastattr->next = attr;
4856 lastattr = attr;
4857 }
4858 }
4859 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004860 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004861 return (child);
Daniel Veillard4255d502002-04-16 15:50:10 +00004862}
4863
4864/**
4865 * xmlSchemaParseAnnotation:
4866 * @ctxt: a schema validation context
4867 * @schema: the schema being built
4868 * @node: a subtree containing XML Schema informations
4869 *
4870 * parse a XML schema Attrribute declaration
4871 * *WARNING* this interface is highly subject to change
4872 *
William M. Bracke7091952004-05-11 15:09:58 +00004873 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00004874 * 1 in case of success.
4875 */
4876static xmlSchemaAnnotPtr
4877xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4878 xmlNodePtr node)
4879{
4880 xmlSchemaAnnotPtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004881 xmlNodePtr child = NULL;
4882 xmlAttrPtr attr;
4883 int barked = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00004884
Daniel Veillardc0826a72004-08-10 14:17:33 +00004885 /*
4886 * INFO: S4S completed.
4887 */
4888 /*
4889 * id = ID
4890 * {any attributes with non-schema namespace . . .}>
4891 * Content: (appinfo | documentation)*
4892 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004893 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4894 return (NULL);
4895 ret = xmlSchemaNewAnnot(ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004896 attr = node->properties;
4897 while (attr != NULL) {
4898 if (((attr->ns == NULL) &&
4899 (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
4900 ((attr->ns != NULL) &&
4901 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
4902
4903 xmlSchemaPIllegalAttrErr(ctxt,
4904 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4905 NULL, NULL, attr);
4906 }
4907 attr = attr->next;
4908 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00004909 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00004910 /*
4911 * And now for the children...
4912 */
4913 child = node->children;
4914 while (child != NULL) {
4915 if (IS_SCHEMA(child, "appinfo")) {
4916 /* TODO: make available the content of "appinfo". */
4917 /*
4918 * source = anyURI
4919 * {any attributes with non-schema namespace . . .}>
4920 * Content: ({any})*
4921 */
4922 attr = child->properties;
4923 while (attr != NULL) {
4924 if (((attr->ns == NULL) &&
4925 (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
4926 ((attr->ns != NULL) &&
4927 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004928
Daniel Veillardc0826a72004-08-10 14:17:33 +00004929 xmlSchemaPIllegalAttrErr(ctxt,
4930 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4931 NULL, NULL, attr);
4932 }
4933 attr = attr->next;
4934 }
4935 xmlSchemaPValAttr(ctxt, NULL, NULL, child, "source",
4936 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
4937 child = child->next;
4938 } else if (IS_SCHEMA(child, "documentation")) {
4939 /* TODO: make available the content of "documentation". */
4940 /*
4941 * source = anyURI
4942 * {any attributes with non-schema namespace . . .}>
4943 * Content: ({any})*
4944 */
4945 attr = child->properties;
4946 while (attr != NULL) {
4947 if (attr->ns == NULL) {
4948 if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
4949 xmlSchemaPIllegalAttrErr(ctxt,
4950 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4951 NULL, NULL, attr);
4952 }
4953 } else {
4954 if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
4955 (xmlStrEqual(attr->name, BAD_CAST "lang") &&
4956 (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
4957
4958 xmlSchemaPIllegalAttrErr(ctxt,
4959 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4960 NULL, NULL, attr);
4961 }
4962 }
4963 attr = attr->next;
4964 }
4965 /*
4966 * Attribute "xml:lang".
4967 */
4968 attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
4969 if (attr != NULL)
4970 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
4971 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
4972 child = child->next;
4973 } else {
4974 if (!barked)
4975 xmlSchemaPContentErr(ctxt,
4976 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
4977 NULL, NULL, node, child, NULL, "(appinfo | documentation)*");
4978 barked = 1;
4979 child = child->next;
4980 }
4981 }
4982
Daniel Veillard4255d502002-04-16 15:50:10 +00004983 return (ret);
4984}
4985
4986/**
4987 * xmlSchemaParseFacet:
4988 * @ctxt: a schema validation context
4989 * @schema: the schema being built
4990 * @node: a subtree containing XML Schema informations
4991 *
4992 * parse a XML schema Facet declaration
4993 * *WARNING* this interface is highly subject to change
4994 *
4995 * Returns the new type structure or NULL in case of error
4996 */
4997static xmlSchemaFacetPtr
4998xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004999 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005000{
5001 xmlSchemaFacetPtr facet;
5002 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005003 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00005004
5005 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5006 return (NULL);
5007
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00005008 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005009 if (facet == NULL) {
5010 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
5011 return (NULL);
5012 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005013 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005014 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00005015 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005016 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
5017 "Facet %s has no value\n", node->name, NULL);
5018 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00005019 return (NULL);
5020 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005021 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005022 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005023 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005024 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005025 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005026 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005027 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005028 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005029 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005030 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005031 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005032 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005033 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005034 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005035 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005036 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005037 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005038 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005039 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005040 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005041 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005042 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
5043 } else if (IS_SCHEMA(node, "minLength")) {
5044 facet->type = XML_SCHEMA_FACET_MINLENGTH;
5045 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005046 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
5047 "Unknown facet type %s\n", node->name, NULL);
5048 xmlSchemaFreeFacet(facet);
5049 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005050 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005051 xmlSchemaPValAttrID(ctxt, NULL,
5052 (xmlSchemaTypePtr) facet, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00005053 facet->value = value;
Daniel Veillard01fa6152004-06-29 17:04:39 +00005054 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
5055 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
5056 const xmlChar *fixed;
5057
5058 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
5059 if (fixed != NULL) {
5060 if (xmlStrEqual(fixed, BAD_CAST "true"))
5061 facet->fixed = 1;
5062 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005063 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005064 child = node->children;
5065
5066 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005067 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5068 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005069 }
5070 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005071 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
5072 "Facet %s has unexpected child content\n",
5073 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005074 }
5075 return (facet);
5076}
5077
5078/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005079 * xmlSchemaParseWildcardNs:
5080 * @ctxt: a schema parser context
5081 * @wildc: the wildcard, already created
5082 * @node: a subtree containing XML Schema informations
5083 *
5084 * Parses the attribute "processContents" and "namespace"
5085 * of a xsd:anyAttribute and xsd:any.
5086 * *WARNING* this interface is highly subject to change
5087 *
5088 * Returns 0 if everything goes fine, a positive error code
5089 * if something is not valid and -1 if an internal error occurs.
5090 */
5091static int
5092xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
5093 xmlSchemaPtr schema,
5094 xmlSchemaWildcardPtr wildc,
5095 xmlNodePtr node)
5096{
5097 const xmlChar *pc, *ns, *dictnsItem;
5098 int ret = 0;
5099 xmlChar *nsItem;
5100 xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
5101 xmlAttrPtr attr;
5102
5103 pc = xmlSchemaGetProp(ctxt, node, "processContents");
5104 if ((pc == NULL)
5105 || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
5106 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
5107 } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
5108 wildc->processContents = XML_SCHEMAS_ANY_SKIP;
5109 } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
5110 wildc->processContents = XML_SCHEMAS_ANY_LAX;
5111 } else {
5112 xmlSchemaPSimpleTypeErr(ctxt,
5113 XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD,
5114 NULL, NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00005115 NULL, "(strict | skip | lax)", pc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005116 NULL, NULL, NULL);
5117 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
5118 ret = XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD;
5119 }
5120 /*
5121 * Build the namespace constraints.
5122 */
5123 attr = xmlSchemaGetPropNode(node, "namespace");
5124 ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5125 if ((ns == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
5126 wildc->any = 1;
5127 else if (xmlStrEqual(ns, BAD_CAST "##other")) {
5128 wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
5129 if (wildc->negNsSet == NULL) {
5130 return (-1);
5131 }
5132 wildc->negNsSet->value = schema->targetNamespace;
5133 } else {
5134 const xmlChar *end, *cur;
5135
5136 cur = ns;
5137 do {
5138 while (IS_BLANK_CH(*cur))
5139 cur++;
5140 end = cur;
5141 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
5142 end++;
5143 if (end == cur)
5144 break;
5145 nsItem = xmlStrndup(cur, end - cur);
5146 if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
5147 (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
5148 xmlSchemaPSimpleTypeErr(ctxt,
5149 XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
5150 NULL, NULL, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005151 NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005152 "((##any | ##other) | List of (anyURI | "
5153 "(##targetNamespace | ##local)))",
5154 nsItem, NULL, NULL, NULL);
5155 ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
5156 } else {
5157 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
5158 dictnsItem = schema->targetNamespace;
5159 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
5160 dictnsItem = NULL;
5161 } else {
5162 /*
5163 * Validate the item (anyURI).
5164 */
5165 xmlSchemaPValAttrNodeValue(ctxt, NULL, NULL, attr,
5166 nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
5167 dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
5168 }
5169 /*
5170 * Avoid dublicate namespaces.
5171 */
5172 tmp = wildc->nsSet;
5173 while (tmp != NULL) {
5174 if (dictnsItem == tmp->value)
5175 break;
5176 tmp = tmp->next;
5177 }
5178 if (tmp == NULL) {
5179 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
5180 if (tmp == NULL) {
5181 xmlFree(nsItem);
5182 return (-1);
5183 }
5184 tmp->value = dictnsItem;
5185 tmp->next = NULL;
5186 if (wildc->nsSet == NULL)
5187 wildc->nsSet = tmp;
5188 else
5189 lastNs->next = tmp;
5190 lastNs = tmp;
5191 }
5192
5193 }
5194 xmlFree(nsItem);
5195 cur = end;
5196 } while (*cur != 0);
5197 }
5198 return (ret);
5199}
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005200
5201static int
5202xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
5203 xmlSchemaTypePtr item,
5204 xmlNodePtr node,
5205 int minOccurs,
5206 int maxOccurs) {
5207
5208 if (maxOccurs != UNBOUNDED) {
5209 /*
5210 * TODO: Maby we should better not create the particle,
5211 * if min/max is invalid, since it could confuse the build of the
5212 * content model.
5213 */
5214 /*
5215 * 3.9.6 Schema Component Constraint: Particle Correct
5216 *
5217 */
5218 if (maxOccurs < 1) {
5219 /*
5220 * 2.2 {max occurs} must be greater than or equal to 1.
5221 */
5222 xmlSchemaPCustomAttrErr(ctxt,
5223 XML_SCHEMAP_P_PROPS_CORRECT_2_2,
5224 NULL, item, xmlSchemaGetPropNode(node, "maxOccurs"),
5225 "The value must be greater than or equal to 1");
5226 return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
5227 } else if (minOccurs > maxOccurs) {
5228 /*
5229 * 2.1 {min occurs} must not be greater than {max occurs}.
5230 */
5231 xmlSchemaPCustomAttrErr(ctxt,
5232 XML_SCHEMAP_P_PROPS_CORRECT_2_1,
5233 NULL, item, xmlSchemaGetPropNode(node, "minOccurs"),
5234 "The value must not be greater than the value of 'maxOccurs'");
5235 return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
5236 }
5237 }
5238 return (0);
5239}
5240
Daniel Veillardc0826a72004-08-10 14:17:33 +00005241/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005242 * xmlSchemaParseAny:
5243 * @ctxt: a schema validation context
5244 * @schema: the schema being built
5245 * @node: a subtree containing XML Schema informations
5246 *
5247 * parse a XML schema Any declaration
5248 * *WARNING* this interface is highly subject to change
5249 *
5250 * Returns the new type structure or NULL in case of error
5251 */
5252static xmlSchemaTypePtr
5253xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5254 xmlNodePtr node)
5255{
5256 xmlSchemaTypePtr type;
5257 xmlNodePtr child = NULL;
5258 xmlChar name[30];
Daniel Veillardc0826a72004-08-10 14:17:33 +00005259 xmlSchemaWildcardPtr wildc;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005260 int minOccurs, maxOccurs;
Daniel Veillard4255d502002-04-16 15:50:10 +00005261
5262 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5263 return (NULL);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005264 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
5265 "(nonNegativeInteger | unbounded)");
5266 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
5267 "nonNegativeInteger");
5268 if ((minOccurs == 0) && (maxOccurs == 0))
5269 return (NULL);
5270
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005271 snprintf((char *) name, 30, "#any%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00005272 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005273 if (type == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005274 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005275 type->node = node;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005276 type->type = XML_SCHEMA_TYPE_ANY;
5277
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005278 /*
5279 * TODO: Use a particle component here.
5280 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00005281 wildc = xmlSchemaAddWildcard(ctxt);
5282 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005283 * Check min/max sanity.
5284 */
5285 type->maxOccurs = maxOccurs;
5286 type->minOccurs = minOccurs;
5287 xmlSchemaPCheckParticleCorrect_2(ctxt, type,
5288 node, type->minOccurs, type->maxOccurs);
5289 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005290 * This is not nice, since it is won't be used as a attribute wildcard,
5291 * but better than adding a field to the structure.
5292 */
5293 type->attributeWildcard = wildc;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005294 xmlSchemaParseWildcardNs(ctxt, schema, wildc, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005295 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00005296 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005297 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5298 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005299 }
5300 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005301 xmlSchemaPErr2(ctxt, node, child,
5302 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
5303 "Sequence %s has unexpected content\n", type->name,
5304 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005305 }
5306
5307 return (type);
5308}
5309
5310/**
5311 * xmlSchemaParseNotation:
5312 * @ctxt: a schema validation context
5313 * @schema: the schema being built
5314 * @node: a subtree containing XML Schema informations
5315 *
5316 * parse a XML schema Notation declaration
5317 *
5318 * Returns the new structure or NULL in case of error
5319 */
5320static xmlSchemaNotationPtr
5321xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005322 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005323{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005324 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00005325 xmlSchemaNotationPtr ret;
5326 xmlNodePtr child = NULL;
5327
5328 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5329 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005330 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00005331 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005332 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
5333 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005334 return (NULL);
5335 }
5336 ret = xmlSchemaAddNotation(ctxt, schema, name);
5337 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005338 return (NULL);
5339 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005340 ret->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00005341
5342 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
5343 node, BAD_CAST "id");
5344
5345 if (IS_SCHEMA(child, "annotation")) {
5346 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5347 child = child->next;
5348 }
5349
Daniel Veillard4255d502002-04-16 15:50:10 +00005350 child = node->children;
5351 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005352 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5353 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005354 }
5355 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005356 xmlSchemaPErr2(ctxt, node, child,
5357 XML_SCHEMAP_UNKNOWN_NOTATION_CHILD,
5358 "notation %s has unexpected content\n", name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005359 }
5360
5361 return (ret);
5362}
5363
5364/**
5365 * xmlSchemaParseAnyAttribute:
5366 * @ctxt: a schema validation context
5367 * @schema: the schema being built
5368 * @node: a subtree containing XML Schema informations
5369 *
5370 * parse a XML schema AnyAttrribute declaration
5371 * *WARNING* this interface is highly subject to change
5372 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005373 * Returns a wildcard or NULL.
Daniel Veillard4255d502002-04-16 15:50:10 +00005374 */
Daniel Veillard3646d642004-06-02 19:19:14 +00005375static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005376xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
5377 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005378{
Daniel Veillard3646d642004-06-02 19:19:14 +00005379 xmlSchemaWildcardPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00005380 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005381 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005382
5383 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5384 return (NULL);
5385
Daniel Veillard3646d642004-06-02 19:19:14 +00005386 ret = xmlSchemaAddWildcard(ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00005387 if (ret == NULL) {
5388 return (NULL);
5389 }
William M. Bracke7091952004-05-11 15:09:58 +00005390 ret->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005391 /*
5392 * Check for illegal attributes.
5393 */
5394 attr = node->properties;
5395 while (attr != NULL) {
5396 if (attr->ns == NULL) {
5397 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5398 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
5399 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
5400 xmlSchemaPIllegalAttrErr(ctxt,
5401 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5402 NULL, NULL, attr);
5403 }
5404 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5405 xmlSchemaPIllegalAttrErr(ctxt,
5406 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5407 NULL, NULL, attr);
5408 }
5409 attr = attr->next;
5410 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005411 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
5412 node, BAD_CAST "id");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005413 /*
5414 * Parse the namespace list.
5415 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00005416 if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0) {
5417 xmlSchemaFreeWildcard(ret);
5418 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005419 }
5420 /*
5421 * And now for the children...
5422 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005423 child = node->children;
5424 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005425 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5426 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005427 }
5428 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005429 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005430 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5431 NULL, NULL, node, child,
5432 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005433 }
5434
5435 return (ret);
5436}
5437
5438
5439/**
5440 * xmlSchemaParseAttribute:
5441 * @ctxt: a schema validation context
5442 * @schema: the schema being built
5443 * @node: a subtree containing XML Schema informations
5444 *
5445 * parse a XML schema Attrribute declaration
5446 * *WARNING* this interface is highly subject to change
5447 *
William M. Bracke7091952004-05-11 15:09:58 +00005448 * Returns the attribute declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00005449 */
5450static xmlSchemaAttributePtr
5451xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00005452 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005453{
Daniel Veillardc0826a72004-08-10 14:17:33 +00005454 const xmlChar *name, *attrValue;
5455 xmlChar *repName = NULL; /* The reported designation. */
Daniel Veillard4255d502002-04-16 15:50:10 +00005456 xmlSchemaAttributePtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005457 xmlNodePtr child = NULL;
5458 xmlAttrPtr attr, nameAttr;
5459 int isRef = 0;
William M. Bracke7091952004-05-11 15:09:58 +00005460
5461 /*
5462 * Note that the w3c spec assumes the schema to be validated with schema
5463 * for schemas beforehand.
5464 *
5465 * 3.2.3 Constraints on XML Representations of Attribute Declarations
William M. Bracke7091952004-05-11 15:09:58 +00005466 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005467
5468 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5469 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005470 attr = xmlSchemaGetPropNode(node, "ref");
5471 nameAttr = xmlSchemaGetPropNode(node, "name");
5472
5473 if ((attr == NULL) && (nameAttr == NULL)) {
5474 /*
5475 * 3.2.3 : 3.1
5476 * One of ref or name must be present, but not both
5477 */
5478 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
5479 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, node, NULL,
5480 "One of the attributes 'ref' or 'name' must be present");
5481 return (NULL);
5482 }
5483 if ((topLevel) || (attr == NULL)) {
5484 if (nameAttr == NULL) {
5485 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
5486 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, node,
5487 "name", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005488 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005489 }
5490 } else
5491 isRef = 1;
5492
5493 if (isRef) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005494 char buf[50];
Daniel Veillardc0826a72004-08-10 14:17:33 +00005495 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix = NULL;
5496
5497 /*
5498 * Parse as attribute reference.
5499 */
5500 if (xmlSchemaPValAttrNodeQName(ctxt, schema,
5501 (xmlChar **) &xmlSchemaElemDesAttrRef, NULL, attr, &refNs,
5502 &refPrefix, &ref) != 0) {
5503 return (NULL);
5504 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005505 snprintf(buf, 49, "#aRef%d", ctxt->counter++ + 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005506 name = (const xmlChar *) buf;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005507 ret = xmlSchemaAddAttribute(ctxt, schema, name, NULL, node, 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005508 if (ret == NULL) {
5509 if (repName != NULL)
5510 xmlFree(repName);
5511 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005512 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005513 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
5514 ret->node = node;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005515 ret->refNs = refNs;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005516 ret->refPrefix = refPrefix;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005517 ret->ref = ref;
5518 xmlSchemaCheckReference(ctxt, schema, node, (xmlSchemaTypePtr) ret, refNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005519 /*
5520 xmlSchemaFormatTypeRep(&repName, (xmlSchemaTypePtr) ret, NULL, NULL);
5521 */
5522 if (nameAttr != NULL)
5523 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
5524 &repName, (xmlSchemaTypePtr) ret, nameAttr,
5525 "ref", "name");
5526 /*
5527 * Check for illegal attributes.
5528 */
5529 attr = node->properties;
5530 while (attr != NULL) {
5531 if (attr->ns == NULL) {
5532 if (xmlStrEqual(attr->name, BAD_CAST "type") ||
5533 xmlStrEqual(attr->name, BAD_CAST "form")) {
5534 /*
5535 * 3.2.3 : 3.2
5536 * If ref is present, then all of <simpleType>,
5537 * form and type must be absent.
5538 */
5539 xmlSchemaPIllegalAttrErr(ctxt,
5540 XML_SCHEMAP_SRC_ATTRIBUTE_3_2, &repName,
5541 (xmlSchemaTypePtr) ret, attr);
5542 } else if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
5543 (!xmlStrEqual(attr->name, BAD_CAST "use")) &&
5544 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5545 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
5546 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
5547 (!xmlStrEqual(attr->name, BAD_CAST "default"))) {
5548 xmlSchemaPIllegalAttrErr(ctxt,
5549 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5550 &repName, (xmlSchemaTypePtr) ret, attr);
5551 }
5552 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5553 xmlSchemaPIllegalAttrErr(ctxt,
5554 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5555 &repName, (xmlSchemaTypePtr) ret, attr);
5556 }
5557 attr = attr->next;
5558 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005559 } else {
William M. Bracke7091952004-05-11 15:09:58 +00005560 const xmlChar *ns = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005561
5562 /*
5563 * Parse as attribute declaration.
5564 */
5565 if (xmlSchemaPValAttrNode(ctxt,
5566 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, nameAttr,
5567 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
5568 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005569 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005570 /*
5571 xmlSchemaFormatTypeRep(&repName, NULL, xmlSchemaElemDesAttrDecl, name);
5572 */
5573 /*
5574 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
5575 */
5576 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
5577 xmlSchemaPSimpleTypeErr(ctxt,
5578 XML_SCHEMAP_NO_XMLNS,
5579 &repName, NULL, (xmlNodePtr) nameAttr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005580 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), "NCName", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005581 "The value must not match 'xmlns'",
5582 NULL, NULL);
5583 if (repName != NULL)
5584 xmlFree(repName);
5585 return (NULL);
5586 }
5587 /*
5588 * Evaluate the target namespace
5589 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005590 if (topLevel) {
5591 ns = schema->targetNamespace;
5592 } else {
5593 attr = xmlSchemaGetPropNode(node, "form");
5594 if (attr != NULL) {
5595 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5596 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
5597 ns = schema->targetNamespace;
5598 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
5599 xmlSchemaPSimpleTypeErr(ctxt,
5600 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5601 &repName, NULL, (xmlNodePtr) attr,
5602 NULL, "(qualified | unqualified)",
5603 attrValue, NULL, NULL, NULL);
5604 }
5605 } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
5606 ns = schema->targetNamespace;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005607 }
5608 ret = xmlSchemaAddAttribute(ctxt, schema, name, ns, node, topLevel);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005609 if (ret == NULL) {
5610 if (repName != NULL)
5611 xmlFree(repName);
Daniel Veillard3646d642004-06-02 19:19:14 +00005612 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005613 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005614 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005615 ret->node = node;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005616 if (topLevel)
5617 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
5618 /*
5619 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
5620 */
5621 if (xmlStrEqual(ret->targetNamespace, xmlSchemaInstanceNs)) {
5622 xmlSchemaPCustomErr(ctxt,
5623 XML_SCHEMAP_NO_XSI,
5624 &repName, (xmlSchemaTypePtr) ret, node,
5625 "The target namespace must not match '%s'",
5626 xmlSchemaInstanceNs);
5627 }
5628 /*
5629 * Check for illegal attributes.
5630 */
5631 attr = node->properties;
5632 while (attr != NULL) {
5633 if (attr->ns == NULL) {
5634 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5635 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
5636 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
5637 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
5638 (!xmlStrEqual(attr->name, BAD_CAST "type"))) {
5639 if ((topLevel) ||
5640 ((!xmlStrEqual(attr->name, BAD_CAST "form")) &&
5641 (!xmlStrEqual(attr->name, BAD_CAST "use")))) {
5642 xmlSchemaPIllegalAttrErr(ctxt,
5643 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5644 &repName, (xmlSchemaTypePtr) ret, attr);
5645 }
5646 }
5647 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5648 xmlSchemaPIllegalAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5649 &repName, (xmlSchemaTypePtr) ret, attr);
5650 }
5651 attr = attr->next;
5652 }
5653 xmlSchemaPValAttrQName(ctxt, schema, &repName, (xmlSchemaTypePtr) ret,
5654 node, "type", &ret->typeNs, NULL, &ret->typeName);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005655 }
5656 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
5657 node, BAD_CAST "id");
William M. Bracke7091952004-05-11 15:09:58 +00005658 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005659 * Attribute "fixed".
William M. Bracke7091952004-05-11 15:09:58 +00005660 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00005661 ret->defValue = xmlSchemaGetProp(ctxt, node, "fixed");
5662 if (ret->defValue != NULL)
5663 ret->flags |= XML_SCHEMAS_ATTR_FIXED;
5664 /*
5665 * Attribute "default".
5666 */
5667 attr = xmlSchemaGetPropNode(node, "default");
5668 if (attr != NULL) {
5669 /*
5670 * 3.2.3 : 1
5671 * default and fixed must not both be present.
5672 */
5673 if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
5674 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
5675 &repName, (xmlSchemaTypePtr) ret, attr, "default", "fixed");
5676 } else
5677 ret->defValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5678 }
5679 if (topLevel == 0) {
5680 /*
5681 * Attribute "use".
5682 */
5683 attr = xmlSchemaGetPropNode(node, "use");
5684 if (attr != NULL) {
5685 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5686 if (xmlStrEqual(attrValue, BAD_CAST "optional"))
5687 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
5688 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
5689 ret->occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
5690 else if (xmlStrEqual(attrValue, BAD_CAST "required"))
5691 ret->occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
5692 else
5693 xmlSchemaPSimpleTypeErr(ctxt,
5694 XML_SCHEMAP_INVALID_ATTR_USE,
5695 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005696 NULL, "(optional | prohibited | required)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00005697 attrValue, NULL, NULL, NULL);
5698 } else
5699 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
5700 /*
5701 * 3.2.3 : 2
5702 * If default and use are both present, use must have
5703 * the actual value optional.
5704 */
5705 if ((ret->occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
5706 (ret->defValue != NULL) &&
5707 ((ret->flags & XML_SCHEMAS_ATTR_FIXED) == 0)) {
5708 xmlSchemaPSimpleTypeErr(ctxt,
5709 XML_SCHEMAP_SRC_ATTRIBUTE_2,
5710 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005711 NULL, "(optional | prohibited | required)", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005712 "The value must be 'optional' if the attribute "
5713 "'default' is present as well", NULL, NULL);
5714 }
5715 }
5716 /*
5717 * And now for the children...
5718 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005719 child = node->children;
5720 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005721 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5722 child = child->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005723 }
5724 if (isRef) {
5725 if (child != NULL) {
5726 if (IS_SCHEMA(child, "simpleType"))
5727 /*
5728 * 3.2.3 : 3.2
5729 * If ref is present, then all of <simpleType>,
5730 * form and type must be absent.
5731 */
5732 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
5733 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
5734 "(annotation?)");
5735 else
5736 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5737 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
5738 "(annotation?)");
5739 }
5740 } else {
5741 if (IS_SCHEMA(child, "simpleType")) {
5742 if (ret->typeName != NULL) {
5743 /*
5744 * 3.2.3 : 4
5745 * type and <simpleType> must not both be present.
5746 */
5747 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
5748 &repName, (xmlSchemaTypePtr) ret, node, child,
5749 "The attribute 'type' and the <simpleType> child "
5750 "are mutually exclusive", NULL);
5751 } else
5752 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
5753 child = child->next;
5754 }
5755 if (child != NULL)
5756 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5757 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
5758 "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005759 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005760 /*
5761 * Cleanup.
5762 */
5763 if (repName != NULL)
5764 xmlFree(repName);
Daniel Veillard4255d502002-04-16 15:50:10 +00005765 return (ret);
5766}
5767
5768/**
5769 * xmlSchemaParseAttributeGroup:
5770 * @ctxt: a schema validation context
5771 * @schema: the schema being built
5772 * @node: a subtree containing XML Schema informations
5773 *
5774 * parse a XML schema Attribute Group declaration
5775 * *WARNING* this interface is highly subject to change
5776 *
5777 * Returns the attribute group or NULL in case of error.
5778 */
5779static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005780xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00005781 xmlSchemaPtr schema, xmlNodePtr node,
5782 int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005783{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005784 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00005785 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00005786 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005787 const xmlChar *oldcontainer;
5788 xmlAttrPtr attr, nameAttr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005789
5790 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5791 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005792
5793 nameAttr = xmlSchemaGetPropNode(node, "name");
5794 attr = xmlSchemaGetPropNode(node, "ref");
5795 if ((topLevel) || (attr == NULL)) {
5796 /*
5797 * Parse as an attribute group definition.
5798 * Note that those are allowed at top level only.
5799 */
5800 if (nameAttr == NULL) {
5801 xmlSchemaPMissingAttrErr(ctxt,
5802 XML_SCHEMAP_S4S_ATTR_MISSING,
5803 NULL, NULL, node, "name", NULL);
5804 return (NULL);
5805 }
5806 name = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) nameAttr);
5807 /*
5808 * The name is crucial, exit if invalid.
5809 */
5810 if (xmlSchemaPValAttrNode(ctxt,
5811 NULL, NULL, nameAttr,
5812 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
5813 return (NULL);
5814 }
5815 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
5816 if (ret == NULL)
5817 return (NULL);
5818 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
5819 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
5820 ret->node = node;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005821 ret->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005822 } else {
5823 char buf[50];
5824 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix;
5825
5826 /*
5827 * Parse as an attribute group definition reference.
5828 */
5829 if (attr == NULL) {
5830 xmlSchemaPMissingAttrErr(ctxt,
5831 XML_SCHEMAP_S4S_ATTR_MISSING,
5832 NULL, NULL, node, "ref", NULL);
5833 }
5834 xmlSchemaPValAttrNodeQName(ctxt, schema,
5835 NULL, NULL, attr, &refNs, &refPrefix, &ref);
5836
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005837 snprintf(buf, 49, "#agRef%d", ctxt->counter++ + 1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005838 name = (const xmlChar *) buf;
5839 if (name == NULL) {
5840 xmlSchemaPErrMemory(ctxt, "creating internal name for an "
5841 "attribute group definition reference", node);
5842 return (NULL);
5843 }
5844 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
5845 if (ret == NULL)
5846 return (NULL);
5847 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
5848 ret->ref = ref;
5849 ret->refNs = refNs;
5850 /* TODO: Is @refPrefix currently used? */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005851 ret->refPrefix = refPrefix;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005852 ret->node = node;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005853 xmlSchemaCheckReference(ctxt, schema, node, (xmlSchemaTypePtr) ret, refNs);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005854 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005855 /*
5856 * Check for illegal attributes.
5857 */
5858 attr = node->properties;
5859 while (attr != NULL) {
5860 if (attr->ns == NULL) {
5861 if ((((topLevel == 0) && (!xmlStrEqual(attr->name, BAD_CAST "ref"))) ||
5862 (topLevel && (!xmlStrEqual(attr->name, BAD_CAST "name")))) &&
5863 (!xmlStrEqual(attr->name, BAD_CAST "id")))
5864 {
5865 xmlSchemaPIllegalAttrErr(ctxt,
5866 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5867 NULL, NULL, attr);
5868 }
5869 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5870 xmlSchemaPIllegalAttrErr(ctxt,
5871 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5872 NULL, NULL, attr);
5873 }
5874 attr = attr->next;
5875 }
5876 /* TODO: Validate "id" ? */
5877 /*
5878 * And now for the children...
5879 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005880 oldcontainer = ctxt->container;
Daniel Veillard4255d502002-04-16 15:50:10 +00005881 ctxt->container = name;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005882 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00005883 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005884 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5885 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005886 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005887 if (topLevel) {
5888 child = xmlSchemaParseAttrDecls(ctxt, schema, child, (xmlSchemaTypePtr) ret);
5889 if (IS_SCHEMA(child, "anyAttribute")) {
5890 ret->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
5891 child = child->next;
5892 }
5893 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005894 if (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005895 xmlSchemaPContentErr(ctxt,
5896 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5897 NULL, NULL, node, child, NULL,
5898 "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005899 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005900 ctxt->container = oldcontainer;
5901 return (ret);
5902}
5903
5904/**
William M. Brack2f2a6632004-08-20 23:09:47 +00005905 * xmlSchemaPValAttrFormDefault:
5906 * @value: the value
5907 * @flags: the flags to be modified
5908 * @flagQualified: the specific flag for "qualified"
5909 *
5910 * Returns 0 if the value is valid, 1 otherwise.
5911 */
5912static int
5913xmlSchemaPValAttrFormDefault(const xmlChar *value,
5914 int *flags,
5915 int flagQualified)
5916{
5917 if (xmlStrEqual(value, BAD_CAST "qualified")) {
5918 if ((*flags & flagQualified) == 0)
5919 *flags |= flagQualified;
5920 } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
5921 return (1);
5922
5923 return (0);
5924}
5925
5926/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005927 * xmlSchemaPValAttrBlockFinal:
5928 * @value: the value
5929 * @flags: the flags to be modified
5930 * @flagAll: the specific flag for "#all"
5931 * @flagExtension: the specific flag for "extension"
5932 * @flagRestriction: the specific flag for "restriction"
5933 * @flagSubstitution: the specific flag for "substitution"
5934 * @flagList: the specific flag for "list"
5935 * @flagUnion: the specific flag for "union"
5936 *
5937 * Validates the value of the attribute "final" and "block". The value
5938 * is converted into the specified flag values and returned in @flags.
5939 *
5940 * Returns 0 if the value is valid, 1 otherwise.
5941 */
5942
5943static int
5944xmlSchemaPValAttrBlockFinal(const xmlChar *value,
5945 int *flags,
5946 int flagAll,
5947 int flagExtension,
5948 int flagRestriction,
5949 int flagSubstitution,
5950 int flagList,
5951 int flagUnion)
5952{
5953 int ret = 0;
5954
5955 /*
5956 * TODO: This does not check for dublicate entries.
5957 */
William M. Brack2f2a6632004-08-20 23:09:47 +00005958 if (value == NULL)
5959 return (1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005960 if (xmlStrEqual(value, BAD_CAST "#all")) {
5961 if (flagAll != -1)
5962 *flags |= flagAll;
5963 else {
5964 if (flagExtension != -1)
5965 *flags |= flagExtension;
5966 if (flagRestriction != -1)
5967 *flags |= flagRestriction;
5968 if (flagSubstitution != -1)
5969 *flags |= flagSubstitution;
5970 if (flagList != -1)
5971 *flags |= flagList;
5972 if (flagUnion != -1)
5973 *flags |= flagUnion;
5974 }
5975 } else {
5976 const xmlChar *end, *cur = value;
5977 xmlChar *item;
5978
5979 do {
5980 while (IS_BLANK_CH(*cur))
5981 cur++;
5982 end = cur;
5983 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
5984 end++;
5985 if (end == cur)
5986 break;
5987 item = xmlStrndup(cur, end - cur);
5988 if (xmlStrEqual(item, BAD_CAST "extension")) {
5989 if (flagExtension != -1) {
5990 if ((*flags & flagExtension) == 0)
5991 *flags |= flagExtension;
5992 } else
5993 ret = 1;
5994 } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
5995 if (flagRestriction != -1) {
5996 if ((*flags & flagRestriction) == 0)
5997 *flags |= flagRestriction;
5998 } else
5999 ret = 1;
6000 } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
6001 if (flagSubstitution != -1) {
6002 if ((*flags & flagSubstitution) == 0)
6003 *flags |= flagSubstitution;
6004 } else
6005 ret = 1;
6006 } else if (xmlStrEqual(item, BAD_CAST "list")) {
6007 if (flagList != -1) {
6008 if ((*flags & flagList) == 0)
6009 *flags |= flagList;
6010 } else
6011 ret = 1;
6012 } else if (xmlStrEqual(item, BAD_CAST "union")) {
6013 if (flagUnion != -1) {
6014 if ((*flags & flagUnion) == 0)
6015 *flags |= flagUnion;
6016 } else
6017 ret = 1;
6018 } else
6019 ret = 1;
6020 if (item != NULL)
6021 xmlFree(item);
6022 cur = end;
6023 } while ((ret == 0) && (*cur != 0));
6024 }
6025
6026 return (ret);
6027}
6028
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006029#ifdef IDC_ENABLED
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006030static int
6031xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006032 xmlSchemaIDCPtr idc,
6033 xmlSchemaIDCSelectPtr selector,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006034 xmlAttrPtr attr,
6035 int isField)
6036{
6037 xmlNodePtr node;
6038
6039 /*
6040 * c-selector-xpath:
6041 * Schema Component Constraint: Selector Value OK
6042 *
6043 * TODO: 1 The {selector} must be a valid XPath expression, as defined
6044 * in [XPath].
6045 */
6046 if (selector == NULL) {
6047 xmlSchemaPErr(ctxt, idc->node,
6048 XML_SCHEMAP_INTERNAL,
6049 "Internal error: xmlSchemaCheckCSelectorXPath, "
6050 "the selector is not specified.\n", NULL, NULL);
6051 return (-1);
6052 }
6053 if (attr == NULL)
6054 node = idc->node;
6055 else
6056 node = (xmlNodePtr) attr;
6057 if (selector->xpath == NULL) {
6058 xmlSchemaPCustomErr(ctxt,
6059 /* TODO: Adjust error code. */
6060 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6061 NULL, NULL, node,
6062 "The XPath expression of the selector is not valid", NULL);
6063 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
6064 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006065 const xmlChar **nsArray = NULL;
6066 xmlNsPtr *nsList = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006067 /*
6068 * Compile the XPath expression.
6069 */
6070 /*
6071 * TODO: We need the array of in-scope namespaces for compilation.
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006072 * TODO: Call xmlPatterncompile with different options for selector/
6073 * field.
6074 */
6075 nsList = xmlGetNsList(attr->doc, attr->parent);
6076 /*
6077 * Build an array of prefixes and namespaces.
6078 */
6079 if (nsList != NULL) {
6080 int i, count = 0;
6081 xmlNsPtr ns;
6082
6083 for (i = 0; nsList[i] != NULL; i++)
6084 count++;
6085
6086 nsArray = (const xmlChar **) xmlMalloc(
6087 (count * 2 + 1) * sizeof(const xmlChar *));
6088 if (nsArray == NULL) {
6089 xmlSchemaPErrMemory(ctxt, "allocating a namespace array",
6090 NULL);
6091 return (-1);
6092 }
6093 for (i = 0; i < count; i++) {
6094 ns = nsList[i];
6095 nsArray[2 * i] = nsList[i]->href;
6096 nsArray[2 * i + 1] = nsList[i]->prefix;
6097 }
6098 nsArray[count * 2] = NULL;
6099 xmlFree(nsList);
6100 }
6101 if (isField)
6102 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik285ebab2005-03-04 18:04:59 +00006103 NULL, 1, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006104 else
6105 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik285ebab2005-03-04 18:04:59 +00006106 NULL, 1, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006107 if (nsArray != NULL)
6108 xmlFree((xmlChar **) nsArray);
6109
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006110#ifdef IDC_XPATH_SUPPORT
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00006111 if (selector->xpathComp == NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006112 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00006113 /* TODO: Adjust error code? */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006114 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6115 NULL, NULL, node,
6116 "The XPath expression '%s' could not be "
6117 "compiled", selector->xpath);
6118 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
6119 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00006120#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006121 }
6122 return (0);
6123}
6124
6125/**
6126 * xmlSchemaAssignAnnotation:
6127 * @item: the schema component
6128 * @annot: the annotation
6129 *
6130 * Adds the annotation to the given schema component.
6131 *
6132 * Returns the given annotaion.
6133 */
6134static xmlSchemaAnnotPtr
6135xmlSchemaAssignAnnotation(xmlSchemaBasicItemPtr item,
6136 xmlSchemaAnnotPtr annot)
6137{
6138 xmlSchemaAnnotPtr cur = item->annot;
6139
6140 if (item->annot == NULL) {
6141 item->annot = annot;
6142 return (annot);
6143 }
6144 cur = item->annot;
6145 if (cur->next != NULL) {
6146 cur = cur->next;
6147 }
6148 cur->next = annot;
6149 return (annot);
6150}
6151
6152/**
6153 * xmlSchemaParseIDCSelectorAndField:
6154 * @ctxt: a schema validation context
6155 * @schema: the schema being built
6156 * @node: a subtree containing XML Schema informations
6157 *
6158 * Parses a XML Schema identity-contraint definition's
6159 * <selector> and <field> elements.
6160 *
6161 * Returns the parsed identity-constraint definition.
6162 */
6163static xmlSchemaIDCSelectPtr
6164xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
6165 xmlSchemaPtr schema,
6166 xmlSchemaIDCPtr idc,
6167 xmlNodePtr node,
6168 int isField)
6169{
6170 xmlSchemaIDCSelectPtr item;
6171 xmlNodePtr child = NULL;
6172 xmlAttrPtr attr;
6173
6174 /*
6175 * Check for illegal attributes.
6176 */
6177 attr = node->properties;
6178 while (attr != NULL) {
6179 if (attr->ns == NULL) {
6180 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6181 (!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
6182 xmlSchemaPIllegalAttrErr(ctxt,
6183 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6184 NULL, NULL, attr);
6185 }
6186 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6187 xmlSchemaPIllegalAttrErr(ctxt,
6188 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6189 NULL, NULL, attr);
6190 }
6191 attr = attr->next;
6192 }
6193 /*
6194 * Create the item.
6195 */
6196 item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
6197 if (item == NULL) {
6198 xmlSchemaPErrMemory(ctxt,
6199 "allocating a 'selector' of an identity-constraint definition",
6200 NULL);
6201 return (NULL);
6202 }
6203 memset(item, 0, sizeof(xmlSchemaIDCSelect));
6204 /*
6205 * Attribute "xpath" (mandatory).
6206 */
6207 attr = xmlSchemaGetPropNode(node, "xpath");
6208 if (attr == NULL) {
6209 xmlSchemaPMissingAttrErr(ctxt,
6210 XML_SCHEMAP_S4S_ATTR_MISSING,
6211 NULL, NULL, node,
6212 "name", NULL);
6213 } else {
6214 item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6215 /*
6216 * URGENT TODO: "field"s have an other syntax than "selector"s.
6217 */
6218
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006219 if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr,
6220 isField) == -1) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006221 xmlSchemaPErr(ctxt,
6222 (xmlNodePtr) attr,
6223 XML_SCHEMAP_INTERNAL,
6224 "Internal error: xmlSchemaParseIDCSelectorAndField, "
6225 "validating the XPath expression of a IDC selector.\n",
6226 NULL, NULL);
6227 }
6228
6229 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00006230 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006231 /*
6232 * And now for the children...
6233 */
6234 child = node->children;
6235 if (IS_SCHEMA(child, "annotation")) {
6236 /*
6237 * Add the annotation to the parent IDC.
6238 */
6239 xmlSchemaAssignAnnotation((xmlSchemaBasicItemPtr) idc,
6240 xmlSchemaParseAnnotation(ctxt, schema, child));
6241 child = child->next;
6242 }
6243 if (child != NULL) {
6244 xmlSchemaPContentErr(ctxt,
6245 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6246 NULL, NULL, node, child,
6247 NULL, "(annotation?)");
6248 }
6249
6250 return (item);
6251}
6252
6253/**
6254 * xmlSchemaParseIDC:
6255 * @ctxt: a schema validation context
6256 * @schema: the schema being built
6257 * @node: a subtree containing XML Schema informations
6258 *
6259 * Parses a XML Schema identity-contraint definition.
6260 *
6261 * Returns the parsed identity-constraint definition.
6262 */
6263static xmlSchemaIDCPtr
6264xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
6265 xmlSchemaPtr schema,
6266 xmlNodePtr node,
6267 xmlSchemaTypeType idcCategory,
6268 const xmlChar *targetNamespace)
6269{
6270 xmlSchemaIDCPtr item = NULL;
6271 xmlNodePtr child = NULL;
6272 xmlAttrPtr attr;
6273 const xmlChar *name = NULL;
6274 xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
6275 int resAdd;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00006276
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006277 /*
6278 * Check for illegal attributes.
6279 */
6280 attr = node->properties;
6281 while (attr != NULL) {
6282 if (attr->ns == NULL) {
6283 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6284 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
6285 ((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
6286 (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
6287 xmlSchemaPIllegalAttrErr(ctxt,
6288 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6289 NULL, NULL, attr);
6290 }
6291 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6292 xmlSchemaPIllegalAttrErr(ctxt,
6293 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6294 NULL, NULL, attr);
6295 }
6296 attr = attr->next;
6297 }
6298 /*
6299 * Attribute "name" (mandatory).
6300 */
6301 attr = xmlSchemaGetPropNode(node, "name");
6302 if (attr == NULL) {
6303 xmlSchemaPMissingAttrErr(ctxt,
6304 XML_SCHEMAP_S4S_ATTR_MISSING,
6305 NULL, NULL, node,
6306 "name", NULL);
6307 return (NULL);
6308 } else if (xmlSchemaPValAttrNode(ctxt,
6309 NULL, NULL, attr,
6310 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
6311 return (NULL);
6312 }
6313 /*
6314 * Create the component.
6315 */
6316 if (schema->idcDef == NULL)
6317 schema->idcDef = xmlHashCreateDict(10, ctxt->dict);
6318 if (schema->idcDef == NULL)
6319 return (NULL);
6320
6321 item = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
6322 if (item == NULL) {
6323 xmlSchemaPErrMemory(ctxt,
6324 "allocating an identity-constraint definition", NULL);
6325 return (NULL);
6326 }
6327 /*
6328 * Add the IDC to the list of IDCs on the schema component.
6329 */
6330 resAdd = xmlHashAddEntry2(schema->idcDef, name, targetNamespace, item);
6331 if (resAdd != 0) {
6332 xmlSchemaPCustomErrExt(ctxt,
6333 XML_SCHEMAP_REDEFINED_TYPE,
6334 NULL, NULL, node,
6335 "An identity-constraint definition with the name '%s' "
6336 "and targetNamespace '%s' does already exist",
6337 name, targetNamespace, NULL);
6338 xmlFree(item);
6339 return (NULL);
6340 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006341 memset(item, 0, sizeof(xmlSchemaIDC));
6342 item->name = name;
6343 item->type = idcCategory;
6344 item->node = node;
6345 /*
6346 * The target namespace of the parent element declaration.
6347 */
6348 item->targetNamespace = targetNamespace;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00006349 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) item,
6350 node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006351 if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
6352 /*
6353 * Attribute "refer" (mandatory).
6354 */
6355 attr = xmlSchemaGetPropNode(node, "refer");
6356 if (attr == NULL) {
6357 xmlSchemaPMissingAttrErr(ctxt,
6358 XML_SCHEMAP_S4S_ATTR_MISSING,
6359 NULL, NULL, node,
6360 "refer", NULL);
6361 } else {
6362 /*
6363 * Create a reference item.
6364 */
6365 item->ref = (xmlSchemaItemQNRefPtr) xmlMalloc(
6366 sizeof(xmlSchemaItemQNRef));
6367 if (item->ref == NULL) {
6368 xmlSchemaPErrMemory(ctxt,
6369 "allocating a QName reference item", NULL);
6370 return (NULL);
6371 }
6372 memset(item->ref, 0, sizeof(xmlSchemaItemQNRef));
6373 xmlSchemaPValAttrNodeQName(ctxt, schema,
6374 NULL, NULL, attr,
6375 &(item->ref->targetNamespace), 0,
6376 &(item->ref->name));
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006377 xmlSchemaCheckReference(ctxt, schema, node, (xmlSchemaTypePtr) item,
6378 item->ref->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006379 }
6380 }
6381 /*
6382 * And now for the children...
6383 */
6384 child = node->children;
6385 if (IS_SCHEMA(child, "annotation")) {
6386 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6387 child = child->next;
6388 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00006389 if (child == NULL) {
6390 xmlSchemaPContentErr(ctxt,
6391 XML_SCHEMAP_S4S_ELEM_MISSING,
6392 NULL, NULL, node, child,
6393 "A child element is missing",
6394 "(annotation?, (selector, field+))");
6395 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006396 /*
6397 * Child element <selector>.
6398 */
6399 if (IS_SCHEMA(child, "selector")) {
6400 item->selector = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
6401 item, child, 0);
6402 child = child->next;
6403 /*
6404 * Child elements <field>.
6405 */
6406 if (IS_SCHEMA(child, "field")) {
6407 do {
6408 field = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
6409 item, child, 1);
6410 if (field != NULL) {
6411 field->index = item->nbFields;
6412 item->nbFields++;
6413 if (lastField != NULL)
6414 lastField->next = field;
6415 else
6416 item->fields = field;
6417 lastField = field;
6418 }
6419 child = child->next;
6420 } while (IS_SCHEMA(child, "field"));
6421 } else {
6422 xmlSchemaPContentErr(ctxt,
6423 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6424 NULL, NULL, node, child,
6425 NULL, "(annotation?, (selector, field+))");
6426 }
6427 }
6428 if (child != NULL) {
6429 xmlSchemaPContentErr(ctxt,
6430 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6431 NULL, NULL, node, child,
6432 NULL, "(annotation?, (selector, field+))");
6433 }
6434
6435 return (item);
6436}
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006437#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006438
Daniel Veillardc0826a72004-08-10 14:17:33 +00006439/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006440 * xmlSchemaParseElement:
6441 * @ctxt: a schema validation context
6442 * @schema: the schema being built
6443 * @node: a subtree containing XML Schema informations
6444 *
6445 * parse a XML schema Element declaration
6446 * *WARNING* this interface is highly subject to change
6447 *
William M. Bracke7091952004-05-11 15:09:58 +00006448 * Returns the parsed element declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00006449 */
6450static xmlSchemaElementPtr
6451xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00006452 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006453{
Daniel Veillardc0826a72004-08-10 14:17:33 +00006454 const xmlChar *name = NULL;
6455 const xmlChar *attrValue;
6456 xmlChar *repName = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00006457 xmlSchemaElementPtr ret;
6458 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006459 const xmlChar *oldcontainer;
6460 xmlAttrPtr attr, nameAttr;
6461 int minOccurs, maxOccurs;
6462 int isRef = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006463#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006464 xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006465#endif
William M. Bracke7091952004-05-11 15:09:58 +00006466
6467 /* 3.3.3 Constraints on XML Representations of Element Declarations */
6468 /* TODO: Complete implementation of 3.3.6 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006469
Daniel Veillard4255d502002-04-16 15:50:10 +00006470 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6471 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006472
Daniel Veillardc0826a72004-08-10 14:17:33 +00006473 oldcontainer = ctxt->container;
6474
6475 nameAttr = xmlSchemaGetPropNode(node, "name");
6476 attr = xmlSchemaGetPropNode(node, "ref");
6477 if ((topLevel) || (attr == NULL)) {
6478 if (nameAttr == NULL) {
6479 xmlSchemaPMissingAttrErr(ctxt,
6480 XML_SCHEMAP_S4S_ATTR_MISSING,
6481 (xmlChar **) &xmlSchemaElemDesElemDecl, NULL, node,
6482 "name", NULL);
6483 return (NULL);
6484 }
6485 name = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) nameAttr);
6486 } else {
6487 isRef = 1;
6488
6489 }
6490 /*
6491 * ... unless minOccurs=maxOccurs=0, in which case the item corresponds
6492 * to no component at all
6493 * TODO: It might be better to validate the element, even if it won't be
6494 * used.
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006495 */
6496 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
6497 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(nonNegativeInteger | unbounded)");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006498 if ((minOccurs == 0) && (maxOccurs == 0))
6499 return (NULL);
6500 /*
6501 * If we get a "ref" attribute on a local <element> we will assume it's
6502 * a reference - even if there's a "name" attribute; this seems to be more
6503 * robust.
6504 */
6505 if (isRef) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006506 char buf[50];
Daniel Veillardc0826a72004-08-10 14:17:33 +00006507 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix;
6508
6509 /*
6510 * Parse as a particle.
6511 */
6512 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006513 (xmlChar **) &xmlSchemaElemDesElemRef,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006514 NULL, attr, &refNs, &refPrefix, &ref);
6515
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006516 snprintf(buf, 49, "#eRef%d", ctxt->counter++ + 1);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006517 ret = xmlSchemaAddElement(ctxt, schema, (const xmlChar *) buf, NULL, node, 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006518 if (ret == NULL) {
6519 if (repName != NULL)
6520 xmlFree(repName);
6521 return (NULL);
6522 }
6523 ret->type = XML_SCHEMA_TYPE_ELEMENT;
6524 ret->node = node;
6525 ret->ref = ref;
6526 ret->refNs = refNs;
6527 ret->refPrefix = refPrefix;
6528 ret->flags |= XML_SCHEMAS_ELEM_REF;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006529 xmlSchemaCheckReference(ctxt, schema, node, (xmlSchemaTypePtr) ret, refNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006530 /*
6531 * Check for illegal attributes.
6532 */
6533 /*
6534 * 3.3.3 : 2.1
6535 * One of ref or name must be present, but not both
6536 */
6537 if (nameAttr != NULL) {
6538 xmlSchemaPMutualExclAttrErr(ctxt,
6539 XML_SCHEMAP_SRC_ELEMENT_2_1,
6540 &repName, (xmlSchemaTypePtr) ret, nameAttr,
6541 "ref", "name");
6542 }
6543 /* 3.3.3 : 2.2 */
6544 attr = node->properties;
6545 while (attr != NULL) {
6546 if (attr->ns == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006547 if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
6548 xmlStrEqual(attr->name, BAD_CAST "name") ||
6549 xmlStrEqual(attr->name, BAD_CAST "id") ||
6550 xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
6551 xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
6552 {
6553 attr = attr->next;
6554 continue;
6555 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006556 xmlSchemaPCustomAttrErr(ctxt,
6557 XML_SCHEMAP_SRC_ELEMENT_2_2,
6558 &repName, (xmlSchemaTypePtr) ret, attr,
6559 "Only the attributes 'minOccurs', 'maxOccurs' and "
6560 "'id' are allowed in addition to 'ref'");
6561 break;
6562 }
6563 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6564 xmlSchemaPIllegalAttrErr(ctxt,
6565 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6566 &repName, (xmlSchemaTypePtr) ret, attr);
6567 }
6568 attr = attr->next;
6569 }
6570 } else {
6571 const xmlChar *ns = NULL, *fixed;
6572
6573 /*
6574 * Parse as an element declaration.
6575 */
6576 if (xmlSchemaPValAttrNode(ctxt,
6577 (xmlChar **) &xmlSchemaElemDesElemDecl, NULL, nameAttr,
6578 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
6579 return (NULL);
6580 /*
6581 * Evaluate the target namespace.
6582 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006583 if (topLevel) {
6584 ns = schema->targetNamespace;
6585 } else {
6586 attr = xmlSchemaGetPropNode(node, "form");
6587 if (attr != NULL) {
6588 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6589 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
William M. Bracke7091952004-05-11 15:09:58 +00006590 ns = schema->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006591 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
6592 xmlSchemaPSimpleTypeErr(ctxt,
6593 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6594 &repName, NULL, (xmlNodePtr) attr,
6595 NULL, "(qualified | unqualified)",
6596 attrValue, NULL, NULL, NULL);
6597 }
6598 } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
6599 ns = schema->targetNamespace;
William M. Brack2f2a6632004-08-20 23:09:47 +00006600 }
6601 ret = xmlSchemaAddElement(ctxt, schema, name, ns, node, topLevel);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006602 if (ret == NULL) {
6603 if (repName != NULL)
6604 xmlFree(repName);
6605 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006606 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006607 ret->type = XML_SCHEMA_TYPE_ELEMENT;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006608 ret->node = node;
6609 ret->targetNamespace = ns;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006610 /*
6611 * Check for illegal attributes.
6612 */
William M. Bracke7091952004-05-11 15:09:58 +00006613 attr = node->properties;
6614 while (attr != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006615 if (attr->ns == NULL) {
6616 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
6617 (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
6618 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6619 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
6620 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
6621 (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006622 (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
6623 {
6624 if (topLevel == 0) {
6625 if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006626 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006627 (!xmlStrEqual(attr->name, BAD_CAST "form")))
6628 {
6629 if (xmlStrEqual(attr->name, BAD_CAST "substitutionGroup")) {
6630 /*
6631 * 3.3.6 : 3 If there is a non-·absent· {substitution
6632 * group affiliation}, then {scope} must be global.
6633 * TODO: This one is redundant, since the S4S does
6634 * prohibit this attribute on local declarations already;
6635 * so why an explicit error code? Weird spec.
6636 * TODO: Move this to the proper constraint layer.
6637 * TODO: Or better wait for spec 1.1 to come.
6638 */
6639 xmlSchemaPIllegalAttrErr(ctxt,
6640 XML_SCHEMAP_E_PROPS_CORRECT_3,
6641 &repName, (xmlSchemaTypePtr) ret, attr);
6642 } else {
6643 xmlSchemaPIllegalAttrErr(ctxt,
6644 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6645 &repName, (xmlSchemaTypePtr) ret, attr);
6646 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006647 }
6648 } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
6649 (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
6650 (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
6651
6652 xmlSchemaPIllegalAttrErr(ctxt,
6653 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6654 &repName, (xmlSchemaTypePtr) ret, attr);
6655 }
6656 }
6657 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6658
6659 xmlSchemaPIllegalAttrErr(ctxt,
6660 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6661 &repName, (xmlSchemaTypePtr) ret, attr);
William M. Bracke7091952004-05-11 15:09:58 +00006662 }
6663 attr = attr->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006664 }
William M. Bracke7091952004-05-11 15:09:58 +00006665 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006666 * Extract/validate attributes.
6667 */
6668 if (topLevel) {
6669 /*
6670 * Process top attributes of global element declarations here.
6671 */
6672 ret->flags |= XML_SCHEMAS_ELEM_GLOBAL;
6673 ret->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
6674 xmlSchemaPValAttrQName(ctxt, schema, &repName,
6675 (xmlSchemaTypePtr) ret, node, "substitutionGroup",
6676 &(ret->substGroupNs), NULL, &(ret->substGroup));
6677 if (xmlGetBooleanProp(ctxt, &repName, (xmlSchemaTypePtr) ret,
6678 node, "abstract", 0))
6679 ret->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
6680 /*
6681 * Attribute "final".
6682 */
6683 attr = xmlSchemaGetPropNode(node, "final");
6684 if (attr == NULL) {
6685 ret->flags |= XML_SCHEMAS_ELEM_FINAL_ABSENT;
6686 } else {
6687 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6688 if (xmlSchemaPValAttrBlockFinal(attrValue, &(ret->flags),
6689 -1,
6690 XML_SCHEMAS_ELEM_FINAL_EXTENSION,
6691 XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
6692 xmlSchemaPSimpleTypeErr(ctxt,
6693 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6694 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00006695 NULL, "(#all | List of (extension | restriction))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00006696 attrValue, NULL, NULL, NULL);
6697 }
6698 }
6699 }
6700 /*
6701 * Attribute "block".
6702 */
6703 attr = xmlSchemaGetPropNode(node, "block");
6704 if (attr == NULL) {
6705 ret->flags |= XML_SCHEMAS_ELEM_BLOCK_ABSENT;
6706 } else {
6707 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6708 if (xmlSchemaPValAttrBlockFinal(attrValue, &(ret->flags),
6709 -1,
6710 XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
6711 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
6712 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
6713 xmlSchemaPSimpleTypeErr(ctxt,
6714 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6715 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00006716 NULL, "(#all | List of (extension | "
Daniel Veillardc0826a72004-08-10 14:17:33 +00006717 "restriction | substitution))", attrValue,
6718 NULL, NULL, NULL);
6719 }
6720 }
6721 if (xmlGetBooleanProp(ctxt, &repName, (xmlSchemaTypePtr) ret,
6722 node, "nillable", 0))
6723 ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006724
Daniel Veillardc0826a72004-08-10 14:17:33 +00006725 xmlSchemaPValAttrQName(ctxt, schema,
6726 &repName, (xmlSchemaTypePtr) ret, node,
6727 "type", &(ret->namedTypeNs), NULL, &(ret->namedType));
Daniel Veillard4255d502002-04-16 15:50:10 +00006728
Daniel Veillardc0826a72004-08-10 14:17:33 +00006729 ret->value = xmlSchemaGetProp(ctxt, node, "default");
6730 attr = xmlSchemaGetPropNode(node, "fixed");
6731 if (attr != NULL) {
6732 fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6733 if (ret->value != NULL) {
6734 /*
6735 * 3.3.3 : 1
6736 * default and fixed must not both be present.
6737 */
6738 xmlSchemaPMutualExclAttrErr(ctxt,
6739 XML_SCHEMAP_SRC_ELEMENT_1,
6740 &repName, (xmlSchemaTypePtr) ret, attr,
6741 "default", "fixed");
6742 } else {
6743 ret->flags |= XML_SCHEMAS_ELEM_FIXED;
6744 ret->value = fixed;
6745 }
6746 }
6747 }
6748 /*
6749 * Extract/validate common attributes.
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006750 */
6751 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6752 node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006753 ret->minOccurs = minOccurs;
6754 ret->maxOccurs = maxOccurs;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006755 if (topLevel != 1)
6756 xmlSchemaPCheckParticleCorrect_2(ctxt, (xmlSchemaTypePtr) ret,
6757 node, minOccurs, maxOccurs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006758 /*
6759 * And now for the children...
6760 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006761 ctxt->container = ret->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006762 child = node->children;
6763 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006764 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6765 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006766 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006767 if (isRef) {
6768 if (child != NULL) {
6769 xmlSchemaPContentErr(ctxt,
6770 XML_SCHEMAP_SRC_ELEMENT_2_2,
6771 &repName, (xmlSchemaTypePtr) ret, node, child,
6772 NULL, "(annotation?)");
William M. Bracke7091952004-05-11 15:09:58 +00006773 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006774 } else {
William M. Bracke7091952004-05-11 15:09:58 +00006775 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006776 /*
6777 * 3.3.3 : 3
6778 * "type" and either <simpleType> or <complexType> are mutually
6779 * exclusive
6780 */
William M. Bracke7091952004-05-11 15:09:58 +00006781 if (ret->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006782 xmlSchemaPContentErr(ctxt,
6783 XML_SCHEMAP_SRC_ELEMENT_3,
6784 &repName, (xmlSchemaTypePtr) ret, node, child,
6785 "The attribute 'type' and the <complexType> child are "
6786 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006787 } else
Daniel Veillard3646d642004-06-02 19:19:14 +00006788 ret->subtypes = xmlSchemaParseComplexType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00006789 child = child->next;
6790 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006791 /*
6792 * 3.3.3 : 3
6793 * "type" and either <simpleType> or <complexType> are
6794 * mutually exclusive
6795 */
William M. Bracke7091952004-05-11 15:09:58 +00006796 if (ret->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006797 xmlSchemaPContentErr(ctxt,
6798 XML_SCHEMAP_SRC_ELEMENT_3,
6799 &repName, (xmlSchemaTypePtr) ret, node, child,
6800 "The attribute 'type' and the <simpleType> child are "
6801 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006802 } else
Daniel Veillard3646d642004-06-02 19:19:14 +00006803 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00006804 child = child->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006805 }
William M. Bracke7091952004-05-11 15:09:58 +00006806 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00006807 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006808#ifdef IDC_ENABLED
6809 if (IS_SCHEMA(child, "unique")) {
6810 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
6811 XML_SCHEMA_TYPE_IDC_UNIQUE, ret->targetNamespace);
6812 } else if (IS_SCHEMA(child, "key")) {
6813 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
6814 XML_SCHEMA_TYPE_IDC_KEY, ret->targetNamespace);
6815 } else if (IS_SCHEMA(child, "keyref")) {
6816 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
6817 XML_SCHEMA_TYPE_IDC_KEYREF, ret->targetNamespace);
6818 }
6819 if (lastIDC != NULL)
6820 lastIDC->next = curIDC;
6821 else
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006822 ret->idcs = (void *) curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006823 lastIDC = curIDC;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006824#else
6825 TODO
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006826#endif
6827 child = child->next;
William M. Bracke7091952004-05-11 15:09:58 +00006828 }
6829 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006830 xmlSchemaPContentErr(ctxt,
6831 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6832 &repName, (xmlSchemaTypePtr) ret, node, child,
6833 NULL, "(annotation?, ((simpleType | complexType)?, "
6834 "(unique | key | keyref)*))");
6835 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006836
Daniel Veillardc0826a72004-08-10 14:17:33 +00006837 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006838 ctxt->container = oldcontainer;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006839 /*
6840 * Cleanup.
6841 */
6842 if (repName != NULL)
6843 xmlFree(repName);
6844 /*
6845 * NOTE: Element Declaration Representation OK 4. will be checked at a
6846 * different layer.
6847 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006848 return (ret);
6849}
6850
6851/**
6852 * xmlSchemaParseUnion:
6853 * @ctxt: a schema validation context
6854 * @schema: the schema being built
6855 * @node: a subtree containing XML Schema informations
6856 *
6857 * parse a XML schema Union definition
6858 * *WARNING* this interface is highly subject to change
6859 *
William M. Bracke7091952004-05-11 15:09:58 +00006860 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00006861 * 1 in case of success.
6862 */
6863static xmlSchemaTypePtr
6864xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006865 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006866{
6867 xmlSchemaTypePtr type, subtype, last = NULL;
6868 xmlNodePtr child = NULL;
6869 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00006870 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006871
6872 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6873 return (NULL);
6874
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006875 snprintf((char *) name, 30, "#union%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00006876 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006877 if (type == NULL)
6878 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00006879 type->type = XML_SCHEMA_TYPE_UNION;
Daniel Veillard4255d502002-04-16 15:50:10 +00006880 type->node = node;
William M. Brack2f2a6632004-08-20 23:09:47 +00006881 /*
6882 * Check for illegal attributes.
6883 */
6884 attr = node->properties;
6885 while (attr != NULL) {
6886 if (attr->ns == NULL) {
6887 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6888 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
6889 xmlSchemaPIllegalAttrErr(ctxt,
6890 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6891 NULL, type, attr);
6892 }
6893 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6894 xmlSchemaPIllegalAttrErr(ctxt,
6895 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6896 NULL, type, attr);
6897 }
6898 attr = attr->next;
6899 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006900 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00006901 /*
6902 * Attribute "memberTypes". This is a list of QNames.
6903 * TODO: Validate the QNames.
6904 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00006905 type->base = xmlSchemaGetProp(ctxt, node, "memberTypes");
William M. Brack2f2a6632004-08-20 23:09:47 +00006906 /*
6907 * And now for the children...
6908 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006909 child = node->children;
6910 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006911 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6912 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006913 }
William M. Brack2f2a6632004-08-20 23:09:47 +00006914 while (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006915 subtype = (xmlSchemaTypePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00006916 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006917 if (subtype != NULL) {
6918 if (last == NULL) {
6919 type->subtypes = subtype;
6920 last = subtype;
6921 } else {
6922 last->next = subtype;
6923 last = subtype;
6924 }
6925 last->next = NULL;
6926 }
6927 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006928 }
6929 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006930 /* TODO: Think about the error code. */
6931 xmlSchemaPContentErr(ctxt,
6932 XML_SCHEMAP_UNKNOWN_UNION_CHILD,
6933 NULL, type, node, child, NULL, "(annotation?, simpleType*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006934 }
6935 return (type);
6936}
6937
6938/**
6939 * xmlSchemaParseList:
6940 * @ctxt: a schema validation context
6941 * @schema: the schema being built
6942 * @node: a subtree containing XML Schema informations
6943 *
6944 * parse a XML schema List definition
6945 * *WARNING* this interface is highly subject to change
6946 *
William M. Bracke7091952004-05-11 15:09:58 +00006947 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00006948 * 1 in case of success.
6949 */
6950static xmlSchemaTypePtr
6951xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006952 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006953{
6954 xmlSchemaTypePtr type, subtype;
6955 xmlNodePtr child = NULL;
6956 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00006957 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006958
6959 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6960 return (NULL);
6961
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006962 snprintf((char *) name, 30, "#list%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00006963 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006964 if (type == NULL)
6965 return (NULL);
6966 type->node = node;
6967 type->type = XML_SCHEMA_TYPE_LIST;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006968 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00006969 /*
6970 * Check for illegal attributes.
6971 */
6972 attr = node->properties;
6973 while (attr != NULL) {
6974 if (attr->ns == NULL) {
6975 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6976 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
6977 xmlSchemaPIllegalAttrErr(ctxt,
6978 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6979 NULL, type, attr);
6980 }
6981 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6982 xmlSchemaPIllegalAttrErr(ctxt,
6983 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6984 NULL, type, attr);
6985 }
6986 attr = attr->next;
6987 }
6988 /*
6989 * Attribute "itemType".
6990 */
6991 xmlSchemaPValAttrQName(ctxt, schema, NULL, NULL,
6992 node, "itemType", &(type->baseNs), NULL, &(type->base));
6993 /*
6994 * And now for the children...
6995 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006996 child = node->children;
6997 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006998 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6999 child = child->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00007000 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007001 subtype = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00007002 if (IS_SCHEMA(child, "simpleType")) {
7003 if (type->base != NULL) {
7004 xmlSchemaPCustomErr(ctxt,
7005 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
7006 NULL, type, node,
7007 "The attribute 'itemType' and the <simpleType> child "
7008 "are mutually exclusive", NULL);
7009 } else {
7010 subtype = (xmlSchemaTypePtr)
7011 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
7012 type->subtypes = subtype;
7013 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00007014 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007015 }
7016 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007017 /* TODO: Think about the error code. */
7018 xmlSchemaPContentErr(ctxt,
7019 XML_SCHEMAP_UNKNOWN_LIST_CHILD,
7020 NULL, type, node, child, NULL, "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00007021 }
7022 return (type);
7023}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007024
Daniel Veillard4255d502002-04-16 15:50:10 +00007025/**
7026 * xmlSchemaParseSimpleType:
7027 * @ctxt: a schema validation context
7028 * @schema: the schema being built
7029 * @node: a subtree containing XML Schema informations
7030 *
7031 * parse a XML schema Simple Type definition
7032 * *WARNING* this interface is highly subject to change
7033 *
William M. Bracke7091952004-05-11 15:09:58 +00007034 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardc0826a72004-08-10 14:17:33 +00007035 * 1 in case of success.
Daniel Veillard4255d502002-04-16 15:50:10 +00007036 */
7037static xmlSchemaTypePtr
7038xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00007039 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00007040{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007041 xmlSchemaTypePtr type, subtype, oldCtxtType, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00007042 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007043 const xmlChar *attrValue = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007044 xmlChar *des = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007045 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00007046
7047 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7048 return (NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007049
Daniel Veillardc0826a72004-08-10 14:17:33 +00007050 if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007051 attr = xmlSchemaGetPropNode(node, "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007052 if (attr == NULL) {
7053 xmlSchemaPMissingAttrErr(ctxt,
7054 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007055 (xmlChar **) &xmlSchemaElemDesST, NULL, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007056 "name", NULL);
7057 return (NULL);
7058 } else if (xmlSchemaPValAttrNode(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007059 (xmlChar **) &xmlSchemaElemDesST, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007060 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00007061 return (NULL);
7062 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007063 }
7064
7065 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007066 char buf[40];
Daniel Veillardc0826a72004-08-10 14:17:33 +00007067
Daniel Veillard01fa6152004-06-29 17:04:39 +00007068 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007069 * Parse as local simple type definition.
Daniel Veillard01fa6152004-06-29 17:04:39 +00007070 */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00007071 snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007072 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007073 if (type == NULL)
7074 return (NULL);
7075 type->node = node;
7076 type->type = XML_SCHEMA_TYPE_SIMPLE;
7077 /*
7078 * Check for illegal attributes.
7079 */
7080 attr = node->properties;
7081 while (attr != NULL) {
7082 if (attr->ns == NULL) {
7083 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
7084 xmlSchemaPIllegalAttrErr(ctxt,
7085 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007086 &des, type, attr);
Daniel Veillard01fa6152004-06-29 17:04:39 +00007087 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007088 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7089 xmlSchemaPIllegalAttrErr(ctxt,
7090 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007091 &des, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007092 }
7093 attr = attr->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +00007094 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007095 } else {
7096 /*
7097 * Parse as global simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007098 *
7099 * Note that attrValue is the value of the attribute "name" here.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007100 */
William M. Brack2f2a6632004-08-20 23:09:47 +00007101 type = xmlSchemaAddType(ctxt, schema, attrValue, schema->targetNamespace, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007102 if (type == NULL)
7103 return (NULL);
7104 type->node = node;
7105 type->type = XML_SCHEMA_TYPE_SIMPLE;
7106 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
7107 /*
7108 * Check for illegal attributes.
7109 */
7110 attr = node->properties;
7111 while (attr != NULL) {
7112 if (attr->ns == NULL) {
7113 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7114 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007115 (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007116 xmlSchemaPIllegalAttrErr(ctxt,
7117 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007118 &des, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007119 }
7120 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7121 xmlSchemaPIllegalAttrErr(ctxt,
7122 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007123 &des, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007124 }
7125 attr = attr->next;
7126 }
7127 /*
7128 * Attribute "final".
7129 */
7130 attr = xmlSchemaGetPropNode(node, "final");
7131 if (attr == NULL) {
7132 type->flags |= XML_SCHEMAS_TYPE_FINAL_DEFAULT;
7133 } else {
7134 attrValue = xmlSchemaGetProp(ctxt, node, "final");
7135 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
7136 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
7137 XML_SCHEMAS_TYPE_FINAL_LIST,
7138 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
7139
7140 xmlSchemaPSimpleTypeErr(ctxt,
7141 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007142 &des, type, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00007143 NULL, "(#all | List of (list | union | restriction)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00007144 attrValue, NULL, NULL, NULL);
7145 }
7146 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00007147 }
7148 type->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00007149 xmlSchemaPValAttrID(ctxt, NULL, type, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007150 /*
7151 * And now for the children...
7152 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007153 oldCtxtType = ctxt->ctxtType;
7154 oldParentItem = ctxt->parentItem;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007155 ctxt->ctxtType = type;
7156 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00007157 child = node->children;
7158 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007159 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7160 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007161 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007162 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00007163 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007164 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00007165 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007166 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007167 } else if (IS_SCHEMA(child, "list")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007168 subtype = (xmlSchemaTypePtr)
7169 xmlSchemaParseList(ctxt, schema, child);
7170 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007171 } else if (IS_SCHEMA(child, "union")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007172 subtype = (xmlSchemaTypePtr)
7173 xmlSchemaParseUnion(ctxt, schema, child);
7174 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007175 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007176 type->subtypes = subtype;
7177 if ((child != NULL) || (subtype == NULL)) {
7178 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007179 &des, type, node, child, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007180 "(annotation?, (restriction | list | union))");
Daniel Veillard4255d502002-04-16 15:50:10 +00007181 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007182 ctxt->parentItem = oldParentItem;
7183 ctxt->ctxtType = oldCtxtType;
7184 FREE_AND_NULL(des)
Daniel Veillard01fa6152004-06-29 17:04:39 +00007185
Daniel Veillard4255d502002-04-16 15:50:10 +00007186 return (type);
7187}
7188
7189
7190/**
7191 * xmlSchemaParseGroup:
7192 * @ctxt: a schema validation context
7193 * @schema: the schema being built
7194 * @node: a subtree containing XML Schema informations
7195 *
7196 * parse a XML schema Group definition
7197 * *WARNING* this interface is highly subject to change
7198 *
William M. Bracke7091952004-05-11 15:09:58 +00007199 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00007200 * 1 in case of success.
7201 */
7202static xmlSchemaTypePtr
7203xmlSchemaParseGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00007204 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00007205{
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00007206 xmlSchemaTypePtr item;
7207 xmlNodePtr child = NULL;
7208 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00007209
7210 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00007211 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007212
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00007213 if (topLevel) {
7214 const xmlChar *name;
7215 /*
7216 * Parse as model group definition.
7217 */
7218 attr = xmlSchemaGetPropNode(node, "name");
7219 if (attr == NULL) {
7220 xmlSchemaPMissingAttrErr(ctxt,
7221 XML_SCHEMAP_S4S_ATTR_MISSING,
7222 NULL, NULL, node,
7223 "name", NULL);
7224 return (NULL);
7225 } else if (xmlSchemaPValAttrNode(ctxt,
7226 NULL, NULL, attr,
7227 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7228 return (NULL);
7229 }
7230 item = xmlSchemaAddGroup(ctxt, schema, name,
7231 schema->targetNamespace, node);
7232 if (item == NULL)
7233 return (NULL);
7234 item->node = node;
7235 item->type = XML_SCHEMA_TYPE_GROUP;
7236 item->flags |= XML_SCHEMAS_TYPE_GLOBAL;
7237 /*
7238 * Check for illegal attributes.
7239 */
7240 attr = node->properties;
7241 while (attr != NULL) {
7242 if (attr->ns == NULL) {
7243 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7244 (!xmlStrEqual(attr->name, BAD_CAST "id"))) {
7245 xmlSchemaPIllegalAttrErr(ctxt,
7246 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7247 NULL, item, attr);
7248 }
7249 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7250 xmlSchemaPIllegalAttrErr(ctxt,
7251 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7252 NULL, item, attr);
7253 }
7254 attr = attr->next;
7255 }
7256 xmlSchemaPValAttrID(ctxt, NULL, item, node, BAD_CAST "id");
7257 /*
7258 * And now for the children...
7259 */
7260 child = node->children;
7261 if (IS_SCHEMA(child, "annotation")) {
7262 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7263 child = child->next;
7264 }
7265 if (IS_SCHEMA(child, "all")) {
7266 item->subtypes = (xmlSchemaTypePtr)
7267 xmlSchemaParseAll(ctxt, schema, child);
7268 child = child->next;
7269 } else if (IS_SCHEMA(child, "choice")) {
7270 item->subtypes = xmlSchemaParseChoice(ctxt, schema, child);
7271 child = child->next;
7272 } else if (IS_SCHEMA(child, "sequence")) {
7273 item->subtypes = xmlSchemaParseSequence(ctxt, schema, child);
7274 child = child->next;
7275 }
7276 if (child != NULL) {
7277 xmlSchemaPContentErr(ctxt,
7278 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7279 NULL, item, node, child, NULL,
7280 "(annotation?, (all | choice | sequence)?)");
7281 }
7282 } else {
7283 const xmlChar *ref = NULL, *refNs = NULL, *refPrefix = NULL;
7284 int minOccurs, maxOccurs;
7285 char buf[40];
Daniel Veillard4255d502002-04-16 15:50:10 +00007286
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00007287 /*
7288 * Parse as particle.
7289 */
7290 attr = xmlSchemaGetPropNode(node, "ref");
7291 if (attr == NULL) {
7292 xmlSchemaPMissingAttrErr(ctxt,
7293 XML_SCHEMAP_S4S_ATTR_MISSING,
7294 NULL, NULL, node,
7295 "ref", NULL);
7296 return (NULL);
7297 } else if (xmlSchemaPValAttrNodeQName(ctxt, schema, NULL, NULL,
7298 attr, &refNs, &refPrefix, &ref) != 0) {
7299 return (NULL);
7300 }
7301
7302 /*
7303 * TODO: Validate the element even if no item is created
7304 * (i.e. min/maxOccurs == 0).
7305 */
7306 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
7307 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
7308 "(nonNegativeInteger | unbounded)");
7309 if ((minOccurs == 0) && (maxOccurs == 0)) {
7310 return (NULL);
7311 }
7312
7313 snprintf(buf, 39, "#grRef%d", ctxt->counter++ + 1);
7314 item = xmlSchemaAddGroup(ctxt, schema, (const xmlChar *)buf, NULL, node);
7315 if (item == NULL)
7316 return (NULL);
7317 item->node = node;
7318 item->type = XML_SCHEMA_TYPE_GROUP;
7319 item->ref = ref;
7320 item->refNs = refNs;
7321 xmlSchemaCheckReference(ctxt, schema, node, item, refNs);
7322 item->minOccurs = minOccurs;
7323 item->maxOccurs = maxOccurs;
7324 xmlSchemaPCheckParticleCorrect_2(ctxt, item,
7325 node, item->minOccurs, item->maxOccurs);
7326 /*
7327 * Check for illegal attributes.
7328 */
7329 attr = node->properties;
7330 while (attr != NULL) {
7331 if (attr->ns == NULL) {
7332 if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
7333 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7334 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
7335 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs"))) {
7336 xmlSchemaPIllegalAttrErr(ctxt,
7337 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7338 NULL, item, attr);
7339 }
7340 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7341 xmlSchemaPIllegalAttrErr(ctxt,
7342 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7343 NULL, item, attr);
7344 }
7345 attr = attr->next;
7346 }
7347 xmlSchemaPValAttrID(ctxt, NULL, item, node, BAD_CAST "id");
7348 /*
7349 * And now for the children...
7350 */
7351 child = node->children;
7352 if (IS_SCHEMA(child, "annotation")) {
7353 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7354 child = child->next;
7355 }
7356 if (child != NULL) {
7357 xmlSchemaPContentErr(ctxt,
7358 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7359 NULL, item, node, child, NULL,
7360 "(annotation?, (all | choice | sequence)?)");
7361 }
7362 }
7363
7364 return (item);
Daniel Veillard4255d502002-04-16 15:50:10 +00007365}
7366
7367/**
7368 * xmlSchemaParseAll:
7369 * @ctxt: a schema validation context
7370 * @schema: the schema being built
7371 * @node: a subtree containing XML Schema informations
7372 *
7373 * parse a XML schema All definition
7374 * *WARNING* this interface is highly subject to change
7375 *
William M. Bracke7091952004-05-11 15:09:58 +00007376 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00007377 * 1 in case of success.
7378 */
7379static xmlSchemaTypePtr
7380xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007381 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007382{
7383 xmlSchemaTypePtr type, subtype, last = NULL;
7384 xmlNodePtr child = NULL;
7385 xmlChar name[30];
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00007386 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007387
7388 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7389 return (NULL);
7390
7391
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00007392 snprintf((char *) name, 30, "#all%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007393 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007394 if (type == NULL)
7395 return (NULL);
7396 type->node = node;
Daniel Veillard7646b182002-04-20 06:41:40 +00007397 type->type = XML_SCHEMA_TYPE_ALL;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00007398
7399 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007400
7401 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
7402 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00007403
7404 oldcontainer = ctxt->container;
7405 ctxt->container = (const xmlChar *) name;
Daniel Veillard4255d502002-04-16 15:50:10 +00007406 child = node->children;
7407 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007408 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7409 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007410 }
7411 while (IS_SCHEMA(child, "element")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007412 subtype = (xmlSchemaTypePtr)
7413 xmlSchemaParseElement(ctxt, schema, child, 0);
7414 if (subtype != NULL) {
William M. Brackb15351e2003-12-27 04:34:42 +00007415 if (subtype->minOccurs > 1)
7416 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MINOCCURS,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007417 "invalid value for minOccurs (must be 0 or 1).\n",
William M. Brackb15351e2003-12-27 04:34:42 +00007418 NULL, NULL);
7419 if (subtype->maxOccurs > 1)
7420 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MAXOCCURS,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007421 "invalid value for maxOccurs (must be 0 or 1).\n",
William M. Brackb15351e2003-12-27 04:34:42 +00007422 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007423 if (last == NULL) {
7424 type->subtypes = subtype;
7425 last = subtype;
7426 } else {
7427 last->next = subtype;
7428 last = subtype;
7429 }
7430 last->next = NULL;
7431 }
7432 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007433 }
7434 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007435 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ALL_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007436 "<all> has unexpected content.\n", type->name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007437 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007438 }
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00007439 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007440 return (type);
7441}
7442
7443/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007444 * xmlSchemaCleanupDoc:
7445 * @ctxt: a schema validation context
7446 * @node: the root of the document.
7447 *
7448 * removes unwanted nodes in a schemas document tree
7449 */
7450static void
7451xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
7452{
7453 xmlNodePtr delete, cur;
7454
7455 if ((ctxt == NULL) || (root == NULL)) return;
7456
7457 /*
7458 * Remove all the blank text nodes
7459 */
7460 delete = NULL;
7461 cur = root;
7462 while (cur != NULL) {
7463 if (delete != NULL) {
7464 xmlUnlinkNode(delete);
7465 xmlFreeNode(delete);
7466 delete = NULL;
7467 }
7468 if (cur->type == XML_TEXT_NODE) {
7469 if (IS_BLANK_NODE(cur)) {
7470 if (xmlNodeGetSpacePreserve(cur) != 1) {
7471 delete = cur;
7472 }
7473 }
7474 } else if ((cur->type != XML_ELEMENT_NODE) &&
7475 (cur->type != XML_CDATA_SECTION_NODE)) {
7476 delete = cur;
7477 goto skip_children;
7478 }
7479
7480 /*
7481 * Skip to next node
7482 */
7483 if (cur->children != NULL) {
7484 if ((cur->children->type != XML_ENTITY_DECL) &&
7485 (cur->children->type != XML_ENTITY_REF_NODE) &&
7486 (cur->children->type != XML_ENTITY_NODE)) {
7487 cur = cur->children;
7488 continue;
7489 }
7490 }
7491 skip_children:
7492 if (cur->next != NULL) {
7493 cur = cur->next;
7494 continue;
7495 }
7496
7497 do {
7498 cur = cur->parent;
7499 if (cur == NULL)
7500 break;
7501 if (cur == root) {
7502 cur = NULL;
7503 break;
7504 }
7505 if (cur->next != NULL) {
7506 cur = cur->next;
7507 break;
7508 }
7509 } while (cur != NULL);
7510 }
7511 if (delete != NULL) {
7512 xmlUnlinkNode(delete);
7513 xmlFreeNode(delete);
7514 delete = NULL;
7515 }
7516}
7517
William M. Brack2f2a6632004-08-20 23:09:47 +00007518
7519/**
7520 * xmlSchemaImportSchema
7521 *
7522 * @ctxt: a schema validation context
7523 * @schemaLocation: an URI defining where to find the imported schema
7524 *
7525 * import a XML schema
7526 * *WARNING* this interface is highly subject to change
7527 *
7528 * Returns -1 in case of error and 1 in case of success.
7529 */
7530#if 0
7531static xmlSchemaImportPtr
7532xmlSchemaImportSchema(xmlSchemaParserCtxtPtr ctxt,
7533 const xmlChar *schemaLocation)
7534{
7535 xmlSchemaImportPtr import;
7536 xmlSchemaParserCtxtPtr newctxt;
7537
7538 newctxt = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
7539 if (newctxt == NULL) {
7540 xmlSchemaPErrMemory(ctxt, "allocating schema parser context",
7541 NULL);
7542 return (NULL);
7543 }
7544 memset(newctxt, 0, sizeof(xmlSchemaParserCtxt));
7545 /* Keep the same dictionnary for parsing, really */
7546 xmlDictReference(ctxt->dict);
7547 newctxt->dict = ctxt->dict;
7548 newctxt->includes = 0;
7549 newctxt->URL = xmlDictLookup(newctxt->dict, schemaLocation, -1);
7550
7551 xmlSchemaSetParserErrors(newctxt, ctxt->error, ctxt->warning,
7552 ctxt->userData);
7553
7554 import = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
7555 if (import == NULL) {
7556 xmlSchemaPErrMemory(NULL, "allocating imported schema",
7557 NULL);
7558 xmlSchemaFreeParserCtxt(newctxt);
7559 return (NULL);
7560 }
7561
7562 memset(import, 0, sizeof(xmlSchemaImport));
7563 import->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
7564 import->schema = xmlSchemaParse(newctxt);
7565
7566 if (import->schema == NULL) {
7567 /* FIXME use another error enum here ? */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00007568 xmlSchemaPErr(ctxt, NULL, XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00007569 "Failed to import schema from location \"%s\".\n",
7570 schemaLocation, NULL);
7571
7572 xmlSchemaFreeParserCtxt(newctxt);
7573 /* The schemaLocation is held by the dictionary.
7574 if (import->schemaLocation != NULL)
7575 xmlFree((xmlChar *)import->schemaLocation);
7576 */
7577 xmlFree(import);
7578 return NULL;
7579 }
7580
7581 xmlSchemaFreeParserCtxt(newctxt);
7582 return import;
7583}
7584#endif
7585
7586static void
7587xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
7588{
7589 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
7590 schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
7591
7592 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
7593 schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
7594
7595 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
7596 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
7597 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
7598 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
7599 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
7600 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
7601 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
7602 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
7603
7604 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
7605 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
7606 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
7607 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
7608 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
7609 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
7610}
7611
7612static void
7613xmlSchemaParseSchemaDefaults(xmlSchemaParserCtxtPtr ctxt,
7614 xmlSchemaPtr schema,
7615 xmlNodePtr node)
7616{
7617 xmlAttrPtr attr;
7618 const xmlChar *val;
7619
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00007620 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
7621 if (schema->version == NULL)
7622 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
7623 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &(schema->version));
7624 else
7625 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
7626 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), NULL);
7627
William M. Brack2f2a6632004-08-20 23:09:47 +00007628 attr = xmlSchemaGetPropNode(node, "elementFormDefault");
7629 if (attr != NULL) {
7630 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7631 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
7632 XML_SCHEMAS_QUALIF_ELEM) != 0) {
7633 xmlSchemaPSimpleTypeErr(ctxt,
7634 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
7635 NULL, NULL, (xmlNodePtr) attr, NULL,
7636 "(qualified | unqualified)", val, NULL, NULL, NULL);
7637 }
7638 }
7639
7640 attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
7641 if (attr != NULL) {
7642 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7643 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
7644 XML_SCHEMAS_QUALIF_ATTR) != 0) {
7645 xmlSchemaPSimpleTypeErr(ctxt,
7646 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
7647 NULL, NULL, (xmlNodePtr) attr, NULL,
7648 "(qualified | unqualified)", val, NULL, NULL, NULL);
7649 }
7650 }
7651
7652 attr = xmlSchemaGetPropNode(node, "finalDefault");
7653 if (attr != NULL) {
7654 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7655 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
7656 XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
7657 XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
7658 -1,
7659 XML_SCHEMAS_FINAL_DEFAULT_LIST,
7660 XML_SCHEMAS_FINAL_DEFAULT_UNION) != 0) {
7661 xmlSchemaPSimpleTypeErr(ctxt,
7662 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7663 NULL, NULL, (xmlNodePtr) attr, NULL,
7664 "(#all | List of (extension | restriction | list | union))",
7665 val, NULL, NULL, NULL);
7666 }
7667 }
7668
7669 attr = xmlSchemaGetPropNode(node, "blockDefault");
7670 if (attr != NULL) {
7671 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7672 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
7673 XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
7674 XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
7675 XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1) != 0) {
7676 xmlSchemaPSimpleTypeErr(ctxt,
7677 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7678 NULL, NULL, (xmlNodePtr) attr, NULL,
7679 "(#all | List of (extension | restriction | substitution))",
7680 val, NULL, NULL, NULL);
7681 }
7682 }
7683}
7684
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007685/**
7686 * xmlSchemaParseSchemaTopLevel:
7687 * @ctxt: a schema validation context
7688 * @schema: the schemas
7689 * @nodes: the list of top level nodes
7690 *
7691 * Returns the internal XML Schema structure built from the resource or
7692 * NULL in case of error
7693 */
7694static void
7695xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
7696 xmlSchemaPtr schema, xmlNodePtr nodes)
7697{
7698 xmlNodePtr child;
7699 xmlSchemaAnnotPtr annot;
7700
7701 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
7702 return;
7703
7704 child = nodes;
7705 while ((IS_SCHEMA(child, "include")) ||
7706 (IS_SCHEMA(child, "import")) ||
7707 (IS_SCHEMA(child, "redefine")) ||
7708 (IS_SCHEMA(child, "annotation"))) {
7709 if (IS_SCHEMA(child, "annotation")) {
7710 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7711 if (schema->annot == NULL)
7712 schema->annot = annot;
7713 else
7714 xmlSchemaFreeAnnot(annot);
7715 } else if (IS_SCHEMA(child, "import")) {
7716 xmlSchemaParseImport(ctxt, schema, child);
7717 } else if (IS_SCHEMA(child, "include")) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00007718 ctxt->includes++;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007719 xmlSchemaParseInclude(ctxt, schema, child);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00007720 ctxt->includes--;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007721 } else if (IS_SCHEMA(child, "redefine")) {
7722 TODO
7723 }
7724 child = child->next;
7725 }
7726 while (child != NULL) {
7727 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007728 xmlSchemaParseComplexType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007729 child = child->next;
7730 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007731 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007732 child = child->next;
7733 } else if (IS_SCHEMA(child, "element")) {
7734 xmlSchemaParseElement(ctxt, schema, child, 1);
7735 child = child->next;
7736 } else if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00007737 xmlSchemaParseAttribute(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007738 child = child->next;
7739 } else if (IS_SCHEMA(child, "attributeGroup")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007740 xmlSchemaParseAttributeGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007741 child = child->next;
7742 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007743 xmlSchemaParseGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007744 child = child->next;
7745 } else if (IS_SCHEMA(child, "notation")) {
7746 xmlSchemaParseNotation(ctxt, schema, child);
7747 child = child->next;
7748 } else {
7749 xmlSchemaPErr2(ctxt, NULL, child,
7750 XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007751 "Unexpected element \"%s\" as child of <schema>.\n",
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007752 child->name, NULL);
7753 child = child->next;
7754 }
7755 while (IS_SCHEMA(child, "annotation")) {
7756 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7757 if (schema->annot == NULL)
7758 schema->annot = annot;
7759 else
7760 xmlSchemaFreeAnnot(annot);
7761 child = child->next;
7762 }
7763 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00007764 ctxt->parentItem = NULL;
7765 ctxt->ctxtType = NULL;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007766}
7767
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007768static xmlSchemaImportPtr
7769xmlSchemaAddImport(xmlSchemaParserCtxtPtr ctxt,
7770 xmlHashTablePtr *imports,
7771 const xmlChar *nsName)
7772{
7773 xmlSchemaImportPtr ret;
7774
7775 if (*imports == NULL) {
Daniel Veillardb9e2f262005-01-23 23:48:34 +00007776 *imports = xmlHashCreateDict(10, ctxt->dict);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007777 if (*imports == NULL) {
7778 xmlSchemaPCustomErr(ctxt,
7779 XML_SCHEMAP_FAILED_BUILD_IMPORT,
7780 NULL, NULL, (xmlNodePtr) ctxt->doc,
7781 "Internal error: failed to build the import table",
7782 NULL);
7783 return (NULL);
7784 }
7785 }
7786 ret = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
7787 if (ret == NULL) {
7788 xmlSchemaPErrMemory(NULL, "allocating import struct", NULL);
7789 return (NULL);
7790 }
7791 memset(ret, 0, sizeof(xmlSchemaImport));
7792 if (nsName == NULL)
7793 nsName = XML_SCHEMAS_NO_NAMESPACE;
7794 xmlHashAddEntry(*imports, nsName, ret);
7795
7796 return (ret);
7797}
7798
7799static int
7800xmlSchemaAcquireSchemaDoc(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007801 xmlSchemaPtr schema,
7802 xmlNodePtr node,
7803 const xmlChar *nsName,
7804 const xmlChar *location,
7805 xmlDocPtr *doc,
7806 const xmlChar **targetNamespace,
7807 int absolute)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007808{
7809 xmlParserCtxtPtr parserCtxt;
7810 xmlSchemaImportPtr import;
7811 const xmlChar *ns;
7812 xmlNodePtr root;
7813
7814 /*
7815 * NOTE: This will be used for <import>, <xsi:schemaLocation> and
7816 * <xsi:noNamespaceSchemaLocation>.
7817 */
7818 *doc = NULL;
7819 /*
7820 * Given that the schemaLocation [attribute] is only a hint, it is open
7821 * to applications to ignore all but the first <import> for a given
7822 * namespace, regardless of the ·actual value· of schemaLocation, but
7823 * such a strategy risks missing useful information when new
7824 * schemaLocations are offered.
7825 *
7826 * XSV (ver 2.5-2) does use the first <import> which resolves to a valid schema.
7827 * Xerces-J (ver 2.5.1) ignores all but the first given <import> - regardless if
7828 * valid or not.
7829 * We will follow XSV here.
7830 */
7831 if (location == NULL) {
7832 /*
7833 * Schema Document Location Strategy:
7834 *
7835 * 3 Based on the namespace name, identify an existing schema document,
7836 * either as a resource which is an XML document or a <schema> element
7837 * information item, in some local schema repository;
7838 *
7839 * 5 Attempt to resolve the namespace name to locate such a resource.
7840 *
7841 * NOTE: Those stategies are not supported, so we will skip.
7842 */
7843 return (0);
7844 }
7845 if (nsName == NULL)
7846 ns = XML_SCHEMAS_NO_NAMESPACE;
7847 else
7848 ns = nsName;
7849
7850 import = xmlHashLookup(schema->schemasImports, ns);
7851 if (import != NULL) {
7852 /*
7853 * There was a valid resource for the specified namespace already
7854 * defined, so skip.
7855 * TODO: This might be changed someday to allow import of
7856 * components from multiple documents for a single target namespace.
7857 */
7858 return (0);
7859 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007860
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007861 /*
7862 * Schema Document Location Strategy:
7863 *
7864 * 2 Based on the location URI, identify an existing schema document,
7865 * either as a resource which is an XML document or a <schema> element
7866 * information item, in some local schema repository;
7867 *
7868 * 4 Attempt to resolve the location URI, to locate a resource on the
7869 * web which is or contains or references a <schema> element;
7870 * TODO: Hmm, I don't know if the reference stuff in 4. will work.
7871 *
7872 */
7873 if ((absolute == 0) && (node != NULL)) {
7874 xmlChar *base, *URI;
7875
7876 base = xmlNodeGetBase(node->doc, node);
7877 if (base == NULL) {
7878 URI = xmlBuildURI(location, node->doc->URL);
7879 } else {
7880 URI = xmlBuildURI(location, base);
7881 xmlFree(base);
7882 }
7883 if (URI != NULL) {
7884 location = xmlDictLookup(ctxt->dict, URI, -1);
7885 xmlFree(URI);
7886 }
7887 }
7888 parserCtxt = xmlNewParserCtxt();
7889 if (parserCtxt == NULL) {
7890 xmlSchemaPErrMemory(NULL, "xmlSchemaParseImport: "
7891 "allocating a parser context", NULL);
7892 return(-1);
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00007893 }
7894
7895 if ((ctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
7896 xmlDictFree(parserCtxt->dict);
7897 parserCtxt->dict = ctxt->dict;
7898 xmlDictReference(parserCtxt->dict);
7899 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007900
7901 *doc = xmlCtxtReadFile(parserCtxt, (const char *) location,
7902 NULL, SCHEMAS_PARSE_OPTIONS);
7903
7904 /*
7905 * 2.1 The referent is (a fragment of) a resource which is an
7906 * XML document (see clause 1.1), which in turn corresponds to
7907 * a <schema> element information item in a well-formed information
7908 * set, which in turn corresponds to a valid schema.
7909 * TODO: What to do with the "fragment" stuff?
7910 *
7911 * 2.2 The referent is a <schema> element information item in
7912 * a well-formed information set, which in turn corresponds
7913 * to a valid schema.
7914 * NOTE: 2.2 won't apply, since only XML documents will be processed
7915 * here.
7916 */
7917 if (*doc == NULL) {
7918 xmlErrorPtr lerr;
7919 /*
7920 * It is *not* an error for the application schema reference
7921 * strategy to fail.
7922 *
7923 * If the doc is NULL and the parser error is an IO error we
7924 * will assume that the resource could not be located or accessed.
7925 *
7926 * TODO: Try to find specific error codes to react only on
7927 * localisation failures.
7928 *
7929 * TODO, FIXME: Check the spec: is a namespace added to the imported
7930 * namespaces, even if the schemaLocation did not provide
7931 * a resource? I guess so, since omitting the "schemaLocation"
7932 * attribute, imports a namespace as well.
7933 */
7934 lerr = xmlGetLastError();
7935 if ((lerr != NULL) && (lerr->domain == XML_FROM_IO)) {
7936 xmlFreeParserCtxt(parserCtxt);
7937 return(0);
7938 }
7939
7940 xmlSchemaPCustomErr(ctxt,
7941 XML_SCHEMAP_SRC_IMPORT_2_1,
7942 NULL, NULL, node,
7943 "Failed to parse the resource '%s' for import",
7944 location);
7945 xmlFreeParserCtxt(parserCtxt);
7946 return(XML_SCHEMAP_SRC_IMPORT_2_1);
7947 }
7948 xmlFreeParserCtxt(parserCtxt);
7949
7950 root = xmlDocGetRootElement(*doc);
7951 if (root == NULL) {
7952 xmlSchemaPCustomErr(ctxt,
7953 XML_SCHEMAP_SRC_IMPORT_2_1,
7954 NULL, NULL, node,
7955 "The XML document '%s' to be imported has no document "
7956 "element", location);
7957 xmlFreeDoc(*doc);
7958 *doc = NULL;
7959 return (XML_SCHEMAP_SRC_IMPORT_2_1);
7960 }
7961
7962 xmlSchemaCleanupDoc(ctxt, root);
7963
7964 if (!IS_SCHEMA(root, "schema")) {
7965 xmlSchemaPCustomErr(ctxt,
7966 XML_SCHEMAP_SRC_IMPORT_2_1,
7967 NULL, NULL, node,
7968 "The XML document '%s' to be imported is not a XML schema document",
7969 location);
7970 xmlFreeDoc(*doc);
7971 *doc = NULL;
7972 return (XML_SCHEMAP_SRC_IMPORT_2_1);
7973 }
7974 *targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
7975 /*
7976 * Schema Representation Constraint: Import Constraints and Semantics
7977 */
7978 if (nsName == NULL) {
7979 if (*targetNamespace != NULL) {
7980 xmlSchemaPCustomErr(ctxt,
7981 XML_SCHEMAP_SRC_IMPORT_3_2,
7982 NULL, NULL, node,
7983 "The XML schema to be imported is not expected "
7984 "to have a target namespace; this differs from "
7985 "its target namespace of '%s'", *targetNamespace);
7986 xmlFreeDoc(*doc);
7987 *doc = NULL;
7988 return (XML_SCHEMAP_SRC_IMPORT_3_2);
7989 }
7990 } else {
7991 if (*targetNamespace == NULL) {
7992 xmlSchemaPCustomErr(ctxt,
7993 XML_SCHEMAP_SRC_IMPORT_3_1,
7994 NULL, NULL, node,
7995 "The XML schema to be imported is expected to have a target "
7996 "namespace of '%s'", nsName);
7997 xmlFreeDoc(*doc);
7998 *doc = NULL;
7999 return (XML_SCHEMAP_SRC_IMPORT_3_1);
8000 } else if (!xmlStrEqual(*targetNamespace, nsName)) {
8001 xmlSchemaPCustomErrExt(ctxt,
8002 XML_SCHEMAP_SRC_IMPORT_3_1,
8003 NULL, NULL, node,
8004 "The XML schema to be imported is expected to have a "
8005 "target namespace of '%s'; this differs from "
8006 "its target namespace of '%s'",
8007 nsName, *targetNamespace, NULL);
8008 xmlFreeDoc(*doc);
8009 *doc = NULL;
8010 return (XML_SCHEMAP_SRC_IMPORT_3_1);
8011 }
8012 }
8013
8014 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports), nsName);
8015 if (import == NULL) {
8016 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT,
8017 NULL, NULL, NULL,
8018 "Internal error: xmlSchemaAcquireSchemaDoc, "
8019 "failed to build import table", NULL);
8020 xmlFreeDoc(*doc);
8021 *doc = NULL;
8022 return (-1);
8023 }
8024 import->schemaLocation = location;
8025 import->doc = *doc;
8026 return (0);
8027}
William M. Brack2f2a6632004-08-20 23:09:47 +00008028
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008029static void
8030xmlSchemaParseForImpInc(xmlSchemaParserCtxtPtr pctxt,
8031 xmlSchemaPtr schema,
8032 const xmlChar *targetNamespace,
8033 xmlNodePtr node)
8034{
8035 const xmlChar *oldURL, **oldLocImps, *oldTNS;
8036 int oldFlags, oldNumLocImps, oldSizeLocImps;
8037
8038 /*
8039 * Save and reset the context & schema.
8040 */
8041 oldURL = pctxt->URL;
8042 /* TODO: Is using the doc->URL here correct? */
8043 pctxt->URL = node->doc->URL;
8044 oldLocImps = pctxt->localImports;
8045 pctxt->localImports = NULL;
8046 oldNumLocImps = pctxt->nbLocalImports;
8047 pctxt->nbLocalImports = 0;
8048 oldSizeLocImps = pctxt->sizeLocalImports;
8049 pctxt->sizeLocalImports = 0;
8050 oldFlags = schema->flags;
8051 xmlSchemaClearSchemaDefaults(schema);
8052 oldTNS = schema->targetNamespace;
8053 schema->targetNamespace = targetNamespace;
8054 /*
8055 * Parse the schema.
8056 */
8057 xmlSchemaParseSchemaDefaults(pctxt, schema, node);
8058 xmlSchemaParseSchemaTopLevel(pctxt, schema, node->children);
8059 /*
8060 * Restore the context & schema.
8061 */
8062 schema->flags = oldFlags;
8063 schema->targetNamespace = oldTNS;
8064 if (pctxt->localImports != NULL)
8065 xmlFree((xmlChar *) pctxt->localImports);
8066 pctxt->localImports = oldLocImps;
8067 pctxt->nbLocalImports = oldNumLocImps;
8068 pctxt->sizeLocalImports = oldSizeLocImps;
8069 pctxt->URL = oldURL;
8070}
8071
William M. Brack2f2a6632004-08-20 23:09:47 +00008072/**
8073 * xmlSchemaParseImport:
8074 * @ctxt: a schema validation context
8075 * @schema: the schema being built
8076 * @node: a subtree containing XML Schema informations
8077 *
8078 * parse a XML schema Import definition
8079 * *WARNING* this interface is highly subject to change
8080 *
8081 * Returns 0 in case of success, a positive error code if
8082 * not valid and -1 in case of an internal error.
8083 */
8084static int
8085xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
8086 xmlNodePtr node)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008087{
8088 xmlNodePtr child;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008089 const xmlChar *namespaceName = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00008090 const xmlChar *schemaLocation = NULL;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008091 const xmlChar *targetNamespace;
William M. Brack2f2a6632004-08-20 23:09:47 +00008092 xmlAttrPtr attr;
8093 xmlDocPtr doc;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008094 int ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00008095
8096 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8097 return (-1);
8098
8099 /*
8100 * Check for illegal attributes.
8101 */
8102 attr = node->properties;
8103 while (attr != NULL) {
8104 if (attr->ns == NULL) {
8105 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8106 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
8107 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
8108 xmlSchemaPIllegalAttrErr(ctxt,
8109 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8110 NULL, NULL, attr);
8111 }
8112 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8113 xmlSchemaPIllegalAttrErr(ctxt,
8114 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8115 NULL, NULL, attr);
8116 }
8117 attr = attr->next;
8118 }
8119 /*
8120 * Extract and validate attributes.
8121 */
8122 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
8123 "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008124 &namespaceName) != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008125 xmlSchemaPSimpleTypeErr(ctxt,
8126 XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI,
8127 NULL, NULL, node,
8128 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008129 NULL, namespaceName, NULL, NULL, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00008130 return (XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI);
8131 }
8132
8133 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
8134 "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
8135 &schemaLocation) != 0) {
8136 xmlSchemaPSimpleTypeErr(ctxt,
8137 XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI,
8138 NULL, NULL, node,
8139 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008140 NULL, namespaceName, NULL, NULL, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00008141 return (XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI);
8142 }
8143 /*
8144 * And now for the children...
8145 */
8146 child = node->children;
8147 if (IS_SCHEMA(child, "annotation")) {
8148 /*
8149 * the annotation here is simply discarded ...
8150 */
8151 child = child->next;
8152 }
8153 if (child != NULL) {
8154 xmlSchemaPContentErr(ctxt,
8155 XML_SCHEMAP_UNKNOWN_IMPORT_CHILD,
8156 NULL, NULL, node, child, NULL,
8157 "(annotation?)");
8158 }
8159 /*
8160 * Apply additional constraints.
8161 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008162 if (namespaceName != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008163 /*
8164 * 1.1 If the namespace [attribute] is present, then its ·actual value·
8165 * must not match the ·actual value· of the enclosing <schema>'s
8166 * targetNamespace [attribute].
8167 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008168 if (xmlStrEqual(schema->targetNamespace, namespaceName)) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008169 xmlSchemaPCustomErr(ctxt,
8170 XML_SCHEMAP_SRC_IMPORT_1_1,
8171 NULL, NULL, node,
8172 "The value of the attribute 'namespace' must not match "
8173 "the target namespace '%s' of the importing schema",
8174 schema->targetNamespace);
8175 return (XML_SCHEMAP_SRC_IMPORT_1_1);
8176 }
8177 } else {
8178 /*
8179 * 1.2 If the namespace [attribute] is not present, then the enclosing
8180 * <schema> must have a targetNamespace [attribute].
8181 */
8182 if (schema->targetNamespace == NULL) {
8183 xmlSchemaPCustomErr(ctxt,
8184 XML_SCHEMAP_SRC_IMPORT_1_2,
8185 NULL, NULL, node,
8186 "The attribute 'namespace' must be existent if "
8187 "the importing schema has no target namespace",
8188 NULL);
8189 return (XML_SCHEMAP_SRC_IMPORT_1_2);
8190 }
8191 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008192 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008193 * Add the namespace to the list of locally imported namespace.
8194 */
8195 if (ctxt->localImports == NULL) {
8196 ctxt->localImports = (const xmlChar **) xmlMalloc(10 *
8197 sizeof(const xmlChar*));
8198 ctxt->sizeLocalImports = 10;
8199 ctxt->nbLocalImports = 0;
8200 } else if (ctxt->sizeLocalImports <= ctxt->nbLocalImports) {
8201 ctxt->sizeLocalImports *= 2;
8202 ctxt->localImports = (const xmlChar **) xmlRealloc(
8203 (xmlChar **) ctxt->localImports,
8204 ctxt->sizeLocalImports * sizeof(const xmlChar*));
8205 }
8206 ctxt->localImports[ctxt->nbLocalImports++] = namespaceName;
8207 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008208 * Locate and aquire the schema document.
William M. Brack2f2a6632004-08-20 23:09:47 +00008209 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008210 ret = xmlSchemaAcquireSchemaDoc(ctxt, schema, node, namespaceName,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008211 schemaLocation, &doc, &targetNamespace, 0);
8212 if (ret != 0) {
8213 if (doc != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00008214 xmlFreeDoc(doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008215 return (ret);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008216 } else if (doc != NULL) {
8217 xmlSchemaParseForImpInc(ctxt, schema, targetNamespace,
8218 xmlDocGetRootElement(doc));
William M. Brack2f2a6632004-08-20 23:09:47 +00008219 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008220
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008221 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +00008222}
8223
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008224/**
8225 * xmlSchemaParseInclude:
8226 * @ctxt: a schema validation context
8227 * @schema: the schema being built
8228 * @node: a subtree containing XML Schema informations
8229 *
8230 * parse a XML schema Include definition
8231 *
William M. Bracke7091952004-05-11 15:09:58 +00008232 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008233 * 1 in case of success.
8234 */
8235static int
8236xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
8237 xmlNodePtr node)
8238{
8239 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008240 const xmlChar *schemaLocation, *targetNamespace;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008241 xmlDocPtr doc = NULL;
8242 xmlNodePtr root = NULL;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008243 xmlSchemaIncludePtr include;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008244 int wasConvertingNs = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00008245 xmlAttrPtr attr;
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00008246 xmlParserCtxtPtr parserCtxt;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008247
8248
8249 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8250 return (-1);
8251
8252 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00008253 * Check for illegal attributes.
8254 */
8255 attr = node->properties;
8256 while (attr != NULL) {
8257 if (attr->ns == NULL) {
8258 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8259 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
8260 xmlSchemaPIllegalAttrErr(ctxt,
8261 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8262 NULL, NULL, attr);
8263 }
8264 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8265 xmlSchemaPIllegalAttrErr(ctxt,
8266 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8267 NULL, NULL, attr);
8268 }
8269 attr = attr->next;
8270 }
8271 /*
8272 * Extract and validate attributes.
8273 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008274 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00008275 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008276 * Preliminary step, extract the URI-Reference for the include and
8277 * make an URI from the base.
8278 */
William M. Brack2f2a6632004-08-20 23:09:47 +00008279 attr = xmlSchemaGetPropNode(node, "schemaLocation");
8280 if (attr != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008281 xmlChar *base = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00008282 xmlChar *uri = NULL;
8283
8284 if (xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
8285 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &schemaLocation) != 0)
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008286 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008287 base = xmlNodeGetBase(node->doc, node);
8288 if (base == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008289 uri = xmlBuildURI(schemaLocation, node->doc->URL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008290 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00008291 uri = xmlBuildURI(schemaLocation, base);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008292 xmlFree(base);
8293 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008294 if (uri == NULL) {
8295 xmlSchemaPErr(ctxt,
8296 node,
8297 XML_SCHEMAP_INTERNAL,
8298 "Internal error: xmlSchemaParseInclude, "
8299 "could not build an URI from the schemaLocation.\n",
8300 NULL, NULL);
8301 goto exit_failure;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008302 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008303 schemaLocation = xmlDictLookup(ctxt->dict, uri, -1);
8304 xmlFree(uri);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008305 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00008306 xmlSchemaPMissingAttrErr(ctxt,
8307 XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI,
8308 NULL, NULL, node, "schemaLocation", NULL);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008309 goto exit_invalid;
8310 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008311 /*
8312 * And now for the children...
8313 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008314 child = node->children;
8315 while (IS_SCHEMA(child, "annotation")) {
8316 /*
8317 * the annotations here are simply discarded ...
8318 */
8319 child = child->next;
8320 }
8321 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008322 xmlSchemaPContentErr(ctxt,
8323 XML_SCHEMAP_UNKNOWN_INCLUDE_CHILD,
8324 NULL, NULL, node, child, NULL,
8325 "(annotation?)");
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008326 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008327 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008328 * Report self-inclusion.
8329 */
8330 if (xmlStrEqual(schemaLocation, ctxt->URL)) {
8331 xmlSchemaPCustomErr(ctxt,
8332 XML_SCHEMAP_SRC_INCLUDE,
8333 NULL, NULL, node,
8334 "The schema document '%s' cannot include itself.",
8335 schemaLocation);
8336 return (XML_SCHEMAP_SRC_INCLUDE);
8337 }
8338 /*
8339 * Check if this one was already processed to avoid incorrect
8340 * duplicate component errors and infinite circular inclusion.
8341 */
8342 include = schema->includes;
8343 while (include != NULL) {
8344 if (xmlStrEqual(include->schemaLocation, schemaLocation)) {
8345 targetNamespace = include->origTargetNamespace;
8346 if (targetNamespace == NULL) {
8347 /*
8348 * Chameleon include: skip only if it was build for
8349 * the targetNamespace of the including schema.
8350 */
8351 if (xmlStrEqual(schema->targetNamespace,
8352 include->targetNamespace)) {
8353 fprintf(stderr, "already included chameleon '%s', TNS '%s'\n",
8354 include->schemaLocation,
8355 include->origTargetNamespace);
8356 goto check_targetNamespace;
8357 }
8358 } else {
8359 fprintf(stderr, "already included '%s', TNS '%s'\n",
8360 include->schemaLocation,
8361 include->origTargetNamespace);
8362 goto check_targetNamespace;
8363 }
8364 }
8365 include = include->next;
8366 }
8367 /*
8368 * First step is to parse the input document into an DOM/Infoset
8369 * TODO: Use xmlCtxtReadFile to share the dictionary?
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00008370 */
8371 parserCtxt = xmlNewParserCtxt();
8372 if (parserCtxt == NULL) {
8373 xmlSchemaPErrMemory(NULL, "xmlSchemaParseInclude: "
8374 "allocating a parser context", NULL);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008375 goto exit_failure;
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00008376 }
8377
8378 if ((ctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
8379 xmlDictFree(parserCtxt->dict);
8380 parserCtxt->dict = ctxt->dict;
8381 xmlDictReference(parserCtxt->dict);
8382 }
8383
8384 doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
8385 NULL, SCHEMAS_PARSE_OPTIONS);
8386 xmlFreeParserCtxt(parserCtxt);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008387 if (doc == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008388 /*
8389 * TODO: It is not an error for the ·actual value· of the
8390 * schemaLocation [attribute] to fail to resolve it all, in which
8391 * case no corresponding inclusion is performed.
8392 * So do we need a warning report here?
8393 */
8394 xmlSchemaPCustomErr(ctxt,
8395 XML_SCHEMAP_FAILED_LOAD,
8396 NULL, NULL, node,
8397 "Failed to load the document '%s' for inclusion", schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008398 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008399 }
8400
8401 /*
8402 * Then extract the root of the schema
8403 */
8404 root = xmlDocGetRootElement(doc);
8405 if (root == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008406 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008407 XML_SCHEMAP_NOROOT,
William M. Brack2f2a6632004-08-20 23:09:47 +00008408 NULL, NULL, node,
8409 "The included document '%s' has no document "
8410 "element", schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008411 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008412 }
8413
8414 /*
8415 * Remove all the blank text nodes
8416 */
8417 xmlSchemaCleanupDoc(ctxt, root);
8418
8419 /*
8420 * Check the schemas top level element
8421 */
8422 if (!IS_SCHEMA(root, "schema")) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008423 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008424 XML_SCHEMAP_NOT_SCHEMA,
William M. Brack2f2a6632004-08-20 23:09:47 +00008425 NULL, NULL, node,
8426 "The document '%s' to be included is not a schema document",
8427 schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008428 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008429 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008430
William M. Brack2f2a6632004-08-20 23:09:47 +00008431 targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008432 /*
8433 * 2.1 SII has a targetNamespace [attribute], and its ·actual
8434 * value· is identical to the ·actual value· of the targetNamespace
8435 * [attribute] of SIIÂ’ (which must have such an [attribute]).
8436 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008437check_targetNamespace:
Daniel Veillardc0826a72004-08-10 14:17:33 +00008438 if (targetNamespace != NULL) {
8439 if (schema->targetNamespace == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008440 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008441 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00008442 NULL, NULL, node,
8443 "The target namespace of the included schema "
8444 "'%s' has to be absent, since the including schema "
8445 "has no target namespace",
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008446 schemaLocation);
8447 goto exit_invalid;
William M. Brack2f2a6632004-08-20 23:09:47 +00008448 } else if (!xmlStrEqual(targetNamespace, schema->targetNamespace)) {
8449 xmlSchemaPCustomErrExt(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008450 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00008451 NULL, NULL, node,
8452 "The target namespace '%s' of the included schema '%s' "
8453 "differs from '%s' of the including schema",
8454 targetNamespace, schemaLocation, schema->targetNamespace);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008455 goto exit_invalid;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008456 }
8457 } else if (schema->targetNamespace != NULL) {
8458 if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
8459 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
8460 } else
8461 wasConvertingNs = 1;
8462 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008463
8464 if (include != NULL)
8465 goto exit;
8466
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008467 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008468 * URGENT TODO: If the schema is a chameleon-include then copy the
8469 * components into the including schema and modify the targetNamespace
8470 * of those components, do nothing otherwise.
8471 * NOTE: This is currently worked-around by compiling the chameleon
8472 * for every destinct including targetNamespace; thus not performant at
8473 * the moment.
8474 * TODO: Check when the namespace in wildcards for chameleons needs
8475 * to be converted: before we built wildcard intersections or after.
8476 */
8477 /*
8478 * Register the include.
8479 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008480 include = (xmlSchemaIncludePtr) xmlMalloc(sizeof(xmlSchemaInclude));
8481 if (include == NULL) {
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008482 xmlSchemaPErrMemory(ctxt, "allocating include entry", NULL);
8483 goto exit_failure;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008484 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008485 memset(include, 0, sizeof(xmlSchemaInclude));
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008486 include->next = schema->includes;
8487 schema->includes = include;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008488 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008489 * TODO: Use the resolved URI for the this location, since it might
8490 * differ if using filenames/URIs simultaneosly.
Daniel Veillardc0826a72004-08-10 14:17:33 +00008491 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008492 include->schemaLocation = schemaLocation;
8493 include->doc = doc;
8494 /*
8495 * In case of chameleons, the original target namespace will differ
8496 * from the resulting namespace.
8497 */
8498 include->origTargetNamespace = targetNamespace;
8499 include->targetNamespace = schema->targetNamespace;
8500 /*
8501 * Compile the included schema.
8502 */
8503 xmlSchemaParseForImpInc(ctxt, schema, schema->targetNamespace, root);
8504
8505exit:
Daniel Veillardc0826a72004-08-10 14:17:33 +00008506 /*
8507 * Remove the converting flag.
8508 */
William M. Brack2f2a6632004-08-20 23:09:47 +00008509 if ((wasConvertingNs == 0) &&
8510 (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS))
Daniel Veillardc0826a72004-08-10 14:17:33 +00008511 schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008512 return (1);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008513
8514exit_invalid:
8515 if (doc != NULL) {
8516 if (include != NULL)
8517 include->doc = NULL;
8518 xmlFreeDoc(doc);
8519 }
8520 return (ctxt->err);
8521
8522exit_failure:
8523 if (doc != NULL) {
8524 if (include != NULL)
8525 include->doc = NULL;
8526 xmlFreeDoc(doc);
8527 }
8528 return (-1);
8529
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008530}
8531
8532/**
Daniel Veillard4255d502002-04-16 15:50:10 +00008533 * xmlSchemaParseChoice:
8534 * @ctxt: a schema validation context
8535 * @schema: the schema being built
8536 * @node: a subtree containing XML Schema informations
8537 *
8538 * parse a XML schema Choice definition
8539 * *WARNING* this interface is highly subject to change
8540 *
William M. Bracke7091952004-05-11 15:09:58 +00008541 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00008542 * 1 in case of success.
8543 */
8544static xmlSchemaTypePtr
8545xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008546 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008547{
8548 xmlSchemaTypePtr type, subtype, last = NULL;
8549 xmlNodePtr child = NULL;
8550 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00008551 xmlAttrPtr attr;
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00008552 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00008553
8554 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8555 return (NULL);
8556
8557
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008558 snprintf((char *) name, 30, "#ch%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008559 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00008560 if (type == NULL)
8561 return (NULL);
8562 type->node = node;
8563 type->type = XML_SCHEMA_TYPE_CHOICE;
William M. Brack2f2a6632004-08-20 23:09:47 +00008564 /*
8565 * Check for illegal attributes.
8566 */
8567 attr = node->properties;
8568 while (attr != NULL) {
8569 if (attr->ns == NULL) {
8570 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8571 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
8572 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
8573 xmlSchemaPIllegalAttrErr(ctxt,
8574 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8575 NULL, type, attr);
8576 }
8577 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8578 xmlSchemaPIllegalAttrErr(ctxt,
8579 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8580 NULL, type, attr);
8581 }
8582 attr = attr->next;
8583 }
8584 /*
8585 * Extract and validate attributes.
8586 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00008587 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008588 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
8589 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
8590 "(nonNegativeInteger | unbounded)");
William M. Brack2f2a6632004-08-20 23:09:47 +00008591 /*
8592 * And now for the children...
8593 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00008594 oldcontainer = ctxt->container;
8595 ctxt->container = (const xmlChar *) name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008596 child = node->children;
8597 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008598 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8599 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008600 }
8601 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008602 (IS_SCHEMA(child, "group")) ||
8603 (IS_SCHEMA(child, "any")) ||
8604 (IS_SCHEMA(child, "choice")) ||
8605 (IS_SCHEMA(child, "sequence"))) {
8606 subtype = NULL;
8607 if (IS_SCHEMA(child, "element")) {
8608 subtype = (xmlSchemaTypePtr)
8609 xmlSchemaParseElement(ctxt, schema, child, 0);
8610 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008611 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008612 } else if (IS_SCHEMA(child, "any")) {
8613 subtype = xmlSchemaParseAny(ctxt, schema, child);
8614 } else if (IS_SCHEMA(child, "sequence")) {
8615 subtype = xmlSchemaParseSequence(ctxt, schema, child);
8616 } else if (IS_SCHEMA(child, "choice")) {
8617 subtype = xmlSchemaParseChoice(ctxt, schema, child);
8618 }
8619 if (subtype != NULL) {
8620 if (last == NULL) {
8621 type->subtypes = subtype;
8622 last = subtype;
8623 } else {
8624 last->next = subtype;
8625 last = subtype;
8626 }
8627 last->next = NULL;
8628 }
8629 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008630 }
8631 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008632 /* TODO: error code. */
8633 xmlSchemaPContentErr(ctxt,
8634 XML_SCHEMAP_UNKNOWN_CHOICE_CHILD,
8635 NULL, type, node, child, NULL,
8636 "(annotation?, (element | group | choice | sequence | any)*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00008637 }
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00008638 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00008639 return (type);
8640}
8641
8642/**
8643 * xmlSchemaParseSequence:
8644 * @ctxt: a schema validation context
8645 * @schema: the schema being built
8646 * @node: a subtree containing XML Schema informations
8647 *
8648 * parse a XML schema Sequence definition
8649 * *WARNING* this interface is highly subject to change
8650 *
William M. Bracke7091952004-05-11 15:09:58 +00008651 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00008652 * 1 in case of success.
8653 */
8654static xmlSchemaTypePtr
8655xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008656 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008657{
8658 xmlSchemaTypePtr type, subtype, last = NULL;
8659 xmlNodePtr child = NULL;
8660 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00008661 xmlAttrPtr attr;
8662 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00008663
8664 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8665 return (NULL);
8666
William M. Brack2f2a6632004-08-20 23:09:47 +00008667 oldcontainer = ctxt->container;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008668 snprintf((char *) name, 30, "#seq%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008669 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00008670 if (type == NULL)
8671 return (NULL);
8672 type->node = node;
8673 type->type = XML_SCHEMA_TYPE_SEQUENCE;
William M. Brack2f2a6632004-08-20 23:09:47 +00008674 /*
8675 * Check for illegal attributes.
8676 */
8677 attr = node->properties;
8678 while (attr != NULL) {
8679 if (attr->ns == NULL) {
8680 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8681 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
8682 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
8683 xmlSchemaPIllegalAttrErr(ctxt,
8684 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8685 NULL, type, attr);
8686 }
8687 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8688 xmlSchemaPIllegalAttrErr(ctxt,
8689 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8690 NULL, type, attr);
8691 }
8692 attr = attr->next;
8693 }
8694 /*
8695 * Extract and validate attributes.
8696 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00008697 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008698 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
8699 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
8700 "(nonNegativeInteger | unbounded)");
William M. Brack2f2a6632004-08-20 23:09:47 +00008701 /*
8702 * And now for the children...
8703 */
8704 ctxt->container = (const xmlChar *) name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008705 child = node->children;
8706 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008707 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8708 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008709 }
8710 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008711 (IS_SCHEMA(child, "group")) ||
8712 (IS_SCHEMA(child, "any")) ||
8713 (IS_SCHEMA(child, "choice")) ||
8714 (IS_SCHEMA(child, "sequence"))) {
8715 subtype = NULL;
8716 if (IS_SCHEMA(child, "element")) {
8717 subtype = (xmlSchemaTypePtr)
8718 xmlSchemaParseElement(ctxt, schema, child, 0);
8719 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008720 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008721 } else if (IS_SCHEMA(child, "any")) {
8722 subtype = xmlSchemaParseAny(ctxt, schema, child);
8723 } else if (IS_SCHEMA(child, "choice")) {
8724 subtype = xmlSchemaParseChoice(ctxt, schema, child);
8725 } else if (IS_SCHEMA(child, "sequence")) {
8726 subtype = xmlSchemaParseSequence(ctxt, schema, child);
8727 }
8728 if (subtype != NULL) {
8729 if (last == NULL) {
8730 type->subtypes = subtype;
8731 last = subtype;
8732 } else {
8733 last->next = subtype;
8734 last = subtype;
8735 }
8736 last->next = NULL;
8737 }
8738 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008739 }
8740 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008741 xmlSchemaPContentErr(ctxt,
8742 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
8743 NULL, type, node, child, NULL,
8744 "(annotation?, (element | group | choice | sequence | any)*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00008745 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008746 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00008747
8748 return (type);
8749}
8750
8751/**
8752 * xmlSchemaParseRestriction:
8753 * @ctxt: a schema validation context
8754 * @schema: the schema being built
8755 * @node: a subtree containing XML Schema informations
Daniel Veillard4255d502002-04-16 15:50:10 +00008756 *
8757 * parse a XML schema Restriction definition
8758 * *WARNING* this interface is highly subject to change
8759 *
8760 * Returns the type definition or NULL in case of error
8761 */
8762static xmlSchemaTypePtr
8763xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00008764 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008765{
Daniel Veillard01fa6152004-06-29 17:04:39 +00008766 xmlSchemaTypePtr type, subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00008767 xmlNodePtr child = NULL;
8768 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008769 const xmlChar *oldcontainer;
William M. Brack2f2a6632004-08-20 23:09:47 +00008770 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00008771
8772 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8773 return (NULL);
8774
8775 oldcontainer = ctxt->container;
8776
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008777 snprintf((char *) name, 30, "#restr%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008778 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00008779 if (type == NULL)
8780 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00008781 type->type = XML_SCHEMA_TYPE_RESTRICTION;
Daniel Veillard4255d502002-04-16 15:50:10 +00008782 type->node = node;
William M. Brack2f2a6632004-08-20 23:09:47 +00008783 /*
8784 * Check for illegal attributes.
8785 */
8786 attr = node->properties;
8787 while (attr != NULL) {
8788 if (attr->ns == NULL) {
8789 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8790 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
8791 xmlSchemaPIllegalAttrErr(ctxt,
8792 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8793 NULL, type, attr);
8794 }
8795 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8796 xmlSchemaPIllegalAttrErr(ctxt,
8797 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8798 NULL, type, attr);
8799 }
8800 attr = attr->next;
8801 }
8802 /*
8803 * Extract and validate attributes.
8804 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00008805 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00008806 /*
8807 * Attribute "base".
8808 */
Daniel Veillard4255d502002-04-16 15:50:10 +00008809 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
Daniel Veillard01fa6152004-06-29 17:04:39 +00008810 if ((type->base == NULL) &&
William M. Brack2f2a6632004-08-20 23:09:47 +00008811 (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX)) {
8812 /* TODO: Think about the error code. */
8813 xmlSchemaPMissingAttrErr(ctxt,
8814 XML_SCHEMAP_RESTRICTION_NONAME_NOREF,
8815 NULL, type, node, "base", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008816 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008817 /*
8818 * And now for the children...
8819 */
Daniel Veillard4255d502002-04-16 15:50:10 +00008820 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008821 child = node->children;
8822 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008823 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8824 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008825 }
8826 subtype = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008827 if (ctxt->parentItem->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
8828 if (IS_SCHEMA(child, "all")) {
8829 subtype = (xmlSchemaTypePtr)
8830 xmlSchemaParseAll(ctxt, schema, child);
8831 child = child->next;
8832 type->subtypes = subtype;
8833 } else if (IS_SCHEMA(child, "choice")) {
8834 subtype = xmlSchemaParseChoice(ctxt, schema, child);
8835 child = child->next;
8836 type->subtypes = subtype;
8837 } else if (IS_SCHEMA(child, "sequence")) {
8838 subtype = (xmlSchemaTypePtr)
8839 xmlSchemaParseSequence(ctxt, schema, child);
8840 child = child->next;
8841 type->subtypes = subtype;
8842 } else if (IS_SCHEMA(child, "group")) {
8843 subtype = (xmlSchemaTypePtr)
8844 xmlSchemaParseGroup(ctxt, schema, child, 0);
8845 child = child->next;
8846 type->subtypes = subtype;
8847 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008848 } else if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_SIMPLE) {
8849 if (IS_SCHEMA(child, "simpleType")) {
8850 if (type->base != NULL) {
8851 /*
8852 * src-restriction-base-or-simpleType
8853 * Either the base [attribute] or the simpleType [child] of the
8854 * <restriction> element must be present, but not both.
8855 */
8856 xmlSchemaPContentErr(ctxt,
8857 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
8858 NULL, NULL, type->node, child,
8859 "The attribute 'base' and the <simpleType> child are "
8860 "mutually exclusive", NULL);
8861 } else {
8862 subtype = (xmlSchemaTypePtr)
8863 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
8864 type->baseType = subtype;
8865 }
8866 child = child->next;
8867 }
8868 } else if (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00008869 if (IS_SCHEMA(child, "simpleType")) {
8870 subtype = (xmlSchemaTypePtr)
8871 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008872 type->subtypes = subtype;
8873 child = child->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00008874 }
8875 }
8876 if ((ctxt->ctxtType->type == XML_SCHEMA_TYPE_SIMPLE) ||
8877 (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
8878 xmlSchemaFacetPtr facet, lastfacet = NULL;
8879
Daniel Veillard01fa6152004-06-29 17:04:39 +00008880 /*
8881 * Add the facets to the parent simpleType/complexType.
8882 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00008883 /*
8884 * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
8885 * Simple Type Definition Schema Representation Constraint:
8886 * *Single Facet Value*
8887 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00008888 while ((IS_SCHEMA(child, "minInclusive")) ||
8889 (IS_SCHEMA(child, "minExclusive")) ||
8890 (IS_SCHEMA(child, "maxInclusive")) ||
8891 (IS_SCHEMA(child, "maxExclusive")) ||
8892 (IS_SCHEMA(child, "totalDigits")) ||
8893 (IS_SCHEMA(child, "fractionDigits")) ||
8894 (IS_SCHEMA(child, "pattern")) ||
8895 (IS_SCHEMA(child, "enumeration")) ||
8896 (IS_SCHEMA(child, "whiteSpace")) ||
8897 (IS_SCHEMA(child, "length")) ||
8898 (IS_SCHEMA(child, "maxLength")) ||
8899 (IS_SCHEMA(child, "minLength"))) {
8900 facet = xmlSchemaParseFacet(ctxt, schema, child);
8901 if (facet != NULL) {
8902 if (lastfacet == NULL)
8903 ctxt->ctxtType->facets = facet;
8904 else
8905 lastfacet->next = facet;
8906 lastfacet = facet;
8907 lastfacet->next = NULL;
8908 }
8909 child = child->next;
8910 }
8911 /*
8912 * Create links for derivation and validation.
8913 */
8914 if (lastfacet != NULL) {
8915 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
8916
8917 facet = ctxt->ctxtType->facets;
8918 do {
8919 facetLink = (xmlSchemaFacetLinkPtr) xmlMalloc(sizeof(xmlSchemaFacetLink));
8920 if (facetLink == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008921 xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008922 xmlFree(facetLink);
8923 return (NULL);
8924 }
8925 facetLink->facet = facet;
8926 facetLink->next = NULL;
8927 if (lastFacetLink == NULL)
8928 ctxt->ctxtType->facetSet = facetLink;
8929 else
8930 lastFacetLink->next = facetLink;
8931 lastFacetLink = facetLink;
8932 facet = facet->next;
8933 } while (facet != NULL);
8934 }
8935 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008936 if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX) {
8937 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
8938 if (IS_SCHEMA(child, "anyAttribute")) {
8939 ctxt->ctxtType->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
8940 child = child->next;
8941 }
8942 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008943 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008944 /* TODO: Think about the error code. */
8945 if (ctxt->parentItem->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
8946 xmlSchemaPContentErr(ctxt,
8947 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
8948 NULL, type, node, child, NULL,
8949 "annotation?, (group | all | choice | sequence)?, "
8950 "((attribute | attributeGroup)*, anyAttribute?))");
8951 } else if (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
8952 xmlSchemaPContentErr(ctxt,
8953 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
8954 NULL, type, node, child, NULL,
8955 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
8956 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
8957 "length | minLength | maxLength | enumeration | whiteSpace | "
8958 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
8959 } else {
8960 /* Simple type */
8961 xmlSchemaPContentErr(ctxt,
8962 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
8963 NULL, type, node, child, NULL,
8964 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
8965 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
8966 "length | minLength | maxLength | enumeration | whiteSpace | "
8967 "pattern)*))");
8968 }
8969 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008970 ctxt->container = oldcontainer;
8971 return (type);
8972}
8973
8974/**
8975 * xmlSchemaParseExtension:
8976 * @ctxt: a schema validation context
8977 * @schema: the schema being built
8978 * @node: a subtree containing XML Schema informations
8979 *
8980 * parse a XML schema Extension definition
8981 * *WARNING* this interface is highly subject to change
8982 *
8983 * Returns the type definition or NULL in case of error
8984 */
8985static xmlSchemaTypePtr
8986xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008987 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008988{
8989 xmlSchemaTypePtr type, subtype;
8990 xmlNodePtr child = NULL;
8991 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008992 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00008993
8994 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8995 return (NULL);
8996
8997 oldcontainer = ctxt->container;
8998
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008999 snprintf((char *) name, 30, "#ext%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00009000 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00009001 if (type == NULL)
9002 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00009003 type->type = XML_SCHEMA_TYPE_EXTENSION;
Daniel Veillard4255d502002-04-16 15:50:10 +00009004 type->node = node;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00009005
9006 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
9007
Daniel Veillard4255d502002-04-16 15:50:10 +00009008 ctxt->container = name;
9009
9010 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
9011 if (type->base == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009012 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_EXTENSION_NO_BASE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009013 "<extension>: The attribute \"base\" is missing.\n",
9014 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009015 }
9016 child = node->children;
9017 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009018 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
9019 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009020 }
9021 subtype = NULL;
9022
9023 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009024 subtype = xmlSchemaParseAll(ctxt, schema, child);
9025 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009026 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009027 subtype = xmlSchemaParseChoice(ctxt, schema, child);
9028 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009029 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009030 subtype = xmlSchemaParseSequence(ctxt, schema, child);
9031 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009032 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009033 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009034 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009035 }
9036 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009037 type->subtypes = subtype;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009038 if ((ctxt->ctxtType != NULL) &&
9039 (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX)) {
9040 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
9041 if (IS_SCHEMA(child, "anyAttribute")) {
9042 ctxt->ctxtType->attributeWildcard =
9043 xmlSchemaParseAnyAttribute(ctxt, schema, child);
9044 child = child->next;
9045 }
9046 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009047 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009048 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009049 XML_SCHEMAP_UNKNOWN_EXTENSION_CHILD,
9050 "<extension> has unexpected content.\n", type->name,
9051 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009052 }
9053 ctxt->container = oldcontainer;
9054 return (type);
9055}
9056
9057/**
9058 * xmlSchemaParseSimpleContent:
9059 * @ctxt: a schema validation context
9060 * @schema: the schema being built
9061 * @node: a subtree containing XML Schema informations
9062 *
9063 * parse a XML schema SimpleContent definition
9064 * *WARNING* this interface is highly subject to change
9065 *
9066 * Returns the type definition or NULL in case of error
9067 */
9068static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009069xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
9070 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00009071{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009072 xmlSchemaTypePtr type, subtype, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00009073 xmlNodePtr child = NULL;
9074 xmlChar name[30];
9075
9076 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9077 return (NULL);
9078
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00009079 snprintf((char *) name, 30, "#SC%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00009080 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00009081 if (type == NULL)
9082 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00009083 type->type = XML_SCHEMA_TYPE_SIMPLE_CONTENT;
Daniel Veillard4255d502002-04-16 15:50:10 +00009084 type->node = node;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00009085
9086 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00009087
9088 child = node->children;
9089 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009090 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
9091 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009092 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009093 oldParentItem = ctxt->parentItem;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009094 ctxt->parentItem = type;
9095 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00009096 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009097 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009098 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009099 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009100 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009101 subtype = (xmlSchemaTypePtr)
9102 xmlSchemaParseExtension(ctxt, schema, child);
9103 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009104 }
9105 type->subtypes = subtype;
9106 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009107 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009108 XML_SCHEMAP_UNKNOWN_SIMPLECONTENT_CHILD,
9109 "<simpleContent> has unexpected content.\n",
9110 NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009111 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009112 ctxt->parentItem = oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00009113 return (type);
9114}
9115
9116/**
9117 * xmlSchemaParseComplexContent:
9118 * @ctxt: a schema validation context
9119 * @schema: the schema being built
9120 * @node: a subtree containing XML Schema informations
9121 *
9122 * parse a XML schema ComplexContent definition
9123 * *WARNING* this interface is highly subject to change
9124 *
9125 * Returns the type definition or NULL in case of error
9126 */
9127static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009128xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
9129 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00009130{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009131 xmlSchemaTypePtr type, subtype, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00009132 xmlNodePtr child = NULL;
9133 xmlChar name[30];
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009134 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00009135
9136 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9137 return (NULL);
9138
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00009139 snprintf((char *) name, 30, "#CC%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00009140 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00009141 if (type == NULL)
9142 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00009143 type->type = XML_SCHEMA_TYPE_COMPLEX_CONTENT;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009144 type->node = node;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009145 /*
9146 * Check for illegal attributes.
9147 */
9148 attr = node->properties;
9149 while (attr != NULL) {
9150 if (attr->ns == NULL) {
9151 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9152 (!xmlStrEqual(attr->name, BAD_CAST "mixed")))
9153 {
9154 xmlSchemaPIllegalAttrErr(ctxt,
9155 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9156 NULL, NULL, attr);
9157 }
9158 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9159 xmlSchemaPIllegalAttrErr(ctxt,
9160 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9161 NULL, NULL, attr);
9162 }
9163 attr = attr->next;
9164 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00009165
9166 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
9167
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009168 /*
9169 * Handle attribute 'mixed'.
9170 */
9171 if (xmlGetBooleanProp(ctxt, NULL, type, node, "mixed", 0)) {
9172 if ((ctxt->ctxtType->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
9173 ctxt->ctxtType->flags |= XML_SCHEMAS_TYPE_MIXED;
9174 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009175 child = node->children;
9176 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009177 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
9178 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009179 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009180 oldParentItem = ctxt->parentItem;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009181 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00009182 subtype = NULL;
9183 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009184 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009185 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009186 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009187 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009188 subtype = (xmlSchemaTypePtr)
9189 xmlSchemaParseExtension(ctxt, schema, child);
9190 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009191 }
9192 type->subtypes = subtype;
9193 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009194 xmlSchemaPContentErr(ctxt,
9195 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9196 NULL, NULL, node, child,
9197 NULL, "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +00009198 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009199 ctxt->parentItem = oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00009200 return (type);
9201}
9202
9203/**
9204 * xmlSchemaParseComplexType:
9205 * @ctxt: a schema validation context
9206 * @schema: the schema being built
9207 * @node: a subtree containing XML Schema informations
9208 *
9209 * parse a XML schema Complex Type definition
9210 * *WARNING* this interface is highly subject to change
9211 *
9212 * Returns the type definition or NULL in case of error
9213 */
9214static xmlSchemaTypePtr
9215xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00009216 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00009217{
Daniel Veillard01fa6152004-06-29 17:04:39 +00009218 xmlSchemaTypePtr type, subtype, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00009219 xmlNodePtr child = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009220 const xmlChar *name = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00009221 const xmlChar *oldcontainer;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009222 xmlAttrPtr attr;
9223 const xmlChar *attrValue;
9224 xmlChar *des = NULL; /* The reported designation. */
Daniel Veillard1a380b82004-10-21 16:00:06 +00009225 char buf[40];
9226
Daniel Veillard4255d502002-04-16 15:50:10 +00009227
9228 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9229 return (NULL);
9230
Daniel Veillard01fa6152004-06-29 17:04:39 +00009231 ctxtType = ctxt->ctxtType;
9232
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009233 if (topLevel) {
9234 attr = xmlSchemaGetPropNode(node, "name");
9235 if (attr == NULL) {
9236 xmlSchemaPMissingAttrErr(ctxt,
9237 XML_SCHEMAP_S4S_ATTR_MISSING,
9238 (xmlChar **) &xmlSchemaElemDesCT, NULL, node,
9239 "name", NULL);
9240 return (NULL);
9241 } else if (xmlSchemaPValAttrNode(ctxt,
9242 (xmlChar **) &xmlSchemaElemDesCT, NULL, attr,
9243 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
9244 return (NULL);
9245 }
9246 }
9247
9248 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009249 /*
9250 * Parse as local complex type definition.
9251 */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00009252 snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009253 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
9254 if (type == NULL)
9255 return (NULL);
9256 name = (const xmlChar *) buf;
9257 type->node = node;
9258 type->type = XML_SCHEMA_TYPE_COMPLEX;
9259 /*
9260 * TODO: We need the target namespace.
9261 */
9262 } else {
9263 /*
9264 * Parse as global complex type definition.
9265 */
William M. Brack2f2a6632004-08-20 23:09:47 +00009266 type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace, node);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009267 if (type == NULL)
9268 return (NULL);
9269 type->node = node;
9270 type->type = XML_SCHEMA_TYPE_COMPLEX;
9271 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
9272 /*
9273 * Set defaults.
9274 */
9275 type->flags |= XML_SCHEMAS_TYPE_FINAL_DEFAULT;
9276 type->flags |= XML_SCHEMAS_TYPE_BLOCK_DEFAULT;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00009277 }
9278 type->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009279 /*
9280 * Handle attributes.
9281 */
9282 attr = node->properties;
9283 while (attr != NULL) {
9284 if (attr->ns == NULL) {
9285 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
9286 /*
9287 * Attribute "id".
9288 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00009289 xmlSchemaPValAttrID(ctxt, NULL, type, node,
9290 BAD_CAST "id");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009291 } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
9292 /*
9293 * Attribute "mixed".
9294 */
9295 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
9296 (xmlNodePtr) attr))
9297 type->flags |= XML_SCHEMAS_TYPE_MIXED;
9298 } else if (topLevel) {
9299 /*
9300 * Attributes of global complex type definitions.
9301 */
9302 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
9303 /* Pass. */
9304 } else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
9305 /*
9306 * Attribute "abstract".
9307 */
9308 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
9309 (xmlNodePtr) attr))
9310 type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
9311 } else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
9312 /*
9313 * Attribute "final".
9314 */
9315 attrValue = xmlSchemaGetNodeContent(ctxt,
9316 (xmlNodePtr) attr);
9317 if (xmlSchemaPValAttrBlockFinal(attrValue,
9318 &(type->flags),
9319 -1,
9320 XML_SCHEMAS_TYPE_FINAL_EXTENSION,
9321 XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
9322 -1, -1, -1) != 0)
9323 {
9324 xmlSchemaPSimpleTypeErr(ctxt,
9325 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9326 &des, type, (xmlNodePtr) attr,
9327 NULL,
9328 "(#all | List of (extension | restriction))",
9329 attrValue, NULL, NULL, NULL);
9330 }
9331 } else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
9332 /*
9333 * Attribute "block".
9334 */
9335 attrValue = xmlSchemaGetNodeContent(ctxt,
9336 (xmlNodePtr) attr);
9337 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
9338 -1,
9339 XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
9340 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
9341 -1, -1, -1) != 0) {
9342 xmlSchemaPSimpleTypeErr(ctxt,
9343 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9344 &des, type, (xmlNodePtr) attr,
9345 NULL,
9346 "(#all | List of (extension | restriction)) ",
9347 attrValue, NULL, NULL, NULL);
9348 }
9349 } else {
9350 xmlSchemaPIllegalAttrErr(ctxt,
9351 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9352 &des, type, attr);
9353 }
9354 } else {
9355 xmlSchemaPIllegalAttrErr(ctxt,
9356 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9357 &des, type, attr);
9358 }
9359 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9360 xmlSchemaPIllegalAttrErr(ctxt,
9361 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9362 &des, type, attr);
9363 }
9364 attr = attr->next;
9365 }
9366 /*
9367 * Set as default for attribute wildcards.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009368 * This will be only changed if a complex type
9369 * inherits an attribute wildcard from a base type.
9370 */
9371 type->flags |= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009372 /*
9373 * And now for the children...
9374 */
9375 oldcontainer = ctxt->container;
9376 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +00009377 child = node->children;
9378 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009379 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
9380 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009381 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00009382 ctxt->ctxtType = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00009383 if (IS_SCHEMA(child, "simpleContent")) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009384 /*
9385 * 3.4.3 : 2.2
9386 * Specifying mixed='true' when the <simpleContent>
9387 * alternative is chosen has no effect
9388 */
William M. Bracke7091952004-05-11 15:09:58 +00009389 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
9390 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009391 type->subtypes = xmlSchemaParseSimpleContent(ctxt, schema, child);
9392 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009393 } else if (IS_SCHEMA(child, "complexContent")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009394 type->subtypes = xmlSchemaParseComplexContent(ctxt, schema, child);
9395 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009396 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009397 subtype = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009398 /*
9399 * Parse model groups.
9400 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009401 if (IS_SCHEMA(child, "all")) {
9402 subtype = xmlSchemaParseAll(ctxt, schema, child);
9403 child = child->next;
9404 } else if (IS_SCHEMA(child, "choice")) {
9405 subtype = xmlSchemaParseChoice(ctxt, schema, child);
9406 child = child->next;
9407 } else if (IS_SCHEMA(child, "sequence")) {
9408 subtype = xmlSchemaParseSequence(ctxt, schema, child);
9409 child = child->next;
9410 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009411 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009412 child = child->next;
9413 }
9414 if (subtype != NULL)
9415 type->subtypes = subtype;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009416 /*
9417 * Parse attribute decls/refs.
9418 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009419 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009420 /*
9421 * Parse attribute wildcard.
9422 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009423 if (IS_SCHEMA(child, "anyAttribute")) {
9424 type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
9425 child = child->next;
9426 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009427 }
9428 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009429 xmlSchemaPContentErr(ctxt,
9430 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9431 &des, type, node, child,
9432 NULL, "(annotation?, (simpleContent | complexContent | "
9433 "((group | all | choice | sequence)?, ((attribute | "
9434 "attributeGroup)*, anyAttribute?))))");
Daniel Veillard4255d502002-04-16 15:50:10 +00009435 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009436 FREE_AND_NULL(des);
Daniel Veillard4255d502002-04-16 15:50:10 +00009437 ctxt->container = oldcontainer;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009438 ctxt->ctxtType = ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00009439 return (type);
9440}
9441
Daniel Veillard4255d502002-04-16 15:50:10 +00009442/**
9443 * xmlSchemaParseSchema:
9444 * @ctxt: a schema validation context
9445 * @node: a subtree containing XML Schema informations
9446 *
9447 * parse a XML schema definition from a node set
9448 * *WARNING* this interface is highly subject to change
9449 *
9450 * Returns the internal XML Schema structure built from the resource or
9451 * NULL in case of error
9452 */
9453static xmlSchemaPtr
9454xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
9455{
9456 xmlSchemaPtr schema = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009457 const xmlChar *val;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00009458 int nberrors;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009459 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00009460
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009461 /*
9462 * This one is called by xmlSchemaParse only and is used if
9463 * the schema to be parsed was specified via the API; i.e. not
9464 * automatically by the validated instance document.
9465 */
Daniel Veillard4255d502002-04-16 15:50:10 +00009466 if ((ctxt == NULL) || (node == NULL))
9467 return (NULL);
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00009468 nberrors = ctxt->nberrors;
9469 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00009470 if (IS_SCHEMA(node, "schema")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009471 xmlSchemaImportPtr import;
9472
Daniel Veillard4255d502002-04-16 15:50:10 +00009473 schema = xmlSchemaNewSchema(ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009474 if (schema == NULL)
9475 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009476 /*
9477 * Disable build of list of items.
9478 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00009479 attr = xmlSchemaGetPropNode(node, "targetNamespace");
9480 if (attr != NULL) {
9481 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
9482 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &val);
9483 /*
9484 * TODO: Should we proceed with an invalid target namespace?
9485 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009486 schema->targetNamespace = xmlDictLookup(ctxt->dict, val, -1);
9487 } else {
9488 schema->targetNamespace = NULL;
9489 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009490 /*
9491 * Add the current ns name and location to the import table;
9492 * this is needed to have a consistent mechanism, regardless
9493 * if all schemata are constructed dynamically fired by the
9494 * instance or if the schema to be used was specified via
9495 * the API.
9496 */
9497 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports),
9498 schema->targetNamespace);
9499 if (import == NULL) {
9500 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT,
9501 NULL, NULL, (xmlNodePtr) ctxt->doc,
9502 "Internal error: xmlSchemaParseSchema, "
9503 "failed to add an import entry", NULL);
9504 xmlSchemaFree(schema);
9505 schema = NULL;
9506 return (NULL);
9507 }
9508 import->schemaLocation = ctxt->URL;
9509 /*
9510 * NOTE: We won't set the doc here, otherwise it will be freed
9511 * if the import struct is freed.
9512 * import->doc = ctxt->doc;
9513 */
William M. Brack2f2a6632004-08-20 23:09:47 +00009514 xmlSchemaParseSchemaDefaults(ctxt, schema, node);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009515 xmlSchemaParseSchemaTopLevel(ctxt, schema, node->children);
9516 } else {
9517 xmlDocPtr doc;
9518
9519 doc = node->doc;
9520
9521 if ((doc != NULL) && (doc->URL != NULL)) {
9522 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
9523 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009524 "The file \"%s\" is not a XML schema.\n", doc->URL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009525 } else {
9526 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
9527 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009528 "The file is not a XML schema.\n", NULL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009529 }
9530 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009531 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00009532 if (ctxt->nberrors != 0) {
9533 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009534 xmlSchemaFree(schema);
9535 schema = NULL;
9536 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00009537 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009538 if (schema != NULL)
9539 schema->counter = ctxt->counter;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00009540 ctxt->nberrors = nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00009541#ifdef DEBUG
9542 if (schema == NULL)
9543 xmlGenericError(xmlGenericErrorContext,
9544 "xmlSchemaParse() failed\n");
9545#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00009546 return (schema);
9547}
9548
9549/************************************************************************
9550 * *
9551 * Validating using Schemas *
9552 * *
9553 ************************************************************************/
9554
9555/************************************************************************
9556 * *
9557 * Reading/Writing Schemas *
9558 * *
9559 ************************************************************************/
9560
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009561#if 0 /* Will be enabled if it is clear what options are needed. */
9562/**
9563 * xmlSchemaParserCtxtSetOptions:
9564 * @ctxt: a schema parser context
9565 * @options: a combination of xmlSchemaParserOption
9566 *
9567 * Sets the options to be used during the parse.
9568 *
9569 * Returns 0 in case of success, -1 in case of an
9570 * API error.
9571 */
9572static int
9573xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
9574 int options)
9575
9576{
9577 int i;
9578
9579 if (ctxt == NULL)
9580 return (-1);
9581 /*
9582 * WARNING: Change the start value if adding to the
9583 * xmlSchemaParseOption.
9584 */
9585 for (i = 1; i < (int) sizeof(int) * 8; i++) {
9586 if (options & 1<<i) {
9587 return (-1);
9588 }
9589 }
9590 ctxt->options = options;
9591 return (0);
9592}
9593
9594/**
9595 * xmlSchemaValidCtxtGetOptions:
9596 * @ctxt: a schema parser context
9597 *
9598 * Returns the option combination of the parser context.
9599 */
9600static int
9601xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
9602
9603{
9604 if (ctxt == NULL)
9605 return (-1);
9606 else
9607 return (ctxt->options);
9608}
9609
9610 void *curItems; /* used for dynamic addition of schemata */
9611 int nbCurItems; /* used for dynamic addition of schemata */
9612 int sizeCurItems; /* used for dynamic addition of schemata */
9613
9614#endif
9615
Daniel Veillard4255d502002-04-16 15:50:10 +00009616/**
9617 * xmlSchemaNewParserCtxt:
9618 * @URL: the location of the schema
9619 *
9620 * Create an XML Schemas parse context for that file/resource expected
9621 * to contain an XML Schemas file.
9622 *
9623 * Returns the parser context or NULL in case of error
9624 */
9625xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009626xmlSchemaNewParserCtxt(const char *URL)
9627{
Daniel Veillard4255d502002-04-16 15:50:10 +00009628 xmlSchemaParserCtxtPtr ret;
9629
9630 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009631 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009632
9633 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9634 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009635 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009636 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009637 return (NULL);
9638 }
9639 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009640 ret->dict = xmlDictCreate();
9641 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00009642 ret->includes = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00009643 return (ret);
9644}
9645
9646/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009647 * xmlSchemaNewParserCtxtUseDict:
9648 * @URL: the location of the schema
9649 * @dict: the dictionary to be used
9650 *
9651 * Create an XML Schemas parse context for that file/resource expected
9652 * to contain an XML Schemas file.
9653 *
9654 * Returns the parser context or NULL in case of error
9655 */
9656static xmlSchemaParserCtxtPtr
9657xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
9658{
9659 xmlSchemaParserCtxtPtr ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009660 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009661 if (URL == NULL)
9662 return (NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009663 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009664
9665 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9666 if (ret == NULL) {
9667 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
9668 NULL);
9669 return (NULL);
9670 }
9671 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
9672 ret->dict = dict;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009673 xmlDictReference(dict);
9674 if (URL != NULL)
9675 ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009676 ret->includes = 0;
9677 return (ret);
9678}
9679
9680
9681/**
Daniel Veillard6045c902002-10-09 21:13:59 +00009682 * xmlSchemaNewMemParserCtxt:
9683 * @buffer: a pointer to a char array containing the schemas
9684 * @size: the size of the array
9685 *
9686 * Create an XML Schemas parse context for that memory buffer expected
9687 * to contain an XML Schemas file.
9688 *
9689 * Returns the parser context or NULL in case of error
9690 */
9691xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009692xmlSchemaNewMemParserCtxt(const char *buffer, int size)
9693{
Daniel Veillard6045c902002-10-09 21:13:59 +00009694 xmlSchemaParserCtxtPtr ret;
9695
9696 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009697 return (NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00009698
9699 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9700 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009701 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009702 NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00009703 return (NULL);
9704 }
9705 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
9706 ret->buffer = buffer;
9707 ret->size = size;
William M. Brackcf9eadf2003-12-25 13:24:05 +00009708 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +00009709 return (ret);
9710}
9711
9712/**
Daniel Veillard9d751502003-10-29 13:21:47 +00009713 * xmlSchemaNewDocParserCtxt:
9714 * @doc: a preparsed document tree
9715 *
9716 * Create an XML Schemas parse context for that document.
9717 * NB. The document may be modified during the parsing process.
9718 *
9719 * Returns the parser context or NULL in case of error
9720 */
9721xmlSchemaParserCtxtPtr
9722xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
9723{
9724 xmlSchemaParserCtxtPtr ret;
9725
9726 if (doc == NULL)
9727 return (NULL);
9728
9729 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9730 if (ret == NULL) {
9731 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
9732 NULL);
9733 return (NULL);
9734 }
9735 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
9736 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +00009737 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +00009738 /* The application has responsibility for the document */
9739 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +00009740
9741 return (ret);
9742}
9743
9744/**
Daniel Veillard4255d502002-04-16 15:50:10 +00009745 * xmlSchemaFreeParserCtxt:
9746 * @ctxt: the schema parser context
9747 *
9748 * Free the resources associated to the schema parser context
9749 */
9750void
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009751xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
9752{
Daniel Veillard4255d502002-04-16 15:50:10 +00009753 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009754 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +00009755 if (ctxt->doc != NULL && !ctxt->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009756 xmlFreeDoc(ctxt->doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009757 if (ctxt->assemble != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009758 xmlFree((xmlSchemaTypePtr *) ctxt->assemble->items);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009759 xmlFree(ctxt->assemble);
9760 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009761 if (ctxt->vctxt != NULL) {
9762 xmlSchemaFreeValidCtxt(ctxt->vctxt);
9763 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009764 if (ctxt->localImports != NULL)
9765 xmlFree((xmlChar *) ctxt->localImports);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009766 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00009767 xmlFree(ctxt);
9768}
9769
9770/************************************************************************
9771 * *
9772 * Building the content models *
9773 * *
9774 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009775
Daniel Veillard4255d502002-04-16 15:50:10 +00009776/**
9777 * xmlSchemaBuildAContentModel:
9778 * @type: the schema type definition
9779 * @ctxt: the schema parser context
9780 * @name: the element name whose content is being built
9781 *
9782 * Generate the automata sequence needed for that type
9783 */
9784static void
9785xmlSchemaBuildAContentModel(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009786 xmlSchemaParserCtxtPtr ctxt,
9787 const xmlChar * name)
9788{
Daniel Veillard4255d502002-04-16 15:50:10 +00009789 if (type == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009790 xmlGenericError(xmlGenericErrorContext,
9791 "Found unexpected type = NULL in %s content model\n",
9792 name);
9793 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00009794 }
9795 switch (type->type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009796 case XML_SCHEMA_TYPE_ANY: {
9797 xmlAutomataStatePtr start, end;
9798 xmlSchemaWildcardPtr wild;
9799 xmlSchemaWildcardNsPtr ns;
Daniel Veillard32370232002-10-16 14:08:14 +00009800
Daniel Veillardc0826a72004-08-10 14:17:33 +00009801 wild = type->attributeWildcard;
9802
9803 if (wild == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00009804 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009805 "Internal error: xmlSchemaBuildAContentModel, "
9806 "no wildcard on xsd:any.\n", NULL, NULL);
9807 return;
9808 }
9809
9810 start = ctxt->state;
9811 end = xmlAutomataNewState(ctxt->am);
9812
9813 if (type->maxOccurs == 1) {
9814 if (wild->any == 1) {
9815 /*
9816 * We need to add both transitions:
9817 *
9818 * 1. the {"*", "*"} for elements in a namespace.
9819 */
9820 ctxt->state =
9821 xmlAutomataNewTransition2(ctxt->am,
9822 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
9823 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9824 /*
9825 * 2. the {"*"} for elements in no namespace.
9826 */
9827 ctxt->state =
9828 xmlAutomataNewTransition2(ctxt->am,
9829 start, NULL, BAD_CAST "*", NULL, type);
9830 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9831
9832 } else if (wild->nsSet != NULL) {
9833 ns = wild->nsSet;
9834 do {
9835 ctxt->state = start;
9836 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9837 ctxt->state, NULL, BAD_CAST "*", ns->value, type);
9838 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9839 ns = ns->next;
9840 } while (ns != NULL);
9841
9842 } else if (wild->negNsSet != NULL) {
9843 xmlAutomataStatePtr deadEnd;
9844
9845 deadEnd = xmlAutomataNewState(ctxt->am);
9846 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9847 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, type);
9848 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9849 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
9850 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9851 }
9852 } else {
9853 int counter;
9854 xmlAutomataStatePtr hop;
9855 int maxOccurs =
9856 type->maxOccurs == UNBOUNDED ? UNBOUNDED : type->maxOccurs - 1;
9857 int minOccurs =
9858 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
9859
9860 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
9861 hop = xmlAutomataNewState(ctxt->am);
9862 if (wild->any == 1) {
9863 ctxt->state =
9864 xmlAutomataNewTransition2(ctxt->am,
9865 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
9866 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
9867 ctxt->state =
9868 xmlAutomataNewTransition2(ctxt->am,
9869 start, NULL, BAD_CAST "*", NULL, type);
9870 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
9871 } else if (wild->nsSet != NULL) {
9872 ns = wild->nsSet;
9873 do {
9874 ctxt->state =
9875 xmlAutomataNewTransition2(ctxt->am,
9876 start, NULL, BAD_CAST "*", ns->value, type);
9877 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
9878 ns = ns->next;
9879 } while (ns != NULL);
9880
9881 } else if (wild->negNsSet != NULL) {
9882 xmlAutomataStatePtr deadEnd;
9883
9884 deadEnd = xmlAutomataNewState(ctxt->am);
9885 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9886 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, type);
9887 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9888 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
9889 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
9890 }
9891 xmlAutomataNewCountedTrans(ctxt->am, hop, start, counter);
9892 xmlAutomataNewCounterTrans(ctxt->am, hop, end, counter);
9893 }
9894 if (type->minOccurs == 0) {
9895 xmlAutomataNewEpsilon(ctxt->am, start, end);
9896 }
9897 ctxt->state = end;
9898 break;
9899 }
9900 case XML_SCHEMA_TYPE_ELEMENT:{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009901 xmlAutomataStatePtr oldstate;
9902 xmlSchemaElementPtr particle, elemDecl;
Daniel Veillard32370232002-10-16 14:08:14 +00009903
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009904 /*
9905 * IMPORTANT: This puts element declarations
9906 * (and never element decl. references) into the
9907 * automaton. This is crucial and should not be changed,
9908 * since validating functions rely now on it.
9909 */
9910 particle = (xmlSchemaElementPtr) type;
9911 if (particle->ref != NULL) {
9912 if (particle->refDecl == NULL) {
9913 /*
9914 * Skip content model creation if the reference
9915 * did not resolve to a declaration.
9916 */
9917 break;
9918 } else {
9919 /*
9920 * Referenced global element declaration.
9921 */
9922 elemDecl = particle->refDecl;
9923 }
9924 } else {
9925 /*
9926 * Anonymous element declaration.
9927 */
9928 elemDecl = particle;
9929 }
9930
9931 oldstate = ctxt->state;
9932
9933 if (particle->maxOccurs >= UNBOUNDED) {
9934 if (particle->minOccurs > 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009935 xmlAutomataStatePtr tmp;
9936 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00009937
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009938 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009939 oldstate, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009940 oldstate = ctxt->state;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009941 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009942 particle->minOccurs - 1, UNBOUNDED);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00009943 ctxt->state =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009944 xmlAutomataNewTransition2(ctxt->am,
9945 ctxt->state, NULL,
9946 elemDecl->name,
9947 elemDecl->targetNamespace,
9948 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009949 tmp = ctxt->state;
9950 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009951 counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009952 ctxt->state =
9953 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009954 counter);
Daniel Veillard32370232002-10-16 14:08:14 +00009955
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009956 } else {
9957 ctxt->state =
9958 xmlAutomataNewTransition2(ctxt->am,
9959 ctxt->state, NULL,
9960 elemDecl->name,
9961 elemDecl->targetNamespace,
9962 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009963 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
9964 oldstate);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009965 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009966 /* basically an elem* */
9967 xmlAutomataNewEpsilon(ctxt->am, oldstate,
9968 ctxt->state);
9969 }
9970 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009971 } else if ((particle->maxOccurs > 1) || (particle->minOccurs > 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009972 xmlAutomataStatePtr tmp;
9973 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00009974
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009975 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
9976 oldstate, NULL);
9977 oldstate = ctxt->state;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009978 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009979 particle->minOccurs - 1,
9980 particle->maxOccurs - 1);
9981 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9982 ctxt->state,
9983 NULL,
9984 elemDecl->name,
9985 elemDecl->targetNamespace,
9986 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009987 tmp = ctxt->state;
9988 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009989 counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009990 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, tmp,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009991 NULL, counter);
9992 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009993 /* basically an elem? */
9994 xmlAutomataNewEpsilon(ctxt->am, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009995 ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009996 }
Daniel Veillardb39bc392002-10-26 19:29:51 +00009997
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009998 } else {
9999 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
10000 ctxt->state,
10001 NULL,
10002 elemDecl->name,
10003 elemDecl->targetNamespace,
10004 (xmlSchemaTypePtr) elemDecl);
10005 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010006 /* basically an elem? */
10007 xmlAutomataNewEpsilon(ctxt->am, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010008 ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010009 }
10010 }
10011 break;
10012 }
10013 case XML_SCHEMA_TYPE_SEQUENCE:{
10014 xmlSchemaTypePtr subtypes;
Daniel Veillardb39bc392002-10-26 19:29:51 +000010015
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010016 /*
10017 * If max and min occurances are default (1) then
10018 * simply iterate over the subtypes
10019 */
10020 if ((type->minOccurs == 1) && (type->maxOccurs == 1)) {
10021 subtypes = type->subtypes;
10022 while (subtypes != NULL) {
10023 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
10024 subtypes = subtypes->next;
10025 }
10026 } else {
10027 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000010028
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010029 if (type->maxOccurs >= UNBOUNDED) {
10030 if (type->minOccurs > 1) {
10031 xmlAutomataStatePtr tmp;
10032 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000010033
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010034 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
10035 oldstate,
10036 NULL);
10037 oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000010038
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010039 counter = xmlAutomataNewCounter(ctxt->am,
10040 type->
10041 minOccurs - 1,
10042 UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +000010043
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010044 subtypes = type->subtypes;
10045 while (subtypes != NULL) {
10046 xmlSchemaBuildAContentModel(subtypes, ctxt,
10047 name);
10048 subtypes = subtypes->next;
10049 }
10050 tmp = ctxt->state;
10051 xmlAutomataNewCountedTrans(ctxt->am, tmp,
10052 oldstate, counter);
10053 ctxt->state =
10054 xmlAutomataNewCounterTrans(ctxt->am, tmp,
10055 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +000010056
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010057 } else {
10058 subtypes = type->subtypes;
10059 while (subtypes != NULL) {
10060 xmlSchemaBuildAContentModel(subtypes, ctxt,
10061 name);
10062 subtypes = subtypes->next;
10063 }
10064 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
10065 oldstate);
10066 if (type->minOccurs == 0) {
10067 xmlAutomataNewEpsilon(ctxt->am, oldstate,
10068 ctxt->state);
10069 }
10070 }
10071 } else if ((type->maxOccurs > 1)
10072 || (type->minOccurs > 1)) {
10073 xmlAutomataStatePtr tmp;
10074 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000010075
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010076 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
10077 oldstate,
10078 NULL);
10079 oldstate = ctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +000010080
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010081 counter = xmlAutomataNewCounter(ctxt->am,
10082 type->minOccurs -
10083 1,
10084 type->maxOccurs -
10085 1);
Daniel Veillard4255d502002-04-16 15:50:10 +000010086
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010087 subtypes = type->subtypes;
10088 while (subtypes != NULL) {
10089 xmlSchemaBuildAContentModel(subtypes, ctxt,
10090 name);
10091 subtypes = subtypes->next;
10092 }
10093 tmp = ctxt->state;
10094 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
10095 counter);
10096 ctxt->state =
10097 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
10098 counter);
10099 if (type->minOccurs == 0) {
10100 xmlAutomataNewEpsilon(ctxt->am, oldstate,
10101 ctxt->state);
10102 }
Daniel Veillardb509f152002-04-17 16:28:10 +000010103
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010104 } else {
10105 subtypes = type->subtypes;
10106 while (subtypes != NULL) {
10107 xmlSchemaBuildAContentModel(subtypes, ctxt,
10108 name);
10109 subtypes = subtypes->next;
10110 }
10111 if (type->minOccurs == 0) {
10112 xmlAutomataNewEpsilon(ctxt->am, oldstate,
10113 ctxt->state);
10114 }
10115 }
10116 }
10117 break;
10118 }
10119 case XML_SCHEMA_TYPE_CHOICE:{
10120 xmlSchemaTypePtr subtypes;
10121 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +000010122
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010123 start = ctxt->state;
10124 end = xmlAutomataNewState(ctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +000010125
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010126 /*
10127 * iterate over the subtypes and remerge the end with an
10128 * epsilon transition
10129 */
10130 if (type->maxOccurs == 1) {
10131 subtypes = type->subtypes;
10132 while (subtypes != NULL) {
10133 ctxt->state = start;
10134 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
10135 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
10136 subtypes = subtypes->next;
10137 }
10138 } else {
10139 int counter;
10140 xmlAutomataStatePtr hop;
10141 int maxOccurs = type->maxOccurs == UNBOUNDED ?
10142 UNBOUNDED : type->maxOccurs - 1;
10143 int minOccurs =
10144 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +000010145
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010146 /*
10147 * use a counter to keep track of the number of transtions
10148 * which went through the choice.
10149 */
10150 counter =
10151 xmlAutomataNewCounter(ctxt->am, minOccurs,
10152 maxOccurs);
10153 hop = xmlAutomataNewState(ctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +000010154
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010155 subtypes = type->subtypes;
10156 while (subtypes != NULL) {
10157 ctxt->state = start;
10158 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
10159 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
10160 subtypes = subtypes->next;
10161 }
10162 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
10163 counter);
10164 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
10165 counter);
10166 }
10167 if (type->minOccurs == 0) {
10168 xmlAutomataNewEpsilon(ctxt->am, start, end);
10169 }
10170 ctxt->state = end;
10171 break;
10172 }
10173 case XML_SCHEMA_TYPE_ALL:{
10174 xmlAutomataStatePtr start;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000010175 xmlSchemaElementPtr elemDecl, particle;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010176 int lax;
10177
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000010178 particle = (xmlSchemaElementPtr) type->subtypes;
10179 if (particle == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010180 break;
10181 start = ctxt->state;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000010182 while (particle != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010183 ctxt->state = start;
William M. Brack9989c7d2004-05-12 14:39:38 +000010184 /*
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000010185 * Changed to put the element declaration and
10186 * never the element decl. reference into the
10187 * automaton. This fixes bug 139897 and bug 167754.
William M. Brack9989c7d2004-05-12 14:39:38 +000010188 */
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000010189 if (particle->ref != NULL) {
10190 if (particle->refDecl == NULL) {
10191 /*
10192 * TODO: Note that we break on missing
10193 * sub-components.
10194 */
10195 break;
10196 } else
10197 elemDecl = particle->refDecl;
10198 } else
10199 elemDecl = particle;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010200 /*
10201 * NOTE: The {max occurs} of all the particles in the
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000010202 * {particles} of the group must be 0 or 1; this is
10203 * already ensured during the parse of the content of
10204 * <all>.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010205 */
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000010206 if ((particle->minOccurs == 1) &&
10207 (particle->maxOccurs == 1)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010208 xmlAutomataNewOnceTrans2(ctxt->am, ctxt->state,
10209 ctxt->state,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000010210 elemDecl->name,
10211 elemDecl->targetNamespace,
10212 1, 1, elemDecl);
10213 } else if ((particle->minOccurs == 0) &&
10214 (particle->maxOccurs == 1)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010215
10216 xmlAutomataNewCountTrans2(ctxt->am, ctxt->state,
10217 ctxt->state,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000010218 elemDecl->name,
10219 elemDecl->targetNamespace,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010220 0,
10221 1,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000010222 elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010223 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000010224 particle = (xmlSchemaElementPtr) particle->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010225 }
10226 lax = type->minOccurs == 0;
10227 ctxt->state =
10228 xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL,
10229 lax);
10230 break;
10231 }
10232 case XML_SCHEMA_TYPE_RESTRICTION:
10233 if (type->subtypes != NULL)
10234 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
10235 break;
10236 case XML_SCHEMA_TYPE_EXTENSION:
10237 if (type->baseType != NULL) {
10238 xmlSchemaTypePtr subtypes;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010239
10240 /*
10241 * TODO: Circular definitions will be checked at the
10242 * constraint level. So remove this when the complex type
10243 * constraints are implemented.
10244 */
Daniel Veillardf7627552004-04-22 07:15:40 +000010245 if (type->recurse) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010246 /* TODO: Change the error code. */
10247 xmlSchemaPCustomErr(ctxt,
10248 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
10249 NULL, type, type->node,
10250 "This item is circular", NULL);
Daniel Veillardf7627552004-04-22 07:15:40 +000010251 return;
10252 }
10253 type->recurse = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010254 xmlSchemaBuildAContentModel(type->baseType, ctxt, name);
Daniel Veillardf7627552004-04-22 07:15:40 +000010255 type->recurse = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010256 subtypes = type->subtypes;
10257 while (subtypes != NULL) {
10258 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
10259 subtypes = subtypes->next;
10260 }
10261 } else if (type->subtypes != NULL)
10262 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
10263 break;
10264 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000010265 /*
10266 * Handle model group definition references.
10267 * NOTE: type->subtypes is the referenced model grop definition;
10268 * and type->subtypes->subtypes is the model group (i.e. <all> or
10269 * <choice> or <sequence>).
10270 */
10271 if ((type->ref != NULL) && (type->subtypes != NULL) &&
10272 (type->subtypes->subtypes != NULL)) {
10273 xmlSchemaTypePtr modelGr;
10274 xmlAutomataStatePtr start, end;
10275
10276 modelGr = type->subtypes->subtypes;
10277 start = ctxt->state;
10278 end = xmlAutomataNewState(ctxt->am);
10279 if (type->maxOccurs == 1) {
10280 ctxt->state = start;
10281 xmlSchemaBuildAContentModel(modelGr, ctxt, name);
10282 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
10283 } else {
10284 int counter;
10285 xmlAutomataStatePtr hop;
10286 int maxOccurs = type->maxOccurs == UNBOUNDED ?
10287 UNBOUNDED : type->maxOccurs - 1;
10288 int minOccurs =
10289 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
10290
10291 counter =
10292 xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
10293 hop = xmlAutomataNewState(ctxt->am);
10294 ctxt->state = start;
10295 xmlSchemaBuildAContentModel(modelGr, ctxt, name);
10296 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
10297 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
10298 counter);
10299 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
10300 counter);
10301 }
10302 if (type->minOccurs == 0) {
10303 xmlAutomataNewEpsilon(ctxt->am, start, end);
10304 }
10305 ctxt->state = end;
10306 break;
10307 }
10308 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010309 case XML_SCHEMA_TYPE_COMPLEX:
10310 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
10311 if (type->subtypes != NULL)
10312 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
10313 break;
William M. Brack2f2a6632004-08-20 23:09:47 +000010314 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
10315 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010316 default:
10317 xmlGenericError(xmlGenericErrorContext,
10318 "Found unexpected type %d in %s content model\n",
10319 type->type, name);
10320 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000010321 }
10322}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010323
Daniel Veillard4255d502002-04-16 15:50:10 +000010324/**
10325 * xmlSchemaBuildContentModel:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010326 * @type: the type definition (or reference)
Daniel Veillard4255d502002-04-16 15:50:10 +000010327 * @ctxt: the schema parser context
Daniel Veillarda84c0b32003-06-02 16:58:46 +000010328 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +000010329 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010330 * Builds the content model of the complex type.
Daniel Veillard4255d502002-04-16 15:50:10 +000010331 */
10332static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010333xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010334 xmlSchemaParserCtxtPtr ctxt,
10335 const xmlChar * name)
10336{
Daniel Veillard4255d502002-04-16 15:50:10 +000010337 xmlAutomataStatePtr start;
10338
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010339 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) || (type->ref != NULL) ||
10340 (type->contentType == XML_SCHEMA_CONTENT_BASIC) ||
10341 (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
10342 (type->contModel != NULL))
10343 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +000010344
10345#ifdef DEBUG_CONTENT
10346 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010347 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000010348#endif
10349
Daniel Veillard4255d502002-04-16 15:50:10 +000010350 ctxt->am = xmlNewAutomata();
10351 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010352 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010353 "Cannot create automata for complex tpye %s\n", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010354 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000010355 }
10356 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010357 xmlSchemaBuildAContentModel(type, ctxt, name);
Daniel Veillard4255d502002-04-16 15:50:10 +000010358 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010359 type->contModel = xmlAutomataCompile(ctxt->am);
10360 if (type->contModel == NULL) {
10361 xmlSchemaPCustomErr(ctxt,
10362 XML_SCHEMAP_INTERNAL,
10363 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010364 "Failed to compile the content model", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010365 } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010366 xmlSchemaPCustomErr(ctxt,
10367 XML_SCHEMAP_NOT_DETERMINISTIC,
10368 /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010369 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010370 "The content model is not determinist", NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +000010371 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +000010372#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010373 xmlGenericError(xmlGenericErrorContext,
10374 "Content model of %s:\n", name);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010375 xmlRegexpPrint(stderr, type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +000010376#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +000010377 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +000010378 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000010379 xmlFreeAutomata(ctxt->am);
10380 ctxt->am = NULL;
10381}
10382
10383/**
10384 * xmlSchemaRefFixupCallback:
10385 * @elem: the schema element context
10386 * @ctxt: the schema parser context
10387 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000010388 * Resolves the references of an element declaration
10389 * or particle, which has an element declaration as it's
10390 * term.
Daniel Veillard4255d502002-04-16 15:50:10 +000010391 */
10392static void
10393xmlSchemaRefFixupCallback(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010394 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010395 const xmlChar * name ATTRIBUTE_UNUSED,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010396 const xmlChar * context ATTRIBUTE_UNUSED,
10397 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000010398{
Daniel Veillardc0826a72004-08-10 14:17:33 +000010399 if ((ctxt == NULL) || (elem == NULL) ||
10400 ((elem != NULL) && (elem->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010401 return;
Daniel Veillardc0826a72004-08-10 14:17:33 +000010402 elem->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
Daniel Veillard4255d502002-04-16 15:50:10 +000010403 if (elem->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010404 xmlSchemaElementPtr elemDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +000010405
Daniel Veillardc0826a72004-08-10 14:17:33 +000010406 /*
10407 * TODO: Evaluate, what errors could occur if the declaration is not
10408 * found. It might be possible that the "typefixup" might crash if
10409 * no ref declaration was found.
10410 */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010411 elemDecl = xmlSchemaGetElem(ctxt->schema, elem->ref, elem->refNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +000010412 if (elemDecl == NULL) {
10413 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010414 XML_SCHEMAP_SRC_RESOLVE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010415 NULL, (xmlSchemaTypePtr) elem, elem->node,
10416 "ref", elem->ref, elem->refNs,
10417 XML_SCHEMA_TYPE_ELEMENT, NULL);
10418 } else
10419 elem->refDecl = elemDecl;
10420 } else {
10421 if ((elem->subtypes == NULL) && (elem->namedType != NULL)) {
10422 xmlSchemaTypePtr type;
10423
10424 /* (type definition) ... otherwise the type definition ·resolved·
10425 * to by the ·actual value· of the type [attribute] ...
10426 */
10427 type = xmlSchemaGetType(ctxt->schema, elem->namedType,
10428 elem->namedTypeNs);
10429 if (type == NULL) {
10430 xmlSchemaPResCompAttrErr(ctxt,
10431 XML_SCHEMAP_SRC_RESOLVE,
10432 NULL, (xmlSchemaTypePtr) elem, elem->node,
10433 "type", elem->namedType, elem->namedTypeNs,
10434 XML_SCHEMA_TYPE_BASIC, "type definition");
10435 } else
10436 elem->subtypes = type;
10437 }
10438 if (elem->substGroup != NULL) {
10439 xmlSchemaElementPtr substHead;
10440
10441 /*
10442 * FIXME TODO: Do we need a new field in _xmlSchemaElement for
10443 * substitutionGroup?
10444 */
10445 substHead = xmlSchemaGetElem(ctxt->schema, elem->substGroup,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010446 elem->substGroupNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +000010447 if (substHead == NULL) {
10448 xmlSchemaPResCompAttrErr(ctxt,
10449 XML_SCHEMAP_SRC_RESOLVE,
10450 NULL, (xmlSchemaTypePtr) elem, NULL,
10451 "substitutionGroup", elem->substGroup, elem->substGroupNs,
10452 XML_SCHEMA_TYPE_ELEMENT, NULL);
10453 } else {
10454 xmlSchemaRefFixupCallback(substHead, ctxt, NULL, NULL, NULL);
10455 /*
10456 * (type definition)...otherwise the {type definition} of the
10457 * element declaration ·resolved· to by the ·actual value· of
10458 * the substitutionGroup [attribute], if present
10459 */
10460 if (elem->subtypes == NULL)
10461 elem->subtypes = substHead->subtypes;
10462 }
10463 }
10464 if ((elem->subtypes == NULL) && (elem->namedType == NULL) &&
10465 (elem->substGroup == NULL))
10466 elem->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
10467 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010468}
10469
William M. Bracke7091952004-05-11 15:09:58 +000010470/**
10471 * xmlSchemaParseListRefFixup:
10472 * @type: the schema type definition
10473 * @ctxt: the schema parser context
10474 *
10475 * Fixup of the itemType reference of the list type.
10476 */
Daniel Veillard377e1a92004-04-16 16:30:05 +000010477static void
William M. Bracke7091952004-05-11 15:09:58 +000010478xmlSchemaParseListRefFixup(xmlSchemaTypePtr type, xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010479{
Daniel Veillardc0826a72004-08-10 14:17:33 +000010480
Daniel Veillard01fa6152004-06-29 17:04:39 +000010481 if (((type->base == NULL) &&
10482 (type->subtypes == NULL)) ||
10483 ((type->base != NULL) &&
10484 (type->subtypes != NULL))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010485 /*
10486 * src-list-itemType-or-simpleType
10487 * Either the itemType [attribute] or the <simpleType> [child] of
10488 * the <list> element must be present, but not both.
Daniel Veillard01fa6152004-06-29 17:04:39 +000010489 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000010490 /*
10491 * TODO: Move this to the parse function.
10492 */
10493 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010494 XML_SCHEMAP_SRC_LIST_ITEMTYPE_OR_SIMPLETYPE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010495 NULL, type, type->node,
10496 "The attribute 'itemType' and the <simpleType> child "
10497 "are mutually exclusive", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010498 } else if (type->base!= NULL) {
10499 type->subtypes = xmlSchemaGetType(ctxt->schema, type->base, type->baseNs);
10500 if (type->subtypes == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010501 xmlSchemaPResCompAttrErr(ctxt,
10502 XML_SCHEMAP_SRC_RESOLVE,
10503 NULL, type, type->node,
10504 "itemType", type->base, type->baseNs,
10505 XML_SCHEMA_TYPE_SIMPLE, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010506 }
10507 }
10508 if ((type->subtypes != NULL) &&
10509 (type->subtypes->contentType == XML_SCHEMA_CONTENT_UNKNOWN))
10510 xmlSchemaTypeFixup(type->subtypes, ctxt, NULL);
William M. Bracke7091952004-05-11 15:09:58 +000010511}
10512
10513/**
10514 * xmlSchemaParseUnionRefCheck:
10515 * @typeDecl: the schema type definition
10516 * @ctxt: the schema parser context
10517 *
Daniel Veillard01fa6152004-06-29 17:04:39 +000010518 * Checks and builds the memberTypes of the union type.
10519 * Returns -1 in case of an internal error, 0 otherwise.
William M. Bracke7091952004-05-11 15:09:58 +000010520 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010521static int
William M. Bracke7091952004-05-11 15:09:58 +000010522xmlSchemaParseUnionRefCheck(xmlSchemaTypePtr type,
Daniel Veillard377e1a92004-04-16 16:30:05 +000010523 xmlSchemaParserCtxtPtr ctxt)
10524{
Daniel Veillardc0826a72004-08-10 14:17:33 +000010525
Daniel Veillard01fa6152004-06-29 17:04:39 +000010526 xmlSchemaTypeLinkPtr link, lastLink = NULL, prevLink, subLink, newLink;
10527 xmlSchemaTypePtr memberType, ctxtType;
Daniel Veillard377e1a92004-04-16 16:30:05 +000010528
Daniel Veillard01fa6152004-06-29 17:04:39 +000010529 /* 1 If the <union> alternative is chosen, then [Definition:]
10530 * define the explicit members as the type definitions ·resolved·
10531 * to by the items in the ·actual value· of the memberTypes [attribute],
10532 * if any, followed by the type definitions corresponding to the
10533 * <simpleType>s among the [children] of <union>, if any.
10534 */
Daniel Veillard377e1a92004-04-16 16:30:05 +000010535
Daniel Veillard01fa6152004-06-29 17:04:39 +000010536 if (type->type != XML_SCHEMA_TYPE_UNION)
10537 return (-1);
10538 if (ctxt->ctxtType == NULL) {
10539 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010540 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010541 "Internal error: xmlSchemaParseUnionRefCheck, no parent type "
10542 "available", NULL, NULL);
10543 return (-1);
10544 }
10545 /*
10546 * src-union-memberTypes-or-simpleTypes
10547 * Either the memberTypes [attribute] of the <union> element must
10548 * be non-empty or there must be at least one simpleType [child].
10549 */
10550 if ((type->base == NULL) &&
10551 (type->subtypes == NULL)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010552 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010553 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010554 NULL, NULL, type->node,
10555 "Either the attribute 'memberTypes' must be non-empty "
10556 "or there must be at least one <simpleType> child", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010557 }
10558
10559 ctxtType = ctxt->ctxtType;
10560 if (type->base != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010561 xmlAttrPtr attr;
10562 const xmlChar *cur, *end;
10563 xmlChar *tmp;
10564 const xmlChar *localName, *uri;
10565
10566 attr = xmlSchemaGetPropNode(type->node, "memberTypes");
Daniel Veillard01fa6152004-06-29 17:04:39 +000010567 cur = type->base;
10568 do {
10569 while (IS_BLANK_CH(*cur))
10570 cur++;
10571 end = cur;
10572 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
10573 end++;
10574 if (end == cur)
10575 break;
10576 tmp = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +000010577 xmlSchemaPValAttrNodeQNameValue(ctxt, ctxt->schema, NULL,
10578 NULL, attr, BAD_CAST tmp, &uri, NULL, &localName);
10579 memberType = xmlSchemaGetType(ctxt->schema, localName, uri);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010580 if (memberType == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010581 xmlSchemaPResCompAttrErr(ctxt,
10582 XML_SCHEMAP_UNKNOWN_MEMBER_TYPE,
10583 NULL, NULL, type->node, "memberTypes", localName, uri,
10584 XML_SCHEMA_TYPE_SIMPLE, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010585 } else {
10586 if (memberType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
10587 xmlSchemaTypeFixup(memberType, ctxt, NULL);
10588 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
10589 if (link == NULL) {
10590 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
10591 return (-1);
10592 }
10593 link->type = memberType;
10594 link->next = NULL;
10595 if (lastLink == NULL)
10596 ctxtType->memberTypes = link;
10597 else
10598 lastLink->next = link;
10599 lastLink = link;
10600 }
10601 xmlFree(tmp);
10602 cur = end;
10603 } while (*cur != 0);
10604 }
10605 /*
10606 * Add local simple types,
10607 */
10608 memberType = type->subtypes;
10609 while (memberType != NULL) {
10610 if (memberType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
10611 xmlSchemaTypeFixup(memberType, ctxt, NULL);
10612 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
10613 if (link == NULL) {
10614 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
10615 return (-1);
10616 }
10617 link->type = memberType;
10618 link->next = NULL;
10619 if (lastLink == NULL)
10620 ctxtType->memberTypes = link;
10621 else
10622 lastLink->next = link;
10623 lastLink = link;
10624 memberType = memberType->next;
10625 }
10626 /*
10627 * The actual value is then formed by replacing any union type
10628 * definition in the ·explicit members· with the members of their
10629 * {member type definitions}, in order.
10630 */
10631 link = ctxtType->memberTypes;
10632 while (link != NULL) {
10633 if (link->type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
10634 subLink = link->type->memberTypes;
10635 if (subLink != NULL) {
10636 link->type = subLink->type;
10637 if (subLink->next != NULL) {
10638 lastLink = link->next;
10639 subLink = subLink->next;
10640 prevLink = link;
10641 while (subLink != NULL) {
10642 newLink = (xmlSchemaTypeLinkPtr)
10643 xmlMalloc(sizeof(xmlSchemaTypeLink));
10644 if (newLink == NULL) {
10645 xmlSchemaPErrMemory(ctxt, "allocating a type link",
10646 NULL);
10647 return (-1);
10648 }
10649 newLink->type = memberType;
10650 prevLink->next = newLink;
10651 prevLink = newLink;
10652 newLink->next = lastLink;
10653
10654 subLink = subLink->next;
10655 }
10656 }
10657 }
10658 }
10659 link = link->next;
10660 }
10661
10662 return (0);
Daniel Veillard377e1a92004-04-16 16:30:05 +000010663}
10664
Daniel Veillard4255d502002-04-16 15:50:10 +000010665/**
Daniel Veillard3646d642004-06-02 19:19:14 +000010666 * xmlSchemaIsDerivedFromBuiltInType:
10667 * @ctxt: the schema parser context
10668 * @type: the type definition
10669 * @valType: the value type
10670 *
10671 *
10672 * Returns 1 if the type has the given value type, or
10673 * is derived from such a type.
10674 */
William M. Brack803812b2004-06-03 02:11:24 +000010675static int
Daniel Veillard3646d642004-06-02 19:19:14 +000010676xmlSchemaIsDerivedFromBuiltInType(xmlSchemaParserCtxtPtr ctxt,
10677 xmlSchemaTypePtr type, int valType)
10678{
10679 /* TODO: Check if this works in every case. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010680 if ((type->type == XML_SCHEMA_TYPE_BASIC) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000010681 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000010682 if (type->builtInType == valType)
Daniel Veillard3646d642004-06-02 19:19:14 +000010683 return(1);
10684 } else if (type->type == XML_SCHEMA_TYPE_ATTRIBUTE) {
10685 if (((xmlSchemaAttributePtr) type)->subtypes != NULL)
10686 return(xmlSchemaIsDerivedFromBuiltInType(ctxt,
10687 ((xmlSchemaAttributePtr) type)->subtypes, valType));
10688 } else if ((type->type == XML_SCHEMA_TYPE_RESTRICTION) ||
10689 (type->type == XML_SCHEMA_TYPE_EXTENSION)) {
10690 if (type->baseType != NULL)
10691 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->baseType,
10692 valType));
10693 } else if ((type->subtypes != NULL) &&
10694 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX) ||
10695 (type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
10696 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE) ||
10697 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
10698 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->subtypes,
10699 valType));
10700 }
10701
10702 return (0);
10703}
10704
10705/**
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000010706 * xmlSchemaGetPrimitiveType:
Daniel Veillard01fa6152004-06-29 17:04:39 +000010707 * @type: the simpleType definition
10708 *
10709 * Returns the primitive type of the given type or
10710 * NULL in case of error.
10711 */
10712static xmlSchemaTypePtr
10713xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
10714{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000010715
Daniel Veillard01fa6152004-06-29 17:04:39 +000010716 while (type != NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000010717 /*
10718 * Note that anySimpleType is actually not a primitive type
10719 * but we need that here.
10720 */
10721 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
10722 (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
Daniel Veillard01fa6152004-06-29 17:04:39 +000010723 return (type);
10724 type = type->baseType;
10725 }
10726
10727 return (NULL);
10728}
10729
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000010730#if 0
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000010731/**
10732 * xmlSchemaGetBuiltInTypeAncestor:
10733 * @type: the simpleType definition
10734 *
10735 * Returns the primitive type of the given type or
10736 * NULL in case of error.
10737 */
10738static xmlSchemaTypePtr
10739xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
10740{
10741 while (type != NULL) {
10742 if (type->type == XML_SCHEMA_TYPE_BASIC)
10743 return (type);
10744 type = type->baseType;
10745 }
10746
10747 return (NULL);
10748}
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000010749#endif
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000010750
Daniel Veillard01fa6152004-06-29 17:04:39 +000010751
10752/**
Daniel Veillard3646d642004-06-02 19:19:14 +000010753 * xmlSchemaBuildAttributeUsesOwned:
10754 * @ctxt: the schema parser context
10755 * @type: the complex type definition
10756 * @cur: the attribute declaration list
10757 * @lastUse: the top of the attribute use list
10758 *
10759 * Builds the attribute uses list on the given complex type.
10760 * This one is supposed to be called by
10761 * xmlSchemaBuildAttributeValidation only.
10762 */
10763static int
10764xmlSchemaBuildAttributeUsesOwned(xmlSchemaParserCtxtPtr ctxt,
10765 xmlSchemaAttributePtr cur,
10766 xmlSchemaAttributeLinkPtr *uses,
10767 xmlSchemaAttributeLinkPtr *lastUse)
10768{
10769 xmlSchemaAttributeLinkPtr tmp;
10770 while (cur != NULL) {
10771 if (cur->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
10772 /*
10773 * W3C: "2 The {attribute uses} of the attribute groups ·resolved·
10774 * to by the ·actual value·s of the ref [attribute] of the
10775 * <attributeGroup> [children], if any."
10776 */
10777 if (xmlSchemaBuildAttributeUsesOwned(ctxt,
10778 ((xmlSchemaAttributeGroupPtr) cur)->attributes, uses,
10779 lastUse) == -1) {
10780 return (-1);
10781 }
10782 } else {
10783 /* W3C: "1 The set of attribute uses corresponding to the
10784 * <attribute> [children], if any."
10785 */
10786 tmp = (xmlSchemaAttributeLinkPtr)
10787 xmlMalloc(sizeof(xmlSchemaAttributeLink));
10788 if (tmp == NULL) {
10789 xmlSchemaPErrMemory(ctxt, "building attribute uses", NULL);
10790 return (-1);
10791 }
10792 tmp->attr = cur;
10793 tmp->next = NULL;
10794 if (*uses == NULL)
10795 *uses = tmp;
10796 else
10797 (*lastUse)->next = tmp;
10798 *lastUse = tmp;
10799 }
10800 cur = cur->next;
10801 }
10802 return (0);
10803}
10804
Daniel Veillard50355f02004-06-08 17:52:16 +000010805/**
10806 * xmlSchemaCloneWildcardNsConstraints:
10807 * @ctxt: the schema parser context
10808 * @dest: the destination wildcard
10809 * @source: the source wildcard
10810 *
10811 * Clones the namespace constraints of source
10812 * and assignes them to dest.
10813 * Returns -1 on internal error, 0 otherwise.
10814 */
Daniel Veillard3646d642004-06-02 19:19:14 +000010815static int
10816xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
10817 xmlSchemaWildcardPtr *dest,
10818 xmlSchemaWildcardPtr source)
10819{
10820 xmlSchemaWildcardNsPtr cur, tmp, last;
10821
10822 if ((source == NULL) || (*dest == NULL))
10823 return(-1);
10824 (*dest)->any = source->any;
10825 cur = source->nsSet;
10826 last = NULL;
10827 while (cur != NULL) {
10828 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
10829 if (tmp == NULL)
10830 return(-1);
10831 tmp->value = cur->value;
10832 if (last == NULL)
10833 (*dest)->nsSet = tmp;
10834 else
10835 last->next = tmp;
10836 last = tmp;
10837 cur = cur->next;
10838 }
10839 if ((*dest)->negNsSet != NULL)
10840 xmlSchemaFreeWildcardNsSet((*dest)->negNsSet);
10841 if (source->negNsSet != NULL) {
10842 (*dest)->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
10843 if ((*dest)->negNsSet == NULL)
10844 return(-1);
10845 (*dest)->negNsSet->value = source->negNsSet->value;
10846 } else
10847 (*dest)->negNsSet = NULL;
10848 return(0);
10849}
10850
Daniel Veillard50355f02004-06-08 17:52:16 +000010851/**
10852 * xmlSchemaUnionWildcards:
10853 * @ctxt: the schema parser context
10854 * @completeWild: the first wildcard
10855 * @curWild: the second wildcard
10856 *
10857 * Unions the namespace constraints of the given wildcards.
10858 * @completeWild will hold the resulting union.
10859 * Returns a positive error code on failure, -1 in case of an
10860 * internal error, 0 otherwise.
10861 */
Daniel Veillard3646d642004-06-02 19:19:14 +000010862static int
10863xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
10864 xmlSchemaWildcardPtr completeWild,
10865 xmlSchemaWildcardPtr curWild)
10866{
10867 xmlSchemaWildcardNsPtr cur, curB, tmp;
10868
10869 /*
10870 * 1 If O1 and O2 are the same value, then that value must be the
10871 * value.
10872 */
10873 if ((completeWild->any == curWild->any) &&
10874 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
10875 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
10876
10877 if ((completeWild->negNsSet == NULL) ||
10878 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
10879
10880 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000010881 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000010882
10883 /*
10884 * Check equality of sets.
10885 */
10886 cur = completeWild->nsSet;
10887 while (cur != NULL) {
10888 found = 0;
10889 curB = curWild->nsSet;
10890 while (curB != NULL) {
10891 if (cur->value == curB->value) {
10892 found = 1;
10893 break;
10894 }
10895 curB = curB->next;
10896 }
10897 if (!found)
10898 break;
10899 cur = cur->next;
10900 }
10901 if (found)
10902 return(0);
10903 } else
10904 return(0);
10905 }
10906 }
10907 /*
10908 * 2 If either O1 or O2 is any, then any must be the value
10909 */
Daniel Veillard50355f02004-06-08 17:52:16 +000010910 if (completeWild->any != curWild->any) {
Daniel Veillard3646d642004-06-02 19:19:14 +000010911 if (completeWild->any == 0) {
10912 completeWild->any = 1;
10913 if (completeWild->nsSet != NULL) {
10914 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
10915 completeWild->nsSet = NULL;
10916 }
10917 if (completeWild->negNsSet != NULL) {
10918 xmlFree(completeWild->negNsSet);
10919 completeWild->negNsSet = NULL;
10920 }
10921 }
Daniel Veillard50355f02004-06-08 17:52:16 +000010922 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000010923 }
10924 /*
10925 * 3 If both O1 and O2 are sets of (namespace names or ·absent·),
10926 * then the union of those sets must be the value.
10927 */
10928 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
10929 int found;
10930 xmlSchemaWildcardNsPtr start;
10931
10932 cur = curWild->nsSet;
10933 start = completeWild->nsSet;
10934 while (cur != NULL) {
10935 found = 0;
10936 curB = start;
10937 while (curB != NULL) {
10938 if (cur->value == curB->value) {
10939 found = 1;
10940 break;
10941 }
10942 curB = curB->next;
10943 }
10944 if (!found) {
10945 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
10946 if (tmp == NULL)
10947 return (-1);
10948 tmp->value = cur->value;
10949 tmp->next = completeWild->nsSet;
10950 completeWild->nsSet = tmp;
10951 }
10952 cur = cur->next;
10953 }
10954
10955 return(0);
10956 }
10957 /*
10958 * 4 If the two are negations of different values (namespace names
10959 * or ·absent·), then a pair of not and ·absent· must be the value.
10960 */
10961 if ((completeWild->negNsSet != NULL) &&
10962 (curWild->negNsSet != NULL) &&
10963 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
10964 completeWild->negNsSet->value = NULL;
Daniel Veillard50355f02004-06-08 17:52:16 +000010965
10966 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +000010967 }
10968 /*
10969 * 5.
10970 */
10971 if (((completeWild->negNsSet != NULL) &&
10972 (completeWild->negNsSet->value != NULL) &&
10973 (curWild->nsSet != NULL)) ||
10974 ((curWild->negNsSet != NULL) &&
10975 (curWild->negNsSet->value != NULL) &&
10976 (completeWild->nsSet != NULL))) {
10977
10978 int nsFound, absentFound = 0;
10979
10980 if (completeWild->nsSet != NULL) {
10981 cur = completeWild->nsSet;
10982 curB = curWild->negNsSet;
10983 } else {
10984 cur = curWild->nsSet;
10985 curB = completeWild->negNsSet;
10986 }
10987 nsFound = 0;
10988 while (cur != NULL) {
10989 if (cur->value == NULL)
10990 absentFound = 1;
10991 else if (cur->value == curB->value)
10992 nsFound = 1;
10993 if (nsFound && absentFound)
10994 break;
10995 cur = cur->next;
10996 }
10997
10998 if (nsFound && absentFound) {
10999 /*
11000 * 5.1 If the set S includes both the negated namespace
11001 * name and ·absent·, then any must be the value.
11002 */
11003 completeWild->any = 1;
11004 if (completeWild->nsSet != NULL) {
11005 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11006 completeWild->nsSet = NULL;
11007 }
11008 if (completeWild->negNsSet != NULL) {
11009 xmlFree(completeWild->negNsSet);
11010 completeWild->negNsSet = NULL;
11011 }
11012 } else if (nsFound && (!absentFound)) {
11013 /*
11014 * 5.2 If the set S includes the negated namespace name
11015 * but not ·absent·, then a pair of not and ·absent· must
11016 * be the value.
11017 */
11018 if (completeWild->nsSet != NULL) {
11019 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11020 completeWild->nsSet = NULL;
11021 }
11022 if (completeWild->negNsSet == NULL) {
11023 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
11024 if (completeWild->negNsSet == NULL)
11025 return (-1);
11026 }
11027 completeWild->negNsSet->value = NULL;
11028 } else if ((!nsFound) && absentFound) {
11029 /*
11030 * 5.3 If the set S includes ·absent· but not the negated
11031 * namespace name, then the union is not expressible.
11032 */
11033 xmlSchemaPErr(ctxt, completeWild->node,
11034 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011035 "The union of the wilcard is not expressible.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +000011036 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000011037 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +000011038 } else if ((!nsFound) && (!absentFound)) {
11039 /*
11040 * 5.4 If the set S does not include either the negated namespace
11041 * name or ·absent·, then whichever of O1 or O2 is a pair of not
11042 * and a namespace name must be the value.
11043 */
11044 if (completeWild->negNsSet == NULL) {
11045 if (completeWild->nsSet != NULL) {
11046 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11047 completeWild->nsSet = NULL;
11048 }
11049 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
11050 if (completeWild->negNsSet == NULL)
11051 return (-1);
11052 completeWild->negNsSet->value = curWild->negNsSet->value;
11053 }
11054 }
11055 return (0);
11056 }
11057 /*
11058 * 6.
11059 */
11060 if (((completeWild->negNsSet != NULL) &&
11061 (completeWild->negNsSet->value == NULL) &&
11062 (curWild->nsSet != NULL)) ||
11063 ((curWild->negNsSet != NULL) &&
11064 (curWild->negNsSet->value == NULL) &&
11065 (completeWild->nsSet != NULL))) {
11066
11067 if (completeWild->nsSet != NULL) {
11068 cur = completeWild->nsSet;
11069 } else {
11070 cur = curWild->nsSet;
11071 }
11072 while (cur != NULL) {
11073 if (cur->value == NULL) {
11074 /*
11075 * 6.1 If the set S includes ·absent·, then any must be the
11076 * value.
11077 */
11078 completeWild->any = 1;
11079 if (completeWild->nsSet != NULL) {
11080 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11081 completeWild->nsSet = NULL;
11082 }
11083 if (completeWild->negNsSet != NULL) {
11084 xmlFree(completeWild->negNsSet);
11085 completeWild->negNsSet = NULL;
11086 }
11087 return (0);
11088 }
11089 cur = cur->next;
11090 }
11091 if (completeWild->negNsSet == NULL) {
11092 /*
11093 * 6.2 If the set S does not include ·absent·, then a pair of not
11094 * and ·absent· must be the value.
11095 */
11096 if (completeWild->nsSet != NULL) {
11097 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11098 completeWild->nsSet = NULL;
11099 }
11100 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
11101 if (completeWild->negNsSet == NULL)
11102 return (-1);
11103 completeWild->negNsSet->value = NULL;
11104 }
11105 return (0);
11106 }
11107 return (0);
11108
11109}
11110
Daniel Veillard50355f02004-06-08 17:52:16 +000011111/**
11112 * xmlSchemaIntersectWildcards:
11113 * @ctxt: the schema parser context
11114 * @completeWild: the first wildcard
11115 * @curWild: the second wildcard
11116 *
11117 * Intersects the namespace constraints of the given wildcards.
11118 * @completeWild will hold the resulting intersection.
11119 * Returns a positive error code on failure, -1 in case of an
11120 * internal error, 0 otherwise.
11121 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011122static int
11123xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
11124 xmlSchemaWildcardPtr completeWild,
11125 xmlSchemaWildcardPtr curWild)
11126{
William M. Brack803812b2004-06-03 02:11:24 +000011127 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000011128
11129 /*
11130 * 1 If O1 and O2 are the same value, then that value must be the
11131 * value.
11132 */
11133 if ((completeWild->any == curWild->any) &&
11134 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
11135 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
11136
11137 if ((completeWild->negNsSet == NULL) ||
11138 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
11139
11140 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000011141 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000011142
11143 /*
11144 * Check equality of sets.
11145 */
11146 cur = completeWild->nsSet;
11147 while (cur != NULL) {
11148 found = 0;
11149 curB = curWild->nsSet;
11150 while (curB != NULL) {
11151 if (cur->value == curB->value) {
11152 found = 1;
11153 break;
11154 }
11155 curB = curB->next;
11156 }
11157 if (!found)
11158 break;
11159 cur = cur->next;
11160 }
11161 if (found)
11162 return(0);
11163 } else
11164 return(0);
11165 }
11166 }
11167 /*
11168 * 2 If either O1 or O2 is any, then the other must be the value.
11169 */
11170 if ((completeWild->any != curWild->any) && (completeWild->any)) {
11171 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
11172 return(-1);
11173 return(0);
11174 }
11175 /*
11176 * 3 If either O1 or O2 is a pair of not and a value (a namespace
11177 * name or ·absent·) and the other is a set of (namespace names or
11178 * ·absent·), then that set, minus the negated value if it was in
11179 * the set, minus ·absent· if it was in the set, must be the value.
11180 */
11181 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
11182 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
11183 const xmlChar *neg;
11184
11185 if (completeWild->nsSet == NULL) {
11186 neg = completeWild->negNsSet->value;
11187 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
11188 return(-1);
11189 } else
11190 neg = curWild->negNsSet->value;
11191 /*
11192 * Remove absent and negated.
11193 */
11194 prev = NULL;
11195 cur = completeWild->nsSet;
11196 while (cur != NULL) {
11197 if (cur->value == NULL) {
11198 if (prev == NULL)
11199 completeWild->nsSet = cur->next;
11200 else
11201 prev->next = cur->next;
11202 xmlFree(cur);
11203 break;
11204 }
11205 prev = cur;
11206 cur = cur->next;
11207 }
11208 if (neg != NULL) {
11209 prev = NULL;
11210 cur = completeWild->nsSet;
11211 while (cur != NULL) {
11212 if (cur->value == neg) {
11213 if (prev == NULL)
11214 completeWild->nsSet = cur->next;
11215 else
11216 prev->next = cur->next;
11217 xmlFree(cur);
11218 break;
11219 }
11220 prev = cur;
11221 cur = cur->next;
11222 }
11223 }
11224
11225 return(0);
11226 }
11227 /*
11228 * 4 If both O1 and O2 are sets of (namespace names or ·absent·),
11229 * then the intersection of those sets must be the value.
11230 */
11231 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
11232 int found;
11233
11234 cur = completeWild->nsSet;
11235 prev = NULL;
11236 while (cur != NULL) {
11237 found = 0;
11238 curB = curWild->nsSet;
11239 while (curB != NULL) {
11240 if (cur->value == curB->value) {
11241 found = 1;
11242 break;
11243 }
11244 curB = curB->next;
11245 }
11246 if (!found) {
11247 if (prev == NULL)
11248 completeWild->nsSet = cur->next;
11249 else
11250 prev->next = cur->next;
11251 tmp = cur->next;
11252 xmlFree(cur);
11253 cur = tmp;
11254 continue;
11255 }
11256 prev = cur;
11257 cur = cur->next;
11258 }
11259
11260 return(0);
11261 }
11262 /* 5 If the two are negations of different namespace names,
11263 * then the intersection is not expressible
11264 */
11265 if ((completeWild->negNsSet != NULL) &&
11266 (curWild->negNsSet != NULL) &&
11267 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
11268 (completeWild->negNsSet->value != NULL) &&
11269 (curWild->negNsSet->value != NULL)) {
11270
11271 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011272 "The intersection of the wilcard is not expressible.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +000011273 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000011274 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +000011275 }
11276 /*
11277 * 6 If the one is a negation of a namespace name and the other
11278 * is a negation of ·absent·, then the one which is the negation
11279 * of a namespace name must be the value.
11280 */
11281 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
11282 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
11283 (completeWild->negNsSet->value == NULL)) {
11284 completeWild->negNsSet->value = curWild->negNsSet->value;
11285 }
11286 return(0);
11287}
11288
Daniel Veillard50355f02004-06-08 17:52:16 +000011289/**
11290 * xmlSchemaIsWildcardNsConstraintSubset:
11291 * @ctxt: the schema parser context
11292 * @wildA: the first wildcard
11293 * @wildB: the second wildcard
11294 *
11295 * Returns 1 if the namespace constraint of @wildA is an intensional
11296 * subset of @wildB, 0 otherwise.
11297 */
11298static int
Daniel Veillardc0826a72004-08-10 14:17:33 +000011299xmlSchemaIsWildcardNsConstraintSubset(xmlSchemaWildcardPtr wildA,
11300 xmlSchemaWildcardPtr wildB)
Daniel Veillard50355f02004-06-08 17:52:16 +000011301{
Daniel Veillard3646d642004-06-02 19:19:14 +000011302
Daniel Veillard50355f02004-06-08 17:52:16 +000011303 /*
11304 * Schema Component Constraint: Wildcard Subset
11305 */
11306 /*
11307 * 1 super must be any.
11308 */
11309 if (wildB->any)
11310 return (1);
11311 /*
11312 * 2.1 sub must be a pair of not and a namespace name or ·absent·.
11313 * 2.2 super must be a pair of not and the same value.
11314 */
11315 if ((wildA->negNsSet != NULL) &&
11316 (wildB->negNsSet != NULL) &&
11317 (wildA->negNsSet->value == wildA->negNsSet->value))
11318 return (1);
11319 /*
11320 * 3.1 sub must be a set whose members are either namespace names or ·absent·.
11321 */
11322 if (wildA->nsSet != NULL) {
11323 /*
11324 * 3.2.1 super must be the same set or a superset thereof.
11325 */
11326 if (wildB->nsSet != NULL) {
11327 xmlSchemaWildcardNsPtr cur, curB;
11328 int found = 0;
11329
11330 cur = wildA->nsSet;
11331 while (cur != NULL) {
11332 found = 0;
11333 curB = wildB->nsSet;
11334 while (curB != NULL) {
11335 if (cur->value == curB->value) {
11336 found = 1;
11337 break;
11338 }
11339 curB = curB->next;
11340 }
11341 if (!found)
11342 return (0);
11343 cur = cur->next;
11344 }
11345 if (found)
11346 return (1);
11347 } else if (wildB->negNsSet != NULL) {
11348 xmlSchemaWildcardNsPtr cur;
11349 /*
11350 * 3.2.2 super must be a pair of not and a namespace name or
11351 * ·absent· and that value must not be in sub's set.
11352 */
11353 cur = wildA->nsSet;
11354 while (cur != NULL) {
11355 if (cur->value == wildB->negNsSet->value)
11356 return (0);
11357 cur = cur->next;
11358 }
11359 return (1);
11360 }
11361 }
11362 return (0);
11363}
11364
11365/**
11366 * xmlSchemaBuildCompleteAttributeWildcard:
11367 * @ctxt: the schema parser context
11368 * @attrs: the attribute list
11369 * @completeWild: the resulting complete wildcard
11370 *
11371 * Returns -1 in case of an internal error, 0 otherwise.
11372 */
11373static int
11374xmlSchemaBuildCompleteAttributeWildcard(xmlSchemaParserCtxtPtr ctxt,
11375 xmlSchemaAttributePtr attrs,
11376 xmlSchemaWildcardPtr *completeWild)
Daniel Veillard3646d642004-06-02 19:19:14 +000011377{
11378 while (attrs != NULL) {
11379 if (attrs->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
11380 xmlSchemaAttributeGroupPtr group;
11381
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011382 group = (xmlSchemaAttributeGroupPtr) attrs;
11383 /*
11384 * Handle attribute group references.
11385 */
11386 if (group->ref != NULL) {
11387 if (group->refItem == NULL) {
11388 /*
11389 * TODO: Should we raise a warning here?
11390 */
11391 /*
11392 * The referenced attribute group definition could not
11393 * be resolved beforehand, so skip.
11394 */
11395 attrs = attrs->next;
11396 continue;
11397 } else
11398 group = group->refItem;
11399 }
11400 /*
11401 * For every attribute group definition, an intersected wildcard
11402 * will be created (assumed that a wildcard exists on the
11403 * particular attr. gr. def. or on any contained attr. gr. def
11404 * at all).
11405 * The flag XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED ensures
11406 * that the intersection will be performed only once.
11407 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011408 if ((group->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
11409 if (group->attributes != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000011410 if (xmlSchemaBuildCompleteAttributeWildcard(ctxt,
11411 group->attributes, &group->attributeWildcard) == -1)
11412 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000011413 }
11414 group->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
11415 }
11416 if (group->attributeWildcard != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000011417 if (*completeWild == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011418 /*
11419 * Copy the first encountered wildcard as context, except for the annotation.
11420 */
Daniel Veillard50355f02004-06-08 17:52:16 +000011421 *completeWild = xmlSchemaAddWildcard(ctxt);
11422 (*completeWild)->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
11423 if (xmlSchemaCloneWildcardNsConstraints(ctxt,
11424 completeWild, group->attributeWildcard) == -1)
11425 return (-1);
11426 (*completeWild)->processContents = group->attributeWildcard->processContents;
Daniel Veillard3646d642004-06-02 19:19:14 +000011427 /*
11428 * Although the complete wildcard might not correspond to any
11429 * node in the schema, we will save this context node.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011430 * TODO: Hmm, is this sane?
Daniel Veillard3646d642004-06-02 19:19:14 +000011431 */
Daniel Veillard50355f02004-06-08 17:52:16 +000011432 (*completeWild)->node = group->attributeWildcard->node;
11433
11434 } else if (xmlSchemaIntersectWildcards(ctxt, *completeWild, group->attributeWildcard) == -1) {
11435 xmlSchemaFreeWildcard(*completeWild);
11436 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000011437 }
11438 }
11439 }
11440 attrs = attrs->next;
11441 }
11442
Daniel Veillard50355f02004-06-08 17:52:16 +000011443 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000011444}
11445
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011446static int
11447xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributePtr item,
11448 int *fixed,
11449 const xmlChar **value,
11450 xmlSchemaValPtr *val)
11451{
11452 *fixed = 0;
11453 *value = NULL;
11454 if (val != 0)
11455 *val = NULL;
11456
11457 if (item->defValue == NULL)
11458 item = item->refDecl;
11459
11460 if (item == NULL)
11461 return (0);
11462
11463 if (item->defValue != NULL) {
11464 *value = item->defValue;
11465 if (val != 0)
11466 *val = item->defVal;
11467 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
11468 *fixed = 1;
11469 return (1);
11470 }
11471 return (0);
11472}
Daniel Veillard3646d642004-06-02 19:19:14 +000011473/**
11474 * xmlSchemaMatchesWildcardNs:
11475 * @wild: the wildcard
11476 * @ns: the namespace
11477 *
11478 *
11479 * Returns 1 if the given namespace matches the wildcard,
11480 * 0 otherwise.
11481 */
11482static int
11483xmlSchemaMatchesWildcardNs(xmlSchemaWildcardPtr wild, const xmlChar* ns)
11484{
11485 if (wild == NULL)
11486 return(0);
11487
11488 if (wild->any)
11489 return(1);
11490 else if (wild->nsSet != NULL) {
11491 xmlSchemaWildcardNsPtr cur;
11492
11493 cur = wild->nsSet;
11494 while (cur != NULL) {
11495 if (xmlStrEqual(cur->value, ns))
11496 return(1);
11497 cur = cur->next;
11498 }
11499 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
11500 (!xmlStrEqual(wild->negNsSet->value, ns)))
11501 return(1);
11502
11503 return(0);
11504}
11505
11506/**
11507 * xmlSchemaBuildAttributeValidation:
11508 * @ctxt: the schema parser context
11509 * @type: the complex type definition
11510 *
11511 *
11512 * Builds the wildcard and the attribute uses on the given complex type.
11513 * Returns -1 if an internal error occurs, 0 otherwise.
11514 */
11515static int
11516xmlSchemaBuildAttributeValidation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaTypePtr type)
11517{
11518 xmlSchemaTypePtr baseType = NULL;
11519 xmlSchemaAttributeLinkPtr cur, base, tmp, id = NULL, prev = NULL, uses = NULL,
William M. Brack803812b2004-06-03 02:11:24 +000011520 lastUse = NULL, lastBaseUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000011521 xmlSchemaAttributePtr attrs;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011522 xmlSchemaTypePtr anyType;
Daniel Veillard50355f02004-06-08 17:52:16 +000011523 int baseIsAnyType = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011524 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000011525 int err = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000011526
Daniel Veillard01fa6152004-06-29 17:04:39 +000011527 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Daniel Veillard3646d642004-06-02 19:19:14 +000011528 /*
11529 * Complex Type Definition with complex content Schema Component.
11530 *
11531 * Attribute uses.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011532 * TODO: Add checks for absent referenced attribute declarations and
11533 * simple types.
Daniel Veillard3646d642004-06-02 19:19:14 +000011534 */
11535 if (type->attributeUses != NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011536 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011537 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillard3646d642004-06-02 19:19:14 +000011538 "attribute uses already builded.\n",
11539 NULL, NULL);
11540 return (-1);
11541 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011542 if (type->baseType == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011543 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011544 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011545 "complex type '%s' has no base type.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011546 type->name, NULL);
11547 return (-1);
11548 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011549 baseType = type->baseType;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011550 if (baseType == anyType)
11551 baseIsAnyType = 1;
11552 /*
11553 * Inherit the attribute uses of the base type.
11554 */
11555 /*
11556 * NOTE: It is allowed to "extend" the anyType complex type.
11557 */
11558 if (!baseIsAnyType) {
11559 if (baseType != NULL) {
11560 for (cur = baseType->attributeUses; cur != NULL; cur = cur->next) {
11561 tmp = (xmlSchemaAttributeLinkPtr)
11562 xmlMalloc(sizeof(xmlSchemaAttributeLink));
11563 if (tmp == NULL) {
11564 xmlSchemaPErrMemory(ctxt,
11565 "building attribute uses of complexType", NULL);
11566 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000011567 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011568 tmp->attr = cur->attr;
11569 tmp->next = NULL;
11570 if (type->attributeUses == NULL) {
11571 type->attributeUses = tmp;
11572 } else
11573 lastBaseUse->next = tmp;
11574 lastBaseUse = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000011575 }
11576 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011577 }
11578 if ((type->subtypes != NULL) &&
11579 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
11580 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011581 /*
11582 * type --> (<simpleContent>|<complexContent>)
11583 * --> (<restriction>|<extension>) --> attributes
11584 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011585 attrs = type->subtypes->subtypes->attributes;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011586 } else {
11587 /* Short hand form of the complexType. */
11588 attrs = type->attributes;
11589 }
11590 /*
11591 * Handle attribute wildcards.
11592 */
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000011593 err = xmlSchemaBuildCompleteAttributeWildcard(ctxt,
11594 attrs, &type->attributeWildcard);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011595 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011596 * NOTE: During the parse time, the wildcard is created on the complexType
11597 * directly, if encountered in a <restriction> or <extension> element.
Daniel Veillard01fa6152004-06-29 17:04:39 +000011598 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011599 if (err == -1) {
11600 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
11601 "Internal error: xmlSchemaBuildAttributeValidation: "
11602 "failed to build an intersected attribute wildcard.\n",
11603 NULL, NULL);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000011604 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011605 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011606
11607 if ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
11608 ((baseIsAnyType) ||
11609 ((baseType != NULL) &&
11610 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
11611 (baseType->attributeWildcard != NULL)))) {
11612 if (type->attributeWildcard != NULL) {
11613 /*
11614 * Union the complete wildcard with the base wildcard.
11615 */
11616 if (xmlSchemaUnionWildcards(ctxt, type->attributeWildcard,
11617 baseType->attributeWildcard) == -1)
11618 return (-1);
11619 } else {
11620 /*
11621 * Just inherit the wildcard.
11622 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011623 /*
11624 * NOTE: This is the only case where an attribute
11625 * wildcard is shared.
11626 */
11627 if (type->flags & XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD)
11628 type->flags ^= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011629 type->attributeWildcard = baseType->attributeWildcard;
Daniel Veillard50355f02004-06-08 17:52:16 +000011630 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011631 }
11632
11633 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
11634 if (type->attributeWildcard != NULL) {
11635 /*
11636 * Derivation Valid (Restriction, Complex)
11637 * 4.1 The {base type definition} must also have one.
11638 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011639 if (baseType->attributeWildcard == NULL) {
11640 xmlSchemaPCustomErr(ctxt,
11641 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
11642 NULL, type, NULL,
11643 "The type has an attribute wildcard, "
11644 "but the base type %s does not have one",
11645 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11646 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011647 return (1);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011648 } else if (xmlSchemaIsWildcardNsConstraintSubset(
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011649 type->attributeWildcard, baseType->attributeWildcard) == 0) {
11650 /* 4.2 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011651 xmlSchemaPCustomErr(ctxt,
11652 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
11653 NULL, type, NULL,
11654 "The attribute wildcard is not a valid "
11655 "subset of the wildcard in the base type %s",
11656 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11657 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011658 return (1);
11659 }
11660 /* 4.3 Unless the {base type definition} is the ·ur-type
11661 * definition·, the complex type definition's {attribute
11662 * wildcard}'s {process contents} must be identical to or
11663 * stronger than the {base type definition}'s {attribute
11664 * wildcard}'s {process contents}, where strict is stronger
11665 * than lax is stronger than skip.
11666 */
11667 if ((type->baseType != anyType) &&
11668 (type->attributeWildcard->processContents <
11669 baseType->attributeWildcard->processContents)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011670 xmlSchemaPCustomErr(ctxt,
11671 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
11672 NULL, type, NULL,
11673 "The 'process contents' of the attribute wildcard is weaker than "
11674 "the one in the base type %s",
11675 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11676 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011677 return (1);
11678 }
11679 }
11680 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
11681 /*
11682 * Derivation Valid (Extension)
11683 * At this point the type and the base have both, either
11684 * no wildcard or a wildcard.
11685 */
11686 if ((baseType->attributeWildcard != NULL) &&
11687 (baseType->attributeWildcard != type->attributeWildcard)) {
11688 /* 1.3 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011689 if (xmlSchemaIsWildcardNsConstraintSubset(
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011690 baseType->attributeWildcard, type->attributeWildcard) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011691 xmlSchemaPCustomErr(ctxt,
11692 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
11693 NULL, type, NULL,
11694 "The attribute wildcard is not a valid "
11695 "superset of the one in the base type %s",
11696 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11697 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011698 return (1);
11699 }
11700 }
11701 }
11702
Daniel Veillard3646d642004-06-02 19:19:14 +000011703 /*
11704 * Gather attribute uses defined by this type.
11705 */
11706 if (attrs != NULL) {
11707 if (xmlSchemaBuildAttributeUsesOwned(ctxt, attrs,
11708 &uses, &lastUse) == -1) {
11709 return (-1);
11710 }
11711 }
11712 /* 3.4.6 -> Complex Type Definition Properties Correct 4.
11713 * "Two distinct attribute declarations in the {attribute uses} must
11714 * not have identical {name}s and {target namespace}s."
11715 *
11716 * For "extension" this is done further down.
11717 */
11718 if ((uses != NULL) && ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
11719 cur = uses;
11720 while (cur != NULL) {
11721 tmp = cur->next;
11722 while (tmp != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011723 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
11724 xmlSchemaGetAttrName(tmp->attr))) &&
11725 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
11726 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
11727
11728 xmlSchemaPAttrUseErr(ctxt,
11729 XML_SCHEMAP_CT_PROPS_CORRECT_4,
11730 NULL, type, NULL, cur->attr,
11731 "Duplicate attribute use %s specified",
11732 xmlSchemaFormatNsUriLocal(&str,
11733 xmlSchemaGetAttrTargetNsURI(tmp->attr),
11734 xmlSchemaGetAttrName(tmp->attr))
11735 );
11736 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000011737 break;
11738 }
11739 tmp = tmp->next;
11740 }
11741 cur = cur->next;
11742 }
11743 }
11744 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
11745 /*
11746 * Derive by restriction.
11747 */
11748 if (baseIsAnyType) {
11749 type->attributeUses = uses;
11750 } else {
11751 int found;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011752 const xmlChar *bEffValue;
11753 int effFixed;
Daniel Veillard3646d642004-06-02 19:19:14 +000011754
11755 cur = uses;
11756 while (cur != NULL) {
11757 found = 0;
11758 base = type->attributeUses;
11759 while (base != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011760 if (xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
11761 xmlSchemaGetAttrName(base->attr)) &&
11762 xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
11763 xmlSchemaGetAttrTargetNsURI(base->attr))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011764
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011765 found = 1;
11766
Daniel Veillard3646d642004-06-02 19:19:14 +000011767 if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
11768 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
11769 /*
11770 * derivation-ok-restriction 2.1.1
Daniel Veillardc0826a72004-08-10 14:17:33 +000011771 */
11772 xmlSchemaPAttrUseErr(ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000011773 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011774 NULL, type, NULL, cur->attr,
11775 "The 'optional' use is inconsistent with a matching "
11776 "'required' use of the base type", NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000011777 } else if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
11778 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
11779 /*
11780 * derivation-ok-restriction 3
11781 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011782 xmlSchemaPCustomErr(ctxt,
11783 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
11784 NULL, type, NULL,
11785 "A matching attribute use for the 'required' "
11786 "attribute use %s of the base type is missing",
11787 xmlSchemaFormatNsUriLocal(&str,
11788 xmlSchemaGetAttrTargetNsURI(base->attr),
11789 xmlSchemaGetAttrName(base->attr)));
11790 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000011791 } else {
11792 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011793 * 2.1.3 [Definition:] Let the effective value
11794 * constraint of an attribute use be its {value
11795 * constraint}, if present, otherwise its {attribute
11796 * declaration}'s {value constraint} .
11797 */
11798 xmlSchemaGetEffectiveValueConstraint(base->attr, &effFixed,
11799 &bEffValue, 0);
11800 /*
11801 * 2.1.3 ... one of the following must be true
11802 *
11803 * 2.1.3.1 B's ·effective value constraint· is
11804 * ·absent· or default.
11805 */
11806 if ((bEffValue != NULL) &&
11807 (effFixed == 1)) {
11808 const xmlChar *rEffValue = NULL;
11809
11810 xmlSchemaGetEffectiveValueConstraint(base->attr, &effFixed,
11811 &rEffValue, 0);
11812 /*
11813 * 2.1.3.2 R's ·effective value constraint· is
11814 * fixed with the same string as B's.
11815 */
11816 if ((effFixed == 0) ||
11817 (! xmlStrEqual(rEffValue, bEffValue))) {
11818 xmlSchemaPAttrUseErr(ctxt,
11819 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
11820 NULL, type, NULL, cur->attr,
11821 "The effective value constraint of the "
11822 "attribute use is inconsistent with "
11823 "its correspondent of the base type",
11824 NULL);
11825 }
11826 }
11827 /*
11828 * TODO: derivation-ok-restriction 2.1.2 ({type definition} must be validly derived)
11829 */
11830 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000011831 * Override the attribute use.
11832 */
11833 base->attr = cur->attr;
11834 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011835
Daniel Veillard3646d642004-06-02 19:19:14 +000011836 break;
11837 }
11838 base = base->next;
11839 }
11840
11841 if (!found) {
11842 if (cur->attr->occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
11843 /*
11844 * derivation-ok-restriction 2.2
11845 */
11846 if ((type->attributeWildcard != NULL) &&
11847 xmlSchemaMatchesWildcardNs(type->attributeWildcard,
11848 cur->attr->targetNamespace))
11849 found = 1;
11850
11851 if (!found) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011852 xmlSchemaPAttrUseErr(ctxt,
11853 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
11854 NULL, type, NULL, cur->attr,
11855 "Neither a matching attribute use, "
11856 "nor a matching wildcard in the base type does exist",
11857 NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000011858 } else {
11859 /*
11860 * Add the attribute use.
11861 *
11862 * Note that this may lead to funny derivation error reports, if
11863 * multiple equal attribute uses exist; but this is not
11864 * allowed anyway, and it will be reported beforehand.
11865 */
11866 tmp = cur;
11867 if (prev != NULL)
11868 prev->next = cur->next;
11869 else
11870 uses = cur->next;
11871 cur = cur->next;
11872 if (type->attributeUses == NULL) {
11873 type->attributeUses = tmp;
11874 } else
11875 lastBaseUse->next = tmp;
11876 lastBaseUse = tmp;
11877
11878 continue;
11879 }
11880 }
11881 }
11882 prev = cur;
11883 cur = cur->next;
11884 }
11885 if (uses != NULL)
11886 xmlSchemaFreeAttributeUseList(uses);
11887 }
11888 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
11889 /*
11890 * The spec allows only appending, and not other kinds of extensions.
11891 *
11892 * This ensures: Schema Component Constraint: Derivation Valid (Extension) : 1.2
11893 */
11894 if (uses != NULL) {
11895 if (type->attributeUses == NULL) {
11896 type->attributeUses = uses;
11897 } else
11898 lastBaseUse->next = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000011899 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011900 } else {
11901 /*
Daniel Veillard50355f02004-06-08 17:52:16 +000011902 * Derive implicitely from the ur-type.
11903 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011904 type->attributeUses = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000011905 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011906 /*
11907 * 3.4.6 -> Complex Type Definition Properties Correct
11908 */
11909 if (type->attributeUses != NULL) {
11910 cur = type->attributeUses;
11911 prev = NULL;
11912 while (cur != NULL) {
11913 /*
11914 * 4. Two distinct attribute declarations in the {attribute uses} must
11915 * not have identical {name}s and {target namespace}s.
Daniel Veillard50355f02004-06-08 17:52:16 +000011916 *
Daniel Veillard3646d642004-06-02 19:19:14 +000011917 * Note that this was already done for "restriction" and types derived from
11918 * the ur-type.
Daniel Veillard50355f02004-06-08 17:52:16 +000011919 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011920 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
11921 tmp = cur->next;
11922 while (tmp != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011923 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
11924 xmlSchemaGetAttrName(tmp->attr))) &&
11925 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
11926 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011927
Daniel Veillardc0826a72004-08-10 14:17:33 +000011928 xmlSchemaPAttrUseErr(ctxt,
11929 XML_SCHEMAP_CT_PROPS_CORRECT_4,
11930 NULL, type, NULL, tmp->attr,
11931 "Duplicate attribute use specified", NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000011932 break;
11933 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011934 tmp = tmp->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000011935 }
11936 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011937 /*
11938 * 5. Two distinct attribute declarations in the {attribute uses} must
11939 * not have {type definition}s which are or are derived from ID.
11940 */
11941 if ((cur->attr->subtypes != NULL) &&
Daniel Veillard01fa6152004-06-29 17:04:39 +000011942 (xmlSchemaIsDerivedFromBuiltInType(ctxt, (xmlSchemaTypePtr) cur->attr, XML_SCHEMAS_ID))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011943 if (id != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011944 xmlSchemaPAttrUseErr(ctxt,
11945 XML_SCHEMAP_CT_PROPS_CORRECT_5,
11946 NULL, type, NULL, cur->attr,
11947 "There must not exist more than one attribute use, "
11948 "declared of type 'ID' or derived from it",
11949 NULL);
11950 FREE_AND_NULL(str)
Daniel Veillard50355f02004-06-08 17:52:16 +000011951 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011952 id = cur;
11953 }
11954 /*
11955 * Remove "prohibited" attribute uses. The reason this is done at this late
11956 * stage is to be able to catch dublicate attribute uses. So we had to keep
11957 * prohibited uses in the list as well.
11958 */
11959 if (cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
11960 tmp = cur;
11961 if (prev == NULL)
11962 type->attributeUses = cur->next;
11963 else
11964 prev->next = cur->next;
11965 cur = cur->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000011966 xmlFree(tmp);
Daniel Veillard3646d642004-06-02 19:19:14 +000011967 } else {
11968 prev = cur;
11969 cur = cur->next;
11970 }
11971 }
11972 }
11973 /*
11974 * TODO: This check should be removed if we are 100% sure of
11975 * the base type attribute uses already being built.
11976 */
11977 if ((baseType != NULL) && (!baseIsAnyType) &&
11978 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
11979 (baseType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011980 xmlSchemaPErr(ctxt, baseType->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011981 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011982 "attribute uses not builded on base type '%s'.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +000011983 baseType->name, NULL);
11984 }
11985 return (0);
11986}
11987
11988/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000011989 * xmlSchemaTypeFinalContains:
11990 * @schema: the schema
11991 * @type: the type definition
11992 * @final: the final
11993 *
11994 * Evaluates if a type definition contains the given "final".
11995 * This does take "finalDefault" into account as well.
11996 *
11997 * Returns 1 if the type does containt the given "final",
11998 * 0 otherwise.
11999 */
12000static int
12001xmlSchemaTypeFinalContains(xmlSchemaPtr schema, xmlSchemaTypePtr type, int final)
12002{
12003 int tfinal = final, tflags = type->flags;
12004
12005 if (type == NULL)
12006 return (0);
12007 if (type->flags & XML_SCHEMAS_TYPE_FINAL_DEFAULT) {
12008 switch (final) {
12009 case XML_SCHEMAS_TYPE_FINAL_RESTRICTION:
12010 tfinal = XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
12011 break;
12012 case XML_SCHEMAS_TYPE_FINAL_EXTENSION:
12013 tfinal = XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
12014 break;
12015 case XML_SCHEMAS_TYPE_FINAL_LIST:
12016 tfinal = XML_SCHEMAS_FINAL_DEFAULT_LIST;
12017 break;
12018 case XML_SCHEMAS_TYPE_FINAL_UNION:
12019 tfinal = XML_SCHEMAS_FINAL_DEFAULT_UNION;
12020 break;
12021 }
12022 tflags = schema->flags;
12023 }
12024 if (tflags & tfinal)
12025 return (1);
12026 else
12027 return (0);
12028
12029}
12030
12031/**
12032 * xmlSchemaGetUnionSimpleTypeMemberTypes:
12033 * @type: the Union Simple Type
12034 *
12035 * Returns a list of member types of @type if existing,
12036 * returns NULL otherwise.
12037 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012038static xmlSchemaTypeLinkPtr
Daniel Veillard01fa6152004-06-29 17:04:39 +000012039xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
12040{
12041 while (type != NULL) {
12042 if (type->memberTypes != NULL)
12043 return (type->memberTypes);
12044 else
12045 type = type->baseType;
12046 }
12047 return (NULL);
12048}
12049
12050/**
12051 * xmlSchemaGetListSimpleTypeItemType:
12052 * @type: the simple type definition
12053 *
12054 * Returns the item type definition of the list simple type.
12055 */
12056static xmlSchemaTypePtr
12057xmlSchemaGetListSimpleTypeItemType(xmlSchemaTypePtr type)
12058{
12059 if ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)
12060 return (NULL);
12061 /*
12062 * Note: In libxml2, the built-in types do not reflect
12063 * the datatype hierarchy (yet?) - we have to treat them
12064 * in a special way.
12065 */
12066 if (type->type == XML_SCHEMA_TYPE_BASIC)
12067 return (xmlSchemaGetBuiltInListSimpleTypeItemType(type));
12068 if (type->subtypes->type == XML_SCHEMA_TYPE_LIST)
12069 /* 1 If the <list> alternative is chosen, then the type
12070 * definition ·resolved· to by the ·actual value· of the
12071 * itemType [attribute] of <list>, if present, otherwise
12072 * the type definition corresponding to the <simpleType>
12073 * among the [children] of <list>.
12074 */
12075 return (type->subtypes->subtypes);
12076 else {
12077 /* 2 If the <restriction> option is chosen, then the
12078 * {item type definition} of the {base type definition}.
12079 */
12080 return (xmlSchemaGetListSimpleTypeItemType(type->baseType));
12081 }
12082}
12083
12084/**
12085 * xmlSchemaCheckCOSSTDerivedOK:
12086 * @type: the derived simple type definition
12087 * @baseType: the base type definition
12088 *
12089 * Checks wheter @type can be validly
12090 * derived from @baseType.
12091 *
12092 * Returns 0 on success, an positive error code otherwise.
12093 */
12094static int
12095xmlSchemaCheckCOSSTDerivedOK(xmlSchemaPtr schema,
12096 xmlSchemaTypePtr type,
12097 xmlSchemaTypePtr baseType,
12098 int subset)
12099{
12100 /*
12101 * Schema Component Constraint: Type Derivation OK (Simple)
12102 *
12103 *
12104 * 1 They are the same type definition.
12105 * TODO: The identy check might have to be more complex than this.
12106 */
12107 if (type == baseType)
12108 return (0);
12109 /*
12110 * 2.1 restriction is not in the subset, or in the {final}
12111 * of its own {base type definition};
12112 */
12113 if ((subset & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) ||
12114 (xmlSchemaTypeFinalContains(schema,
12115 type->baseType, XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
12116 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
12117 }
12118 /* 2.2 */
12119 if (type->baseType == baseType) {
12120 /*
12121 * 2.2.1 D's ·base type definition· is B.
12122 */
12123 return (0);
12124 }
12125 /*
12126 * 2.2.2 D's ·base type definition· is not the ·ur-type definition·
12127 * and is validly derived from B given the subset, as defined by this
12128 * constraint.
12129 */
12130 if ((type->baseType != xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE)) &&
12131 (xmlSchemaCheckCOSSTDerivedOK(schema, type->baseType, baseType, subset) == 0)) {
12132 return (0);
12133 }
12134 /*
12135 * 2.2.3 D's {variety} is list or union and B is the ·simple ur-type
12136 * definition·.
12137 */
12138 if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
12139 (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)) &&
12140 (baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE))) {
12141 return (0);
12142 }
12143 /*
12144 * 2.2.4 B's {variety} is union and D is validly derived from a type
12145 * definition in B's {member type definitions} given the subset, as
12146 * defined by this constraint.
12147 *
12148 * NOTE: This seems not to involve built-in types, since there is no
12149 * built-in Union Simple Type.
12150 */
12151 if (baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
12152 xmlSchemaTypeLinkPtr cur;
12153
12154 cur = baseType->memberTypes;
12155 while (cur != NULL) {
12156 if (xmlSchemaCheckCOSSTDerivedOK(schema, type,
12157 cur->type, subset) == 0)
12158 return (0);
12159 cur = cur->next;
12160 }
12161 }
12162
12163 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
12164}
12165
12166
12167/**
12168 * xmlSchemaCheckSTPropsCorrect:
12169 * @ctxt: the schema parser context
12170 * @type: the simple type definition
12171 *
12172 * Checks st-props-correct.
12173 *
12174 * Returns 0 if the properties are correct,
12175 * if not, a positive error code and -1 on internal
12176 * errors.
12177 */
12178static int
12179xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
12180 xmlSchemaTypePtr type)
12181{
12182 xmlSchemaTypePtr baseType = type->baseType, anySimpleType,
12183 anyType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012184 xmlChar *str = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012185
Daniel Veillardc0826a72004-08-10 14:17:33 +000012186 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012187 /*
12188 * Schema Component Constraint: Simple Type Definition Properties Correct
12189 *
12190 * NOTE: This is somehow redundant, since we actually built a simple type
12191 * to have all the needed information; this acts as an self test.
12192 */
12193 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
12194 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
12195 /*
12196 * TODO: 1 The values of the properties of a simple type definition must be as
12197 * described in the property tableau in Datatype definition, modulo the
12198 * impact of Missing Sub-components (§5.3).
12199 */
12200 /* Base type: If the datatype has been ·derived· by ·restriction·
12201 * then the Simple Type Definition component from which it is ·derived·,
12202 * otherwise the Simple Type Definition for anySimpleType (§4.1.6).
12203 */
12204 if (baseType == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012205 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012206 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012207 NULL, type, NULL,
12208 "No base type existent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012209 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
12210 }
12211 if ((baseType->type != XML_SCHEMA_TYPE_SIMPLE) &&
12212 ((baseType->type != XML_SCHEMA_TYPE_BASIC) ||
12213 (baseType == anyType))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012214 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012215 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012216 NULL, type, NULL,
12217 "The base type %s is not a simple type",
12218 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
12219 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012220 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
12221 }
12222 if ((baseType != anySimpleType) &&
12223 (type->subtypes->type != XML_SCHEMA_TYPE_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012224 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012225 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012226 NULL, type, NULL,
12227 "A type, derived by list or union, must have"
12228 "the simple ur-type definition as base type, not %s",
12229 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
12230 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012231 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
12232 }
12233 /*
12234 * Variety: One of {atomic, list, union}.
12235 */
12236 if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
12237 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) &&
12238 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012239 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012240 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012241 NULL, type, NULL,
12242 "The variety is absent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012243 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
12244 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000012245 /* TODO: Finish this. Hmm, is this finished? */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012246
12247 /*
12248 * 2 All simple type definitions must be derived ultimately from the ·simple
12249 * ur-type definition (so· circular definitions are disallowed). That is, it
12250 * must be possible to reach a built-in primitive datatype or the ·simple
12251 * ur-type definition· by repeatedly following the {base type definition}.
12252 */
12253 baseType = type->baseType;
12254 while ((baseType != NULL) && (baseType->type != XML_SCHEMA_TYPE_BASIC)) {
12255 if (baseType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
12256 xmlSchemaTypeFixup(baseType, ctxt, NULL);
12257 if (baseType == anySimpleType)
12258 break;
12259 else if (baseType == type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012260 xmlSchemaPCustomErr(ctxt,
12261 XML_SCHEMAP_ST_PROPS_CORRECT_2,
12262 NULL, type, NULL,
12263 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012264 return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
12265 }
12266 baseType = baseType->baseType;
12267 }
12268 /*
12269 * 3 The {final} of the {base type definition} must not contain restriction.
12270 */
12271 if (xmlSchemaTypeFinalContains(ctxt->schema, baseType,
12272 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012273 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012274 XML_SCHEMAP_ST_PROPS_CORRECT_3,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012275 NULL, type, NULL,
12276 "The 'final' of its base type %s must not contain "
12277 "'restriction'",
12278 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
12279 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012280 return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
12281 }
12282 return (0);
12283}
12284
12285/**
12286 * xmlSchemaCheckDerivationValidSimpleRestriction:
12287 * @ctxt: the schema parser context
12288 * @type: the simple type definition
12289 *
12290 * Checks if the given @type (simpleType) is derived
12291 * validly by restriction.
12292 *
12293 * Returns -1 on internal errors, 0 if the type is validly derived,
12294 * a positive error code otherwise.
12295 */
12296static int
12297xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012298 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012299{
Daniel Veillardc0826a72004-08-10 14:17:33 +000012300 xmlChar *str = NULL;
12301
12302 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012303
12304 if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
12305 xmlSchemaPErr(ctxt, type->node,
12306 XML_ERR_INTERNAL_ERROR,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012307 "xmlSchemaCheckDerivationValidSimpleRestriction: The given "
12308 "type '%s' is not a user-derived simpleType.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012309 type->name, NULL);
12310 return (-1);
12311 }
12312
12313 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
12314 xmlSchemaTypePtr primitive;
12315 /*
12316 * 1.1 The {base type definition} must be an atomic simple
12317 * type definition or a built-in primitive datatype.
12318 */
12319 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012320 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012321 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012322 NULL, type, NULL,
12323 "The base type %s is not an atomic simple type",
12324 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
12325 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012326 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
12327 }
12328 /* 1.2 The {final} of the {base type definition} must not contain
12329 * restriction.
12330 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000012331 /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012332 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
12333 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012334 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012335 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012336 NULL, type, NULL,
12337 "The final of its base type %s must not contain 'restriction'",
12338 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
12339 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012340 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
12341 }
12342
12343 /*
12344 * 1.3.1 DF must be an allowed constraining facet for the {primitive
12345 * type definition}, as specified in the appropriate subsection of 3.2
12346 * Primitive datatypes.
12347 */
12348 if (type->facets != NULL) {
12349 xmlSchemaFacetPtr facet;
12350 int ok = 1;
12351
12352 primitive = xmlSchemaGetPrimitiveType(type);
12353 if (primitive == NULL) {
12354 xmlSchemaPErr(ctxt, type->node,
12355 XML_ERR_INTERNAL_ERROR,
12356 "xmlSchemaCheckDerivationValidSimpleRestriction: failed "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012357 "to get primitive type of type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012358 type->name, NULL);
12359 return (-1);
12360 }
12361 facet = type->facets;
12362 do {
12363 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012364 ok = 0;
12365 xmlSchemaPIllegalFacetAtomicErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012366 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012367 NULL, type, primitive, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012368 }
12369 facet = facet->next;
12370 } while (facet != NULL);
12371 if (ok == 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +000012372 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012373 }
12374 /*
12375 * TODO: 1.3.2 (facet derivation)
12376 */
12377 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
12378 xmlSchemaTypePtr itemType = NULL;
12379
12380 itemType = xmlSchemaGetListSimpleTypeItemType(type);
12381 if (itemType == NULL) {
12382 xmlSchemaPErr(ctxt, type->node,
12383 XML_ERR_INTERNAL_ERROR,
12384 "Internal error: xmlSchemaCheckDerivationValidSimpleRestriction: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012385 "failed to evaluate the item type of type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012386 type->name, NULL);
12387 return (-1);
12388 }
12389 /*
12390 * 2.1 The {item type definition} must have a {variety} of atomic or
12391 * union (in which case all the {member type definitions}
12392 * must be atomic).
12393 */
12394 if (((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
12395 ((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012396 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012397 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012398 NULL, type, NULL,
12399 "The item type %s must have a variety of atomic or union",
12400 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1));
12401 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012402 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
12403 } else if (itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
12404 xmlSchemaTypeLinkPtr member;
12405
12406 member = itemType->memberTypes;
12407 while (member != NULL) {
12408 if ((member->type->flags &
12409 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012410 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012411 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012412 NULL, type, NULL,
12413 "The item type is a union type, but the "
12414 "member type %s of this item type is not atomic",
12415 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
12416 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012417 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
12418 }
12419 member = member->next;
12420 }
12421 }
12422
12423 if (type->baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE)) {
12424 xmlSchemaFacetPtr facet;
12425 /*
12426 * This is the case if we have: <simpleType><list ..
12427 */
12428 /*
12429 * 2.3.1
12430 * 2.3.1.1 The {final} of the {item type definition} must not
12431 * contain list.
12432 */
12433 if (xmlSchemaTypeFinalContains(ctxt->schema,
12434 itemType, XML_SCHEMAS_TYPE_FINAL_LIST)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012435 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012436 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012437 NULL, type, NULL,
12438 "The final of its item type %s must not contain 'list'",
12439 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1));
12440 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012441 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
12442 }
12443 /*
12444 * 2.3.1.2 The {facets} must only contain the whiteSpace
12445 * facet component.
12446 */
12447 if (type->facets != NULL) {
12448 facet = type->facets;
12449 do {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012450 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
12451 xmlSchemaPIllegalFacetListUnionErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012452 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012453 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012454 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
12455 }
12456 facet = facet->next;
12457 } while (facet != NULL);
12458 }
12459 /*
12460 * TODO: Datatypes states:
12461 * A ·list· datatype can be ·derived· from an ·atomic· datatype
12462 * whose ·lexical space· allows space (such as string or anyURI)or
12463 * a ·union· datatype any of whose {member type definitions}'s
12464 * ·lexical space· allows space.
12465 */
12466 } else {
12467 /*
12468 * This is the case if we have: <simpleType><restriction ...
12469 */
12470 /*
12471 * 2.3.2
12472 * 2.3.2.1 The {base type definition} must have a {variety} of list.
12473 */
12474 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012475 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012476 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012477 NULL, type, NULL,
12478 "The base type %s must be a list type",
12479 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
12480 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012481 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
12482 }
12483 /*
12484 * 2.3.2.2 The {final} of the {base type definition} must not
12485 * contain restriction.
12486 */
12487 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
12488 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012489 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012490 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012491 NULL, type, NULL,
12492 "The final of the base type %s must not contain 'restriction'",
12493 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
12494 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012495 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
12496 }
12497 /*
12498 * 2.3.2.3 The {item type definition} must be validly derived
12499 * from the {base type definition}'s {item type definition} given
12500 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6).
12501 */
12502 {
12503 xmlSchemaTypePtr baseItemType;
12504
12505 baseItemType = xmlSchemaGetListSimpleTypeItemType(type->baseType);
12506 if (baseItemType == NULL) {
12507 xmlSchemaPErr(ctxt, type->node,
12508 XML_ERR_INTERNAL_ERROR,
12509 "xmlSchemaCheckDerivationValidSimpleRestriction: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012510 "List simple type '%s': Failed to "
12511 "evaluate the item type of its base type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012512 type->name, type->baseType->name);
12513 return (-1);
12514 }
12515 if ((itemType != baseItemType) &&
12516 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema, itemType,
12517 baseItemType, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012518 xmlChar *strBIT = NULL, *strBT = NULL;
12519 xmlSchemaPCustomErrExt(ctxt,
12520 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
12521 NULL, type, NULL,
12522 "The item type %s is not validly derived from the "
12523 "item type %s of the base type %s",
12524 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1),
12525 xmlSchemaFormatItemForReport(&strBIT, NULL, baseItemType, NULL, 1),
12526 xmlSchemaFormatItemForReport(&strBT, NULL, type->baseType, NULL, 1));
12527
12528 FREE_AND_NULL(str)
12529 FREE_AND_NULL(strBIT)
12530 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012531 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
12532 }
12533 }
12534
12535 if (type->facets != NULL) {
12536 xmlSchemaFacetPtr facet;
12537 int ok = 1;
12538 /*
12539 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
12540 * and enumeration facet components are allowed among the {facets}.
12541 */
12542 facet = type->facets;
12543 do {
12544 switch (facet->type) {
12545 case XML_SCHEMA_FACET_LENGTH:
12546 case XML_SCHEMA_FACET_MINLENGTH:
12547 case XML_SCHEMA_FACET_MAXLENGTH:
12548 case XML_SCHEMA_FACET_WHITESPACE:
12549 /*
12550 * TODO: 2.5.1.2 List datatypes
12551 * The value of ·whiteSpace· is fixed to the value collapse.
12552 */
12553 case XML_SCHEMA_FACET_PATTERN:
12554 case XML_SCHEMA_FACET_ENUMERATION:
12555 break;
12556 default: {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012557 xmlSchemaPIllegalFacetListUnionErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012558 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012559 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012560 /*
12561 * We could return, but it's nicer to report all
12562 * invalid facets.
12563 */
12564 ok = 0;
12565 }
12566 }
12567 facet = facet->next;
12568 } while (facet != NULL);
12569 if (ok == 0)
12570 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
12571 /*
12572 * TODO: 2.3.2.5 For each facet in the {facets} (call this DF), if there
12573 * is a facet of the same kind in the {facets} of the {base type
12574 * definition} (call this BF),then the DF's {value} must be a valid
12575 * restriction of BF's {value} as defined in [XML Schemas: Datatypes].
12576 */
12577 }
12578
12579
12580 }
12581 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
12582 /*
12583 * 3.1 The {member type definitions} must all have {variety} of
12584 * atomic or list.
12585 */
12586 xmlSchemaTypeLinkPtr member;
12587
12588 member = type->memberTypes;
12589 while (member != NULL) {
12590 if (((member->type->flags &
12591 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
12592 ((member->type->flags &
12593 XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012594 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012595 XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012596 NULL, type, NULL,
12597 "The member type %s is neither an atomic, nor a list type",
12598 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
12599 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012600 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
12601 }
12602 member = member->next;
12603 }
12604 /*
12605 * 3.3.1 If the {base type definition} is the ·simple ur-type
12606 * definition·
12607 */
12608 if (type->baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE)) {
12609 /*
12610 * 3.3.1.1 All of the {member type definitions} must have a
12611 * {final} which does not contain union.
12612 */
12613 member = type->memberTypes;
12614 while (member != NULL) {
12615 if (xmlSchemaTypeFinalContains(ctxt->schema, member->type,
12616 XML_SCHEMAS_TYPE_FINAL_UNION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012617 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012618 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012619 NULL, type, NULL,
12620 "The final of member type %s contains 'union'",
12621 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
12622 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012623 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
12624 }
12625 member = member->next;
12626 }
12627 /*
12628 * 3.3.1.2 The {facets} must be empty.
12629 */
12630 if (type->facetSet != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012631 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012632 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012633 NULL, type, NULL,
12634 "No facets allowed", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012635 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
12636 }
12637 } else {
12638 /*
12639 * 3.3.2.1 The {base type definition} must have a {variety} of union.
12640 */
12641 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012642 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012643 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012644 NULL, type, NULL,
12645 "The base type %s is not a union type",
12646 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
12647 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012648 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
12649 }
12650 /*
12651 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
12652 */
12653 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
12654 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012655 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012656 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012657 NULL, type, NULL,
12658 "The final of its base type %s must not contain 'restriction'",
12659 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
12660 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012661 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
12662 }
12663 /*
12664 * 3.3.2.3 The {member type definitions}, in order, must be validly
12665 * derived from the corresponding type definitions in the {base
12666 * type definition}'s {member type definitions} given the empty set,
12667 * as defined in Type Derivation OK (Simple) (§3.14.6).
12668 */
12669 {
12670 xmlSchemaTypeLinkPtr baseMember;
12671
12672 /*
12673 * OPTIMIZE: if the type is restricting, it has no local defined
12674 * member types and inherits the member types of the base type;
12675 * thus a check for equality can be skipped.
12676 */
12677 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000012678 * Even worse: I cannot see a scenario where a restricting
Daniel Veillard01fa6152004-06-29 17:04:39 +000012679 * union simple type can have other member types as the member
12680 * types of it's base type. This check seems not necessary with
12681 * respect to the derivation process in libxml2.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000012682 * But necessary if constructing types with an API.
Daniel Veillard01fa6152004-06-29 17:04:39 +000012683 */
12684 if (type->memberTypes != NULL) {
12685 member = type->memberTypes;
12686 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
12687 if ((member == NULL) && (baseMember != NULL)) {
12688 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012689 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012690 "Internal error: "
12691 "xmlSchemaCheckDerivationValidSimpleRestriction "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012692 "(3.3.2.3), union simple type '%s', unequal number "
Daniel Veillard01fa6152004-06-29 17:04:39 +000012693 "of member types in the base type\n",
12694 type->name, NULL);
12695 }
12696 while (member != NULL) {
12697 if (baseMember == NULL) {
12698 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012699 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012700 "Internal error: "
12701 "xmlSchemaCheckDerivationValidSimpleRestriction "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012702 "(3.3.2.3), union simple type '%s', unequal number "
12703 "of member types in the base type.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012704 type->name, NULL);
12705 }
12706 if ((member->type != baseMember->type) &&
12707 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema,
12708 member->type, baseMember->type, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012709 xmlChar *strBMT = NULL, *strBT = NULL;
12710
12711 xmlSchemaPCustomErrExt(ctxt,
12712 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
12713 NULL, type, NULL,
12714 "The member type %s is not validly derived from its "
12715 "corresponding member type %s of the base type %s",
12716 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1),
12717 xmlSchemaFormatItemForReport(&strBMT, NULL, baseMember->type, NULL, 1),
12718 xmlSchemaFormatItemForReport(&strBT, NULL, type->baseType, NULL, 1));
12719 FREE_AND_NULL(str)
12720 FREE_AND_NULL(strBMT)
12721 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012722 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
12723 }
12724 member = member->next;
12725 baseMember = baseMember->next;
12726 }
12727 }
12728 }
12729 /*
12730 * 3.3.2.4 Only pattern and enumeration facet components are
12731 * allowed among the {facets}.
12732 */
12733 if (type->facets != NULL) {
12734 xmlSchemaFacetPtr facet;
12735 int ok = 1;
12736
12737 facet = type->facets;
12738 do {
12739 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
12740 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012741 xmlSchemaPIllegalFacetListUnionErr(ctxt,
12742 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
12743 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012744 ok = 0;
12745 }
12746 facet = facet->next;
12747 } while (facet != NULL);
12748 if (ok == 0)
12749 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
12750
12751 }
12752 /*
12753 * TODO: 3.3.2.5 (facet derivation)
12754 */
12755 }
12756 }
12757
12758 return (0);
12759}
12760
12761/**
12762 * xmlSchemaCheckSRCSimpleType:
12763 * @ctxt: the schema parser context
12764 * @type: the simple type definition
12765 *
12766 * Checks crc-simple-type constraints.
12767 *
12768 * Returns 0 if the constraints are satisfied,
12769 * if not a positive error code and -1 on internal
12770 * errors.
12771 */
12772static int
12773xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
12774 xmlSchemaTypePtr type)
12775{
12776 /*
12777 * NOTE: src-simple-type 2-4 are redundant, since the checks
12778 * were are done for the corresponding <restriction>, <list> and <union>
12779 * elements, but W3C wants a <simpleType> error as well, so it gets one.
12780 * Maby this can be skipped in the future, if we get sure it's not needed.
12781 */
12782 if (type->subtypes == NULL) {
12783 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012784 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012785 "Internal error: xmlSchemaCheckSRCSimpleType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012786 "no subtype on simple type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012787 type->name, NULL);
12788 return (-1);
12789 }
12790 /*
12791 * src-simple-type.1 The corresponding simple type definition, if any,
12792 * must satisfy the conditions set out in Constraints on Simple Type
12793 * Definition Schema Components (§3.14.6).
12794 */
12795 if ((xmlSchemaCheckSTPropsCorrect(ctxt, type) != 0) ||
12796 (xmlSchemaCheckCOSSTRestricts(ctxt, type) != 0)) {
12797 /*
12798 * TODO: Removed this, since it got annoying to get an
12799 * extra error report, if anything failed until now.
12800 * Enable this if needed.
12801 */
12802 /*
12803 xmlSchemaPErr(ctxt, type->node,
12804 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012805 "Simple type '%s' does not satisfy the constraints "
Daniel Veillard01fa6152004-06-29 17:04:39 +000012806 "on simple type definitions.\n",
12807 type->name, NULL);
12808 */
12809 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_1);
12810 }
12811
12812 if (type->subtypes->type == XML_SCHEMA_TYPE_RESTRICTION) {
12813 /*
12814 * src-simple-type.2 If the <restriction> alternative is chosen,
12815 * either it must have a base [attribute] or a <simpleType> among its
12816 * [children], but not both.
12817 */
William M. Brack2f2a6632004-08-20 23:09:47 +000012818 /*
12819 * XML_SCHEMAP_SRC_SIMPLE_TYPE_2
12820 * NOTE: This was removed, since this will be already handled
12821 * in the parse function for <restriction>.
12822 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012823 } else if (type->subtypes->type == XML_SCHEMA_TYPE_LIST) {
12824 /* src-simple-type.3 If the <list> alternative is chosen, either it must have
12825 * an itemType [attribute] or a <simpleType> among its [children],
12826 * but not both.
12827 * NOTE: baseType is set to the local simple type definiton,
12828 * if existent, at parse time. This is a hack and not nice.
12829 */
William M. Brack2f2a6632004-08-20 23:09:47 +000012830 /*
12831 * TODO: Remove this, and add the check to the parse function of <list>.
12832 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012833 if (((type->subtypes->base == NULL) &&
12834 (type->baseType == NULL)) ||
12835 ((type->subtypes->base != NULL) &&
12836 (type->subtypes->baseType != NULL))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012837 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012838 XML_SCHEMAP_SRC_SIMPLE_TYPE_3,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012839 NULL, type, NULL,
12840 "Either the attribute 'itemType' or the <simpleType> child "
12841 "must be present on the <list> child ", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012842 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_3);
12843 }
12844
12845
12846 } else if (type->subtypes->type == XML_SCHEMA_TYPE_UNION) {
12847 xmlSchemaTypeLinkPtr member;
12848 xmlSchemaTypePtr ancestor, anySimpleType;
12849
12850 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
12851
12852 /* src-simple-type.4 Circular union type definition is disallowed. That is, if
12853 * the <union> alternative is chosen, there must not be any entries
12854 * in the memberTypes [attribute] at any depth which resolve to the
12855 * component corresponding to the <simpleType>.
12856 */
12857 member = type->memberTypes;
12858 while (member != NULL) {
12859 ancestor = member->type;
12860 while ((ancestor != NULL) && (ancestor->type != XML_SCHEMA_TYPE_BASIC)) {
12861 if (ancestor->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
12862 xmlSchemaTypeFixup(ancestor, ctxt, NULL);
12863 if (ancestor == anySimpleType)
12864 break;
12865 else if (ancestor == type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012866 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012867 XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012868 NULL, type, NULL,
12869 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012870 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
12871 } else if (ancestor->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
12872 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000012873 * TODO, FIXME: Although a list simple type must not have a union ST
Daniel Veillard01fa6152004-06-29 17:04:39 +000012874 * type as item type, which in turn has a list ST as member
12875 * type, we will assume this here as well, since this check
12876 * was not yet performed.
12877 */
12878
12879 }
12880 ancestor = ancestor->baseType;
12881 }
12882 member = member->next;
12883 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012884 }
12885
12886 return (0);
12887}
12888
William M. Brack2f2a6632004-08-20 23:09:47 +000012889#if 0 /* Not yet used code for CT schema validation */
12890static int
12891xmlSchemaCheckCVCSimpleType(xmlSchemaValidCtxtPtr ctxt,
12892 const xmlChar * value,
12893 xmlSchemaTypePtr type,
12894 int fireErrors)
12895{
12896 int ret;
12897 /*
12898 * 3.14.4 Simple Type Definition Validation Rules
12899 * Validation Rule: String Valid
12900 */
12901 /*
12902 * 1 It is schema-valid with respect to that definition as defined
12903 * by Datatype Valid in [XML Schemas: Datatypes].
12904 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012905 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type, value,
12906 fireErrors, 1, 1, 1);
William M. Brack2f2a6632004-08-20 23:09:47 +000012907 return (ret);
12908 /*
12909 * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
12910 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6), then
12911 * the string must be a ·declared entity name·.
12912 */
12913 /*
12914 * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
12915 * given the empty set, as defined in Type Derivation OK (Simple) (§3.14.6),
12916 * then every whitespace-delimited substring of the string must be a ·declared
12917 * entity name·.
12918 */
12919 /*
12920 * 2.3 otherwise no further condition applies.
12921 */
12922
12923 return (0);
12924}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012925#endif
12926
William M. Brack2f2a6632004-08-20 23:09:47 +000012927
12928static int
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012929xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
12930{
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000012931 if (vctxt->pctxt == NULL) {
12932 if (vctxt->schema != NULL)
12933 vctxt->pctxt = xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
12934 else
12935 vctxt->pctxt = xmlSchemaNewParserCtxt("*");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012936 if (vctxt->pctxt == NULL) {
12937 xmlSchemaVErr(vctxt, NULL,
12938 XML_SCHEMAV_INTERNAL,
12939 "Internal error: xmlSchemaCreatePCtxtOnVCtxt, "
12940 "failed to create a temp. parser context.\n",
William M. Brack2f2a6632004-08-20 23:09:47 +000012941 NULL, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012942 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012943 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012944 /* TODO: Pass user data. */
12945 xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error, vctxt->warning, NULL);
12946 }
12947 return (0);
12948}
12949
12950static int
12951xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
12952{
12953 if (ctxt->vctxt == NULL) {
12954 ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
12955 if (ctxt->vctxt == NULL) {
12956 xmlSchemaPErr(ctxt, NULL,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012957 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012958 "Internal error: xmlSchemaCreatePCtxtOnVCtxt, "
12959 "failed to create a temp. validation context.\n",
12960 NULL, NULL);
12961 return (-1);
12962 }
12963 /* TODO: Pass user data. */
12964 xmlSchemaSetValidErrors(ctxt->vctxt, ctxt->error, ctxt->warning, NULL);
12965 }
12966 return (0);
12967}
12968
12969/**
12970 * xmlSchemaCheckCOSValidDefault:
12971 * @ctxt: the schema parser context
12972 * @type: the simple type definition
12973 * @value: the default value
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000012974 * @val: the precomputed value to be returned
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012975 * @node: an optional node (the holder of the value)
12976 *
12977 * Checks the "cos-valid-default" constraints.
12978 *
12979 * Returns 0 if the constraints are satisfied,
12980 * if not, a positive error code and -1 on internal
12981 * errors.
12982 */
12983static int
12984xmlSchemaCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
12985 xmlSchemaValidCtxtPtr vctxt,
12986 xmlSchemaTypePtr type,
12987 const xmlChar *value,
12988 xmlNodePtr node)
12989{
12990 int ret = 0;
12991
12992 /*
12993 * cos-valid-default:
12994 * Schema Component Constraint: Element Default Valid (Immediate)
12995 * For a string to be a valid default with respect to a type
12996 * definition the appropriate case among the following must be true:
12997 */
12998 /*
12999 * NOTE: This has to work without a given node (the holder of the
13000 * value), since it should work on the component, i.e. an underlying
13001 * DOM must not be mandatory.
13002 */
13003 if ((pctxt == NULL) || (vctxt == NULL)) {
13004 xmlSchemaPErr(pctxt, node,
13005 XML_SCHEMAP_INTERNAL,
13006 "Internal error: xmlSchemaCheckCOSValidDefault, "
13007 "bad arguments: the parser and/or validation context is "
13008 "missing.\n",
13009 NULL, NULL);
13010 return (-1);
13011 }
13012 if IS_COMPLEX_TYPE(type) {
William M. Brack2f2a6632004-08-20 23:09:47 +000013013 /*
13014 * Complex type.
13015 *
13016 * 2.1 its {content type} must be a simple type definition or mixed.
13017 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013018 /*
13019 * TODO: Adjust this when the content type will be computed
13020 * correctly.
13021 */
13022 if ((type->contentType != XML_SCHEMA_CONTENT_SIMPLE) &&
13023 (type->contentType != XML_SCHEMA_CONTENT_BASIC) &&
13024 (type->contentType != XML_SCHEMA_CONTENT_MIXED)) {
13025 xmlSchemaPSimpleTypeErr(pctxt,
13026 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
13027 NULL, NULL, node,
13028 type, NULL, NULL,
13029 "If the type of a constraint value is complex, its content "
13030 "type must be mixed or a simple type",
13031 NULL, NULL);
13032 return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
13033 }
13034 if (type->contentType == XML_SCHEMA_CONTENT_MIXED) {
William M. Brack2f2a6632004-08-20 23:09:47 +000013035 /*
13036 * 2.2.2 If the {content type} is mixed, then the {content type}'s
13037 * particle must be ·emptiable· as defined by Particle Emptiable
13038 * (§3.9.6).
13039 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013040
William M. Brack2f2a6632004-08-20 23:09:47 +000013041 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013042 * URGENT TODO: Implement this.
William M. Brack2f2a6632004-08-20 23:09:47 +000013043 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013044 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000013045 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013046 }
13047 /*
13048 * 1 If the type definition is a simple type definition, then the string
13049 * must be ·valid· with respect to that definition as defined by String
13050 * Valid (§3.14.4).
13051 *
13052 * AND
13053 *
13054 * 2.2.1 If the {content type} is a simple type definition, then the
13055 * string must be ·valid· with respect to that simple type definition
13056 * as defined by String Valid (§3.14.4).
13057 */
13058 vctxt->node = node;
13059 vctxt->cur = NULL;
13060 ret = xmlSchemaValidateSimpleTypeValue(vctxt, type, value, 1, 1, 1, 0);
13061 /* ret = xmlSchemaCheckCVCSimpleType(vctxt, elemDecl->value, typeDef, 0); */
13062 if (ret < 0) {
13063 xmlSchemaPErr(pctxt, node,
13064 /* NOTNICE: error code: This function will be used during
13065 * schema construction and xsi:type validation.
13066 */
13067 XML_SCHEMAP_INTERNAL,
13068 "Internal error: xmlSchemaCheckCOSValidDefault, "
13069 "while validating a value constaint value.\n",
13070 NULL, NULL);
13071
13072 }
13073 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +000013074}
13075
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013076#if 0 /* Not yet used code for CT schema validation */
William M. Brack2f2a6632004-08-20 23:09:47 +000013077/**
13078 * xmlSchemaGetSTContentOfCT:
13079 * @ctxt: the schema parser context
13080 * @type: the complex type definition
13081 *
13082 *
13083 * Returns the corresponding simple type for the content of
13084 * the complex type.
13085 */
13086static xmlSchemaTypePtr
13087xmlSchemaGetSTContentOfCT(xmlSchemaParserCtxtPtr ctxt,
13088 xmlSchemaTypePtr type)
13089{
13090 xmlSchemaTypePtr orig = type, anyType;
13091
13092 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
13093 while ((type != NULL) && (type != anyType) &&
13094 (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
13095 if (type->type == XML_SCHEMA_TYPE_SIMPLE)
13096 return(type);
13097 type = type->baseType;
13098 }
13099 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013100 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000013101 NULL, orig, NULL,
13102 "Internal error: xmlSchemaGetSTContentTypeOfCT, "
13103 "no simple type for the content of complex type '%s' could be "
13104 "computed", orig->name);
13105 return (NULL);
13106}
13107
13108
William M. Brack2f2a6632004-08-20 23:09:47 +000013109
William M. Brack2f2a6632004-08-20 23:09:47 +000013110
13111/**
13112 * xmlSchemaCheckCOSCTExtends:
13113 * @ctxt: the schema parser context
13114 * @type: the complex type definition
13115 *
13116 * Schema Component Constraint: Derivation Valid (Extension)
13117 *
13118 * Returns 0 if the constraints are satisfied, a positive
13119 * error code if not and -1 if an internal error occured.
13120 */
13121static int
13122xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
13123 xmlSchemaTypePtr type)
13124{
13125 xmlSchemaTypePtr base;
13126 /*
13127 * 1 If the {base type definition} is a complex type definition,
13128 * then all of the following must be true:
13129 */
13130 base = type->baseType;
13131 if (base == NULL) {
13132 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013133 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000013134 NULL, type, NULL,
13135 "Internal error: xmlSchemaCheckCOSCTExtends, "
13136 "the complex type '%s' has no base type", type->name);
13137 return (-1);
13138 }
13139 if (base->type == XML_SCHEMA_TYPE_COMPLEX) {
13140 /*
13141 * 1.1 The {final} of the {base type definition} must not
13142 * contain extension.
13143 */
13144 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
13145 xmlSchemaPCustomErr(ctxt,
13146 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
13147 NULL, type, NULL,
13148 "The 'final' of the base type definition "
13149 "contains extension", NULL);
13150 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
13151 }
13152 /*
13153 * 1.2 Its {attribute uses} must be a subset of the {attribute uses}
13154 * of the complex type definition itself, that is, for every attribute
13155 * use in the {attribute uses} of the {base type definition}, there
13156 * must be an attribute use in the {attribute uses} of the complex
13157 * type definition itself whose {attribute declaration} has the same
13158 * {name}, {target namespace} and {type definition} as its attribute
13159 * declaration
13160 *
13161 * NOTE: This will be already satisfied by the way the attribute uses
13162 * are extended in xmlSchemaBuildAttributeValidation; thus this check
13163 * is not needed.
13164 */
13165
13166 /*
13167 * 1.3 If it has an {attribute wildcard}, the complex type definition
13168 * must also have one, and the base type definition's {attribute
13169 * wildcard}'s {namespace constraint} must be a subset of the complex
13170 * type definition's {attribute wildcard}'s {namespace constraint},
13171 * as defined by Wildcard Subset (§3.10.6).
13172 *
13173 * This is already checked in xmlSchemaBuildAttributeValidation; thus
13174 * this check is not needed.
13175 */
13176
13177 /*
13178 * 1.4 One of the following must be true:
13179 *
13180 * 1.4.1 The {content type} of the {base type definition} and the
13181 * {content type} of the complex type definition itself must be the same
13182 * simple type definition
13183 */
13184
13185
13186
13187 } else {
13188 /*
13189 * 2 If the {base type definition} is a simple type definition,
13190 * then all of the following must be true:
13191 */
13192 /*
13193 * 2.1 The {content type} must be the same simple type definition.
13194 */
13195 /*
13196 * 2.2 The {final} of the {base type definition} must not contain
13197 * extension
13198 */
13199 }
13200
13201}
13202
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013203static int
13204xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
13205 xmlSchemaTypePtr type)
13206{
13207 xmlSchemaTypePtr base, content;
13208 int OK = 0;
13209
13210 /*
13211 * TODO: Adjust the error codes here, as I used
13212 * XML_SCHEMAP_SRC_CT_1 only yet.
13213 */
13214 /*
13215 * Schema Representation Constraint:
13216 * Complex Type Definition Representation OK
13217 */
13218 base = type->baseType;
13219 if (base == NULL) {
13220 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL, NULL, type, NULL,
13221 "Internal error: xmlSchemaCheckSRCCT, '%s', no base type",
13222 type->name);
13223 return (-1);
13224 }
13225
13226 if (type->subtypes != NULL) {
13227 if (type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
13228 if IS_COMPLEX_TYPE(base) {
13229 /*
13230 * 1 If the <complexContent> alternative is chosen, the type definition
13231 * ·resolved· to by the ·actual value· of the base [attribute]
13232 * must be a complex type definition;
13233 */
13234 xmlSchemaPCustomErr(ctxt,
13235 XML_SCHEMAP_SRC_CT_1,
13236 NULL, type, NULL,
13237 "The base type is not a complex type", NULL);
13238 return (XML_SCHEMAP_SRC_CT_1);
13239 }
13240 } else if (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
13241
13242 if IS_SIMPLE_TYPE(base) {
13243 if (type->flags &
13244 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
13245 /*
13246 * 2.1.3 only if the <extension> alternative is also
13247 * chosen, a simple type definition.
13248 */
13249 /* TODO: Change error code to ..._SRC_CT_2_1_3. */
13250 xmlSchemaPCustomErr(ctxt,
13251 XML_SCHEMAP_SRC_CT_1,
13252 NULL, type, NULL,
13253 "A complex type (simple content) cannot restrict "
13254 "an other simple type",
13255 NULL);
13256 return (XML_SCHEMAP_SRC_CT_1);
13257 }
13258 OK = 1;
13259
13260 } else { /* if IS_SIMPLE_TYPE(base) */
13261 if (base->contentType = XML_SCHEMA_CONTENT_MIXED) {
13262 /*
13263 * 2.1.2 only if the <restriction> alternative is also
13264 * chosen, a complex type definition whose {content type}
13265 * is mixed and a particle emptyable.
13266 */
13267 /*
13268 * FIXME TODO: Check for *empiable particle* is missing.
13269 */
13270 if ((type->flags &
13271 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) == 0) {
13272 xmlSchemaPCustomErr(ctxt,
13273 XML_SCHEMAP_SRC_CT_1,
13274 NULL, type, NULL,
13275 "A complex type (simple content) cannot "
13276 "extend an other complex type which has a "
13277 "content type of: 'mixed' and emptiable particle",
13278 NULL);
13279 return (XML_SCHEMAP_SRC_CT_1);
13280 }
13281 /*
13282 * NOTE: This will be fired as well, if the base type
13283 * is *'anyType'*.
13284 * NOTE: type->subtypes->subtypes will be the
13285 * <restriction> item.
13286 */
13287 if (type->subtypes->subtypes == NULL) {
13288 /* Yes, this is paranoid programming. */
13289 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
13290 NULL, type, NULL,
13291 "Internal error: xmlSchemaCheckSRCCT, "
13292 "'%s', <simpleContent> has no <restriction>",
13293 type->name);
13294 return (-1);
13295 }
13296 /*
13297 * 2.2 If clause 2.1.2 above is satisfied, then there
13298 * must be a <simpleType> among the [children] of
13299 * <restriction>.
13300 */
13301 if (type->subtypes->subtypes->type !=
13302 XML_SCHEMA_TYPE_SIMPLE) {
13303 /* TODO: Change error code to ..._SRC_CT_2_2. */
13304 xmlSchemaPCustomErr(ctxt,
13305 XML_SCHEMAP_SRC_CT_1,
13306 NULL, type, NULL,
13307 "A <simpleType> is expected among the children "
13308 "of <restriction>", NULL);
13309 return (XML_SCHEMAP_SRC_CT_1);
13310 }
13311 OK = 1;
13312 } else { /* if (base->contentType = XML_SCHEMA_CONTENT_MIXED)*/
13313 /*
13314 * 2.1.1 a complex type definition whose {content type} is a
13315 * simple type definition;
13316 */
13317 if (base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) {
13318 xmlSchemaPCustomErr(ctxt,
13319 XML_SCHEMAP_SRC_CT_1,
13320 NULL, type, NULL,
13321 "A complex type (simple content) cannot "
13322 "be derived from the complex type '%s'",
13323 base->name);
13324 return (XML_SCHEMAP_SRC_CT_1);
13325 }
13326 content = base->contentTypeDef;
13327 if (content == NULL) {
13328 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
13329 NULL, type, NULL,
13330 "Internal error: xmlSchemaCheckSRCCT, "
13331 "'%s', base type has no content type",
13332 type->name);
13333 return (-1);
13334 }
13335 if (content->type != XML_SCHEMA_TYPE_SIMPLE) {
13336 xmlSchemaPCustomErr(ctxt,
13337 XML_SCHEMAP_SRC_CT_1,
13338 NULL, type, NULL,
13339 "A complex type (simple content) cannot "
13340 "be derived from the complex type '%s'",
13341 base->name);
13342 return (XML_SCHEMAP_SRC_CT_1);
13343 }
13344 }
13345 }
13346 }
13347 }
13348 /*
13349 * TODO: 3 The corresponding complex type definition component must
13350 * satisfy the conditions set out in Constraints on Complex Type
13351 * Definition Schema Components (§3.4.6);
13352 *
13353 * TODO: 4 If clause 2.2.1 or clause 2.2.2 in the correspondence specification
13354 * above for {attribute wildcard} is satisfied, the intensional
13355 * intersection must be expressible, as defined in Attribute Wildcard
13356 * Intersection (§3.10.6).
13357 */
13358
13359}
William M. Brack2f2a6632004-08-20 23:09:47 +000013360#endif
13361
Daniel Veillard01fa6152004-06-29 17:04:39 +000013362/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013363 * xmlSchemaGroupDefFixup:
13364 * @typeDecl: the schema model group definition
13365 * @ctxt: the schema parser context
13366 *
13367 * Fixes model group definitions.
13368 */
13369static void
13370xmlSchemaGroupDefFixup(xmlSchemaTypePtr group,
13371 xmlSchemaParserCtxtPtr ctxt,
13372 const xmlChar * name ATTRIBUTE_UNUSED)
13373{
13374 group->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
13375 if ((group->ref != NULL) && (group->subtypes == NULL)) {
13376 xmlSchemaTypePtr groupDef;
13377 /*
13378 * Resolve the reference.
13379 */
13380 groupDef = xmlSchemaGetGroup(ctxt->schema, group->ref,
13381 group->refNs);
13382 if (groupDef == NULL) {
13383 xmlSchemaPResCompAttrErr(ctxt,
13384 XML_SCHEMAP_SRC_RESOLVE,
13385 NULL, group, NULL,
13386 "ref", group->ref, group->refNs,
13387 XML_SCHEMA_TYPE_GROUP, NULL);
13388 return;
13389 }
13390 group->subtypes = groupDef;
13391 }
13392}
13393
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013394#if 0 /* Enable when the content type will be computed. */
13395static int
13396xmlSchemaComputeContentType(xmlSchemaParserCtxtPtr ctxt,
13397 xmlSchemaTypePtr type)
13398{
13399 xmlSchemaTypePtr base, res = NULL;
13400
13401 base = type->baseType;
13402 if (base == NULL) {
13403 xmlSchemaPCustomErr(ctxt,
13404 XML_SCHEMAP_INTERNAL,
13405 NULL, type, NULL,
13406 "Internal error: xmlSchemaGetContentType, "
13407 "the complex type '%s' has no base type", type->name);
13408 return (-1);
13409 }
13410 if (IS_ANYTYPE(base) || (type->subtypes->type ==
13411 XML_SCHEMA_TYPE_COMPLEX_CONTENT)) {
13412 xmlSchemaTypePtr start;
13413 /*
13414 * Effective 'mixed'.
13415 */
13416 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
13417 type->contentType = XML_SCHEMA_CONTENT_MIXED;
13418 /*
13419 * Effective content.
13420 */
13421 if (IS_ANYTYPE(base))
13422 start = type;
13423 else
13424 start = type->subtypes;
13425
13426 } else { /* if XML_SCHEMA_TYPE_COMPLEX_CONTENT */
13427 xmlSchemaTypePtr baseContentItem;
13428
13429 /*
13430 * Complex type with simple content.
13431 */
13432 if IS_COMPLEX_TYPE(base) {
13433 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
13434 /*
13435 * Summary: a complex type (simple content) can *restrict*
13436 * a complex type with the following content type:
13437 * 1. 'mixed' and an emptiable particle
13438 * 2. simple type
13439 */
13440 if (base->contentType == XML_SCHEMA_CONTENT_MIXED) {
13441 /*
13442 * 2 if the {content type} of the base type is mixed and a
13443 * particle which is ·emptiable·,
13444 * [...]
13445 * then starting from the simple type definition
13446 * corresponding to the <simpleType> among the [children]
13447 * of <restriction> (**which must be present**)
13448 *
13449 * FIXME TODO: Handle "emptiable particle".
13450 */
13451 res = type->subtypes->subtypes;
13452 if (res == NULL) {
13453 xmlSchemaPCustomErr(ctxt,
13454 XML_SCHEMAP_INTERNAL,
13455 NULL, type, NULL,
13456 "Internal error: xmlSchemaGetContentType, "
13457 "CT '%s' (restricting): <simpleContent> has no "
13458 "<restriction>",
13459 type->name);
13460 return (-1);
13461 }
13462
13463 res->subtypes;
13464 if (res == NULL) {
13465 xmlSchemaPCustomErr(ctxt,
13466 XML_SCHEMAP_INTERNAL,
13467 NULL, type, NULL,
13468 "Internal error: xmlSchemaGetContentType, "
13469 "CT '%s' (restricting): <restriction> has no "
13470 "mandatory <simpleType>",
13471 type->name);
13472 return (-1);
13473 }
13474 } else {
13475 baseContentItem = base->contentTypeDef;
13476 if (baseContentItem == NULL) {
13477 xmlSchemaPCustomErr(ctxt,
13478 XML_SCHEMAP_INTERNAL,
13479 NULL, type, NULL,
13480 "Internal error: xmlSchemaGetContentType, "
13481 "CT '%s' (restricting), the base type has no "
13482 "content type", type->name);
13483 return (-1);
13484 }
13485 if IS_SIMPLE_TYPE(baseContentItem) {
13486 /*
13487 * 1 If the base type is a complex type whose own
13488 * {content type} is a simple type and the <restriction>
13489 * alternative is chosen
13490 */
13491 /* type->subtypes->subtypes will be the restriction item.*/
13492 res = type->subtypes->subtypes;
13493 if (res == NULL) {
13494 xmlSchemaPCustomErr(ctxt,
13495 XML_SCHEMAP_INTERNAL,
13496 NULL, type, NULL,
13497 "Internal error: xmlSchemaGetContentType, "
13498 "CT '%s' (restricting): <simpleType> has no "
13499 "<restriction>", type->name);
13500 return (-1);
13501 }
13502 /*
13503 * 1.1 the simple type definition corresponding to the
13504 * <simpleType> among the [children] of <restriction>if
13505 * there is one;
13506 */
13507 res = res->subtypes;
13508 if (res == NULL) {
13509 /*
13510 * 1.2 otherwise the {content type}
13511 * of the base type .
13512 */
13513 res = baseContentItem;
13514 }
13515 }
13516 }
13517 /*
13518 * SPECIAL TODO: If *restricting* the spec wants us to
13519 * create an *additional* simple type which restricts the
13520 * located simple type; we won't do this yet, and look how
13521 * far we get with it.
13522 */
13523 } else { /* if XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION */
13524 /*
13525 * Summary: a complex type (simple content) can *extend*
13526 * only a complex base with a simple type as content.
13527 */
13528 /*
13529 * 3 If the type definition ·resolved· to by the ·actual
13530 * value· of the base [attribute] is a complex type
13531 * definition (whose own {content type} *must be* a simple
13532 * type definition, see below) and the *<extension>*
13533 * alternative is chosen, then the {content type} of that
13534 * complex type definition;
13535 */
13536 res = base->contentTypeDef;
13537 if (res == NULL) {
13538 xmlSchemaPCustomErr(ctxt,
13539 XML_SCHEMAP_INTERNAL,
13540 NULL, type, NULL,
13541 "Internal error: xmlSchemaGetContentType, "
13542 "CT '%s' (extending), the base type has no content "
13543 "type", type->name);
13544 return (-1);
13545 }
13546 if (! IS_SIMPLE_TYPE(res)) {
13547 xmlSchemaPCustomErr(ctxt,
13548 XML_SCHEMAP_INTERNAL,
13549 NULL, type, NULL,
13550 "Internal error: xmlSchemaGetContentType, "
13551 "CT '%s' (extending), the content type of the "
13552 "base is not a simple type", type->name);
13553 return (-1);
13554 }
13555 }
13556 } else /* if IS_COMPLEX_TYPE(base) */
13557 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
13558 /*
13559 * 4 otherwise (the type definition ·resolved· to by the
13560 * ·actual value· of the base [attribute] is a simple type
13561 * definition and the <extension> alternative is chosen),
13562 * then that simple type definition.
13563 */
13564 res = base;
13565 }
13566 type->contentTypeDef = res;
13567 if (res == NULL) {
13568 xmlSchemaPCustomErr(ctxt,
13569 XML_SCHEMAP_INTERNAL,
13570 NULL, type, NULL,
13571 "Internal error: xmlSchemaGetContentType, "
13572 "'%s', the content type could not be determined",
13573 type->name);
13574 return (-1);
13575 }
13576
13577 }
13578
13579}
13580#endif
13581
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013582/**
Daniel Veillard4255d502002-04-16 15:50:10 +000013583 * xmlSchemaTypeFixup:
13584 * @typeDecl: the schema type definition
13585 * @ctxt: the schema parser context
13586 *
13587 * Fixes the content model of the type.
13588 */
13589static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013590xmlSchemaTypeFixup(xmlSchemaTypePtr item,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013591 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000013592{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013593 xmlSchemaTypePtr ctxtType;
13594
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013595 if (item == NULL)
Daniel Veillard82bbbd42003-05-11 20:16:09 +000013596 return;
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013597 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000013598 * Do not fixup built-in types.
13599 */
13600 if (item->type == XML_SCHEMA_TYPE_BASIC)
13601 return;
13602 /*
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013603 * Do not allow the following types to be typefixed, prior to
13604 * the corresponding simple/complex types.
13605 */
13606 if (ctxt->ctxtType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013607 switch (item->type) {
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013608 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
13609 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
13610 case XML_SCHEMA_TYPE_UNION:
13611 case XML_SCHEMA_TYPE_RESTRICTION:
13612 case XML_SCHEMA_TYPE_EXTENSION:
13613 return;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013614 default:
13615 break;
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013616 }
13617 }
Daniel Veillard4255d502002-04-16 15:50:10 +000013618 if (name == NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013619 name = item->name;
13620 if (item->contentType == XML_SCHEMA_CONTENT_UNKNOWN) {
13621 switch (item->type) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013622 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013623 if (item->subtypes != NULL) {
13624 if (item->subtypes->contentType ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013625 XML_SCHEMA_CONTENT_UNKNOWN) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013626 xmlSchemaTypeFixup(item->subtypes, ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013627 NULL);
13628 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013629 item->contentType =
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013630 XML_SCHEMA_CONTENT_SIMPLE;
13631 /* item->subtypes->contentType; */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013632 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013633 break;
13634 }
13635 case XML_SCHEMA_TYPE_RESTRICTION:{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013636 xmlSchemaTypePtr base = NULL;
13637
13638 ctxt->ctxtType->flags |=
13639 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013640 if (item->baseType != NULL)
13641 base = item->baseType;
13642 else if (item->base != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013643 base =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013644 xmlSchemaGetType(ctxt->schema, item->base,
13645 item->baseNs);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013646 if (base == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013647 xmlSchemaPResCompAttrErr(ctxt,
13648 XML_SCHEMAP_SRC_RESOLVE,
William M. Brack2f2a6632004-08-20 23:09:47 +000013649 NULL, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013650 (xmlNodePtr) xmlSchemaGetPropNode(item->node, "base"),
13651 "base", item->base, item->baseNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013652 XML_SCHEMA_TYPE_BASIC, "type definition");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013653 } else if (base->contentType ==
Daniel Veillard3646d642004-06-02 19:19:14 +000013654 XML_SCHEMA_CONTENT_UNKNOWN) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013655 xmlSchemaTypeFixup(base, ctxt, NULL);
13656 }
William M. Brack2f2a6632004-08-20 23:09:47 +000013657 }
13658 ctxt->ctxtType->baseType = base;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013659 if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX) {
13660 /*
13661 * ComplexType restriction.
William M. Brack2f2a6632004-08-20 23:09:47 +000013662 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013663 /*
13664 * Content type.
13665 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013666 if (item->subtypes == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013667 /* 1.1.1 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013668 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
13669 else if ((item->subtypes->subtypes == NULL) &&
13670 ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013671 XML_SCHEMA_TYPE_ALL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013672 || (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013673 XML_SCHEMA_TYPE_SEQUENCE)))
13674 /* 1.1.2 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013675 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
13676 else if ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013677 XML_SCHEMA_TYPE_CHOICE)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013678 && (item->subtypes->subtypes == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +000013679 /* 1.1.3 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013680 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013681 else {
13682 /* 1.2 and 2.X are applied at the other layer */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013683 item->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000013684 XML_SCHEMA_CONTENT_ELEMENTS;
13685 }
13686 } else {
13687 /*
13688 * SimpleType restriction.
13689 */
William M. Brack2f2a6632004-08-20 23:09:47 +000013690 /* TODO: Nothing? */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013691 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013692 break;
13693 }
13694 case XML_SCHEMA_TYPE_EXTENSION:{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013695 xmlSchemaTypePtr base = NULL;
13696 xmlSchemaContentType explicitContentType;
13697
13698 /*
13699 * An extension does exist on a complexType only.
13700 */
13701 ctxt->ctxtType->flags |=
13702 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013703 if (item->recurse) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013704 /* TODO: The word "recursive" should be changed to "circular" here. */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013705 xmlSchemaPCustomErr(ctxt,
13706 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013707 NULL, item, item->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013708 "This item is circular", NULL);
Daniel Veillard2582a332004-04-18 19:49:46 +000013709 return;
13710 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013711 if (item->base != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013712 base =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013713 xmlSchemaGetType(ctxt->schema, item->base,
13714 item->baseNs);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013715 if (base == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013716 xmlSchemaPResCompAttrErr(ctxt,
13717 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013718 NULL, item, item->node,
13719 "base", item->base, item->baseNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013720 XML_SCHEMA_TYPE_BASIC, "type definition");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013721 } else if (base->contentType ==
13722 XML_SCHEMA_CONTENT_UNKNOWN) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013723 item->recurse = 1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013724 xmlSchemaTypeFixup(base, ctxt, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013725 item->recurse = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013726 }
13727 /*
13728 * The type definition ·resolved· to by the ·actual
13729 * value· of the base [attribute]
13730 */
13731 ctxt->ctxtType->baseType = base;
13732 /*
13733 * TODO: This one is still needed for computation of
13734 * the content model by xmlSchemaBuildAContentModel.
13735 * Try to get rid of it.
13736 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013737 item->baseType = base;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013738 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013739 if ((item->subtypes != NULL) &&
13740 (item->subtypes->contentType == XML_SCHEMA_CONTENT_UNKNOWN))
13741 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013742
13743 explicitContentType = XML_SCHEMA_CONTENT_ELEMENTS;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013744 if (item->subtypes == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013745 /* 1.1.1 */
13746 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013747 else if ((item->subtypes->subtypes == NULL) &&
13748 ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013749 XML_SCHEMA_TYPE_ALL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013750 || (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013751 XML_SCHEMA_TYPE_SEQUENCE)))
13752 /* 1.1.2 */
13753 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013754 else if ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013755 XML_SCHEMA_TYPE_CHOICE)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013756 && (item->subtypes->subtypes == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +000013757 /* 1.1.3 */
13758 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
13759 if (base != NULL) {
13760 /* It will be reported later, if the base is missing. */
13761 if (explicitContentType == XML_SCHEMA_CONTENT_EMPTY) {
13762 /* 2.1 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013763 item->contentType = base->contentType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013764 } else if (base->contentType ==
13765 XML_SCHEMA_CONTENT_EMPTY) {
13766 /* 2.2 imbitable ! */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013767 item->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000013768 XML_SCHEMA_CONTENT_ELEMENTS;
13769 } else {
13770 /* 2.3 imbitable pareil ! */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013771 item->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000013772 XML_SCHEMA_CONTENT_ELEMENTS;
13773 }
13774 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013775 break;
13776 }
13777 case XML_SCHEMA_TYPE_COMPLEX:{
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013778 ctxtType = ctxt->ctxtType;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013779 ctxt->ctxtType = item;
13780 /*
13781 * Start with an empty content-type type.
13782 */
13783 if (item->subtypes == NULL)
13784 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
13785
13786 if ((item->subtypes == NULL) ||
13787 ((item->subtypes->type !=
Daniel Veillard01fa6152004-06-29 17:04:39 +000013788 XML_SCHEMA_TYPE_SIMPLE_CONTENT) &&
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013789 (item->subtypes->type !=
Daniel Veillard01fa6152004-06-29 17:04:39 +000013790 XML_SCHEMA_TYPE_COMPLEX_CONTENT))) {
13791 /*
13792 * This case is understood as shorthand for complex
13793 * content restricting the ur-type definition, and
13794 * the details of the mappings should be modified as
13795 * necessary.
13796 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013797 item->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
13798 item->flags |=
Daniel Veillard01fa6152004-06-29 17:04:39 +000013799 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013800 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013801 * Assume that we inherit the content-type type
13802 * from 'anyType', which is 'mixed' and a particle
13803 * emptiable.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013804 */
13805 item->contentType = item->baseType->contentType;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013806 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013807 /*
13808 * Fixup the sub components.
13809 */
13810 if ((item->subtypes != NULL) &&
13811 (item->subtypes->contentType ==
13812 XML_SCHEMA_CONTENT_UNKNOWN)) {
13813 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013814 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013815 if (item->flags & XML_SCHEMAS_TYPE_MIXED) {
13816 item->contentType = XML_SCHEMA_CONTENT_MIXED;
13817 } else if (item->subtypes != NULL) {
13818 /*
13819 * Use the content-type type of the model groups
13820 * defined, if 'mixed' is not set. If 'mixed' is set
13821 * it will expand the content-type by allowing character
13822 * content to appear.
13823 */
13824 item->contentType =
13825 item->subtypes->contentType;
13826 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013827
13828 /*
13829 * Some optimization for validation:
13830 * If there are no facets beside the "whitespace" facet,
13831 * then a value needs not to checked against against a
13832 * facet, thus no computed value is needed.
13833 * TODO URGENT: This is just a workaround, we need to
13834 * introduce the correct usage of contentType to store the
13835 * facets in!
13836 */
Daniel Veillardd3210bc2005-01-28 17:56:39 +000013837 if ((item->baseType != NULL) &&
13838 (item->baseType->flags &
13839 XML_SCHEMAS_TYPE_FACETSNEEDVALUE))
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013840 item->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
13841 else {
13842 xmlSchemaFacetLinkPtr cur;
13843
13844 for (cur = item->facetSet; cur != NULL;
13845 cur = cur->next) {
13846 if (cur->facet->type != XML_SCHEMA_FACET_WHITESPACE) {
13847 item->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
13848 break;
13849 }
13850 }
13851 }
13852
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013853 xmlSchemaBuildAttributeValidation(ctxt, item);
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000013854 xmlSchemaCheckDefaults(item, ctxt, item->name);
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013855 ctxt->ctxtType = ctxtType;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013856 break;
13857 }
13858 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013859 if (item->subtypes == NULL) {
13860 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
13861 if (item->flags & XML_SCHEMAS_TYPE_MIXED)
13862 item->contentType =
Daniel Veillard1aefc862004-03-04 11:40:48 +000013863 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013864 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013865 if (item->flags & XML_SCHEMAS_TYPE_MIXED) {
13866 item->contentType =
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013867 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillard3646d642004-06-02 19:19:14 +000013868 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013869 xmlSchemaTypeFixup(item->subtypes, ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013870 NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013871 if (item->subtypes != NULL)
13872 item->contentType =
13873 item->subtypes->contentType;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013874 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013875 /*
13876 * Removed due to implementation of the build of attribute uses.
13877 */
13878 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013879 if (item->attributes == NULL)
13880 item->attributes =
13881 item->subtypes->attributes;
Daniel Veillard3646d642004-06-02 19:19:14 +000013882 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013883 }
13884 break;
13885 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013886 case XML_SCHEMA_TYPE_SIMPLE:
13887 /*
13888 * Simple Type Definition Schema Component
13889 *
13890 */
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013891 ctxtType = ctxt->ctxtType;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013892 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
13893 if (item->subtypes->contentType ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013894 XML_SCHEMA_CONTENT_UNKNOWN) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013895 ctxt->ctxtType = item;
13896 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013897 }
13898 /* Fixup base type */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013899 if ((item->baseType != NULL) &&
13900 (item->baseType->contentType ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013901 XML_SCHEMA_CONTENT_UNKNOWN)) {
13902 /* OPTIMIZE: Actually this one will never by hit, since
13903 * the base type is already type-fixed in <restriction>.
13904 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013905 ctxt->ctxtType = item;
13906 xmlSchemaTypeFixup(item->baseType, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013907 }
13908 /* Base type:
13909 * 2 If the <list> or <union> alternative is chosen,
13910 * then the ·simple ur-type definition·.
13911 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013912 if (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013913 XML_SCHEMA_TYPE_LIST) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013914 item->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
13915 item->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
13916 } else if (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013917 XML_SCHEMA_TYPE_UNION) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013918 item->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
13919 item->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
13920 } else if (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013921 XML_SCHEMA_TYPE_RESTRICTION) {
13922 xmlSchemaFacetLinkPtr facet, cur, last = NULL;
13923
13924 /*
13925 * Variety
13926 * If the <restriction> alternative is chosen, then the
13927 * {variety} of the {base type definition}.
13928 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013929 if (item->baseType != NULL) {
13930 if (item->baseType->flags &
Daniel Veillard01fa6152004-06-29 17:04:39 +000013931 XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013932 item->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
13933 else if (item->baseType->flags &
Daniel Veillard01fa6152004-06-29 17:04:39 +000013934 XML_SCHEMAS_TYPE_VARIETY_LIST)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013935 item->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
13936 else if (item->baseType->flags &
Daniel Veillard01fa6152004-06-29 17:04:39 +000013937 XML_SCHEMAS_TYPE_VARIETY_UNION)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013938 item->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013939 /*
13940 * Schema Component Constraint: Simple Type Restriction
13941 * (Facets)
13942 * NOTE: Satisfaction of 1 and 2 arise from the fixup
13943 * applied beforehand.
13944 *
13945 * 3 The {facets} of R are the union of S and the {facets}
13946 * of B, eliminating duplicates. To eliminate duplicates,
13947 * when a facet of the same kind occurs in both S and the
13948 * {facets} of B, the one in the {facets} of B is not
13949 * included, with the exception of enumeration and pattern
13950 * facets, for which multiple occurrences with distinct values
13951 * are allowed.
13952 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013953 if (item->baseType->facetSet != NULL) {
13954 last = item->facetSet;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013955 if (last != NULL)
13956 while (last->next != NULL)
13957 last = last->next;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013958 cur = item->baseType->facetSet;
13959 for (; cur != NULL; cur = cur->next) {
13960 /*
13961 * Base patterns won't be add here:
13962 * they are ORed in a type and
13963 * ANDed in derived types. This will
13964 * happed at validation level by
13965 * walking the base axis of the type.
13966 */
13967 if (cur->facet->type ==
13968 XML_SCHEMA_FACET_PATTERN)
13969 continue;
13970 facet = NULL;
13971 if ((item->facetSet != NULL) &&
13972 /* REMOVED: a check for
13973 * XML_SCHEMA_FACET_PATTERN was already
13974 * performed above.
13975
13976 * (cur->facet->type !=
13977 * XML_SCHEMA_FACET_PATTERN) &&
Daniel Veillard01fa6152004-06-29 17:04:39 +000013978 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013979 (cur->facet->type !=
13980 XML_SCHEMA_FACET_ENUMERATION)) {
13981 facet = item->facetSet;
13982 do {
13983 if (cur->facet->type ==
13984 facet->facet->type)
13985 break;
13986 facet = facet->next;
13987 } while (facet != NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013988 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013989 if (facet == NULL) {
13990 facet = (xmlSchemaFacetLinkPtr)
13991 xmlMalloc(sizeof(xmlSchemaFacetLink));
13992 if (facet == NULL) {
13993 xmlSchemaPErrMemory(ctxt,
13994 "fixing simpleType", NULL);
13995 return;
13996 }
13997 /*
13998 * The facets are not copied but referenced
13999 * via the facet link.
14000 */
14001 facet->facet = cur->facet;
14002 facet->next = NULL;
14003 if (last == NULL)
14004 item->facetSet = facet;
14005 else
14006 last->next = facet;
14007 last = facet;
14008 }
14009 }
14010 }
14011 /*
14012 * Some optimization for validation:
14013 * If there are no facets beside the "whitespace" facet,
14014 * then a value needs not to checked against against a
14015 * facet, thus no computed value is needed.
14016 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000014017 if (item->baseType->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000014018 item->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
14019 else {
14020 for (cur = item->facetSet; cur != NULL;
14021 cur = cur->next) {
14022 if (cur->facet->type != XML_SCHEMA_FACET_WHITESPACE) {
14023 item->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
14024 break;
14025 }
14026 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014027 }
14028 }
14029 }
14030 /*
14031 * Check constraints.
14032 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014033 xmlSchemaCheckSRCSimpleType(ctxt, item);
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000014034 xmlSchemaCheckDefaults(item, ctxt, item->name);
Daniel Veillard4e5d6652004-06-29 21:01:12 +000014035 ctxt->ctxtType = ctxtType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014036 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014037 case XML_SCHEMA_TYPE_SEQUENCE:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014038 case XML_SCHEMA_TYPE_ALL:
14039 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014040 item->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014041 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014042 case XML_SCHEMA_TYPE_GROUP:
14043 /*
14044 * TODO: Handling was moved to xmlSchemaGroupDefFixup.
14045 */
14046 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014047 case XML_SCHEMA_TYPE_LIST:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014048 xmlSchemaParseListRefFixup(item, ctxt);
14049 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014050 break;
14051 case XML_SCHEMA_TYPE_UNION:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014052 xmlSchemaParseUnionRefCheck(item, ctxt);
14053 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014054 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014055 case XML_SCHEMA_TYPE_BASIC:
14056 case XML_SCHEMA_TYPE_ANY:
14057 case XML_SCHEMA_TYPE_FACET:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014058 case XML_SCHEMA_TYPE_UR:
14059 case XML_SCHEMA_TYPE_ELEMENT:
14060 case XML_SCHEMA_TYPE_ATTRIBUTE:
14061 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
William M. Brack29aa7722004-05-12 00:27:56 +000014062 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014063 case XML_SCHEMA_TYPE_NOTATION:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014064 case XML_SCHEMA_FACET_MININCLUSIVE:
14065 case XML_SCHEMA_FACET_MINEXCLUSIVE:
14066 case XML_SCHEMA_FACET_MAXINCLUSIVE:
14067 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
14068 case XML_SCHEMA_FACET_TOTALDIGITS:
14069 case XML_SCHEMA_FACET_FRACTIONDIGITS:
14070 case XML_SCHEMA_FACET_PATTERN:
14071 case XML_SCHEMA_FACET_ENUMERATION:
14072 case XML_SCHEMA_FACET_WHITESPACE:
14073 case XML_SCHEMA_FACET_LENGTH:
14074 case XML_SCHEMA_FACET_MAXLENGTH:
14075 case XML_SCHEMA_FACET_MINLENGTH:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014076 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
14077 if (item->subtypes != NULL)
14078 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014079 break;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000014080 case XML_SCHEMA_TYPE_IDC_UNIQUE:
14081 case XML_SCHEMA_TYPE_IDC_KEY:
14082 case XML_SCHEMA_TYPE_IDC_KEYREF:
14083 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014084 }
14085 }
Daniel Veillard8651f532002-04-17 09:06:27 +000014086#ifdef DEBUG_TYPE
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014087 if (item->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014088 xmlGenericError(xmlGenericErrorContext,
14089 "Type of %s : %s:%d :", name,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014090 item->node->doc->URL,
14091 xmlGetLineNo(item->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +000014092 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014093 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000014094 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014095 switch (item->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014096 case XML_SCHEMA_CONTENT_SIMPLE:
14097 xmlGenericError(xmlGenericErrorContext, "simple\n");
14098 break;
14099 case XML_SCHEMA_CONTENT_ELEMENTS:
14100 xmlGenericError(xmlGenericErrorContext, "elements\n");
14101 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000014102 case XML_SCHEMA_CONTENT_UNKNOWN:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014103 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
14104 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000014105 case XML_SCHEMA_CONTENT_EMPTY:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014106 xmlGenericError(xmlGenericErrorContext, "empty\n");
14107 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000014108 case XML_SCHEMA_CONTENT_MIXED:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014109 xmlGenericError(xmlGenericErrorContext, "mixed\n");
14110 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014111 /* Removed, since not used. */
14112 /*
Daniel Veillard8651f532002-04-17 09:06:27 +000014113 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014114 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
14115 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014116 */
Daniel Veillard8651f532002-04-17 09:06:27 +000014117 case XML_SCHEMA_CONTENT_BASIC:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014118 xmlGenericError(xmlGenericErrorContext, "basic\n");
14119 break;
14120 default:
14121 xmlGenericError(xmlGenericErrorContext,
14122 "not registered !!!\n");
14123 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000014124 }
14125#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000014126}
14127
14128/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000014129 * xmlSchemaCheckFacet:
14130 * @facet: the facet
14131 * @typeDecl: the schema type definition
14132 * @ctxt: the schema parser context or NULL
14133 * @name: name of the type
14134 *
14135 * Checks the default values types, especially for facets
14136 *
14137 * Returns 0 if okay or -1 in cae of error
14138 */
14139int
14140xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014141 xmlSchemaTypePtr typeDecl,
14142 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000014143{
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +000014144 xmlSchemaTypePtr nonNegativeIntegerType = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014145 int ret = 0, reuseValCtxt = 0;
14146
Daniel Veillardce682bc2004-11-05 17:22:25 +000014147 if ((facet == NULL) || (typeDecl == NULL))
14148 return(-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014149 /*
14150 * TODO: will the parser context be given if used from
14151 * the relaxNG module?
14152 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000014153
14154 if (nonNegativeIntegerType == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014155 nonNegativeIntegerType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000014156 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000014157 }
14158 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014159 case XML_SCHEMA_FACET_MININCLUSIVE:
14160 case XML_SCHEMA_FACET_MINEXCLUSIVE:
14161 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardf4b05d02004-07-05 13:10:37 +000014162 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
14163 case XML_SCHEMA_FACET_ENUMERATION: {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014164 /*
14165 * Okay we need to validate the value
14166 * at that point.
14167 */
14168 xmlSchemaValidCtxtPtr vctxt;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014169 xmlSchemaTypePtr base;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000014170
14171 /* 4.3.5.5 Constraints on enumeration Schema Components
14172 * Schema Component Constraint: enumeration valid restriction
14173 * It is an ·error· if any member of {value} is not in the
14174 * ·value space· of {base type definition}.
14175 *
14176 * minInclusive, maxInclusive, minExclusive, maxExclusive:
14177 * The value ·must· be in the
14178 * ·value space· of the ·base type·.
14179 */
14180 /*
14181 * This function is intended to deliver a compiled value
14182 * on the facet. In XML Schemas the type holding a facet,
14183 * cannot be a built-in type. Thus to ensure that other API
14184 * calls (relaxng) do work, if the given type is a built-in
14185 * type, we will assume that the given built-in type *is
14186 * already* the base type.
14187 */
14188 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
14189 base = typeDecl->baseType;
14190 if (base == NULL) {
14191 xmlSchemaPErr(ctxt, typeDecl->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014192 XML_SCHEMAP_INTERNAL,
Daniel Veillardf4b05d02004-07-05 13:10:37 +000014193 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000014194 "the type '%s' has no base type.\n",
Daniel Veillardf4b05d02004-07-05 13:10:37 +000014195 typeDecl->name, NULL);
14196 return (-1);
14197 }
14198 } else
14199 base = typeDecl;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014200 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014201 * This avoids perseverative creation of the
14202 * validation context if a parser context is
14203 * used.
Daniel Veillard01fa6152004-06-29 17:04:39 +000014204 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014205 if (ctxt != NULL) {
14206 reuseValCtxt = 1;
14207 if (ctxt->vctxt == NULL) {
14208 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
14209 return (-1);
14210 }
14211 vctxt = ctxt->vctxt;
14212 } else {
14213 vctxt = xmlSchemaNewValidCtxt(NULL);
14214 if (vctxt == NULL) {
14215 xmlSchemaPErr(ctxt, typeDecl->node,
14216 XML_SCHEMAP_INTERNAL,
14217 "Internal error: xmlSchemaCheckFacet, "
14218 "creating a new validation context.\n",
14219 NULL, NULL);
14220 return (-1);
14221 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014222 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014223
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014224 vctxt->node = facet->node;
14225 vctxt->cur = NULL;
14226 /*
14227 * NOTE: This call does not check the content nodes,
14228 * since they are not available:
14229 * facet->node is just the node holding the facet
14230 * definition, *not* the attribute holding the *value*
14231 * of the facet.
14232 */
14233 ret = xmlSchemaValidateSimpleTypeValue(vctxt, base,
14234 facet->value, 0, 1, 1, 0);
Daniel Veillardf4b05d02004-07-05 13:10:37 +000014235 facet->val = vctxt->value;
14236 vctxt->value = NULL;
14237 if (ret > 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014238 /* error code */
14239 if (ctxt != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014240 xmlSchemaPErrExt(ctxt, facet->node,
14241 XML_SCHEMAP_INVALID_FACET,
14242 NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014243 "Type definition '%s': The value '%s' of the "
14244 "facet '%s' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000014245 name, facet->value,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014246 xmlSchemaFacetTypeToString(facet->type),
Daniel Veillard01fa6152004-06-29 17:04:39 +000014247 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014248 }
14249 ret = -1;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000014250 } else if (ret < 0) {
14251 xmlSchemaPErrExt(ctxt, facet->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014252 XML_SCHEMAP_INTERNAL,
Daniel Veillardf4b05d02004-07-05 13:10:37 +000014253 NULL, NULL, NULL,
14254 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000014255 "failed to validate the value '%s' name of the "
14256 "facet '%s' against the base type '%s'.\n",
Daniel Veillardf4b05d02004-07-05 13:10:37 +000014257 facet->value,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014258 xmlSchemaFacetTypeToString(facet->type),
Daniel Veillardf4b05d02004-07-05 13:10:37 +000014259 base->name, NULL, NULL);
14260 ret = -1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014261 }
14262 if (reuseValCtxt == 0)
14263 xmlSchemaFreeValidCtxt(vctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014264 break;
14265 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014266 case XML_SCHEMA_FACET_PATTERN:
14267 facet->regexp = xmlRegexpCompile(facet->value);
14268 if (facet->regexp == NULL) {
14269 xmlSchemaPErr(ctxt, typeDecl->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014270 XML_SCHEMAP_REGEXP_INVALID,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014271 "Type definition '%s': The value '%s' of the "
14272 "facet 'pattern' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000014273 name, facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014274 ret = -1;
14275 }
14276 break;
14277 case XML_SCHEMA_FACET_TOTALDIGITS:
14278 case XML_SCHEMA_FACET_FRACTIONDIGITS:
14279 case XML_SCHEMA_FACET_LENGTH:
14280 case XML_SCHEMA_FACET_MAXLENGTH:
14281 case XML_SCHEMA_FACET_MINLENGTH:{
14282 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000014283
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014284 tmp =
14285 xmlSchemaValidatePredefinedType(nonNegativeIntegerType,
14286 facet->value,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +000014287 &(facet->val));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014288 if (tmp != 0) {
14289 /* error code */
14290 if (ctxt != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014291 xmlSchemaPErrExt(ctxt, facet->node,
14292 XML_SCHEMAP_INVALID_FACET_VALUE,
14293 NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014294 "Type definition '%s': The value '%s' of the "
14295 "facet '%s' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000014296 name, facet->value,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014297 xmlSchemaFacetTypeToString(facet->type),
Daniel Veillard01fa6152004-06-29 17:04:39 +000014298 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014299 }
14300 ret = -1;
14301 }
14302 break;
14303 }
14304 case XML_SCHEMA_FACET_WHITESPACE:{
14305 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
14306 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
14307 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
14308 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
14309 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
14310 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
14311 } else {
14312 if (ctxt != NULL) {
14313 xmlSchemaPErr(ctxt, facet->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014314 XML_SCHEMAP_INVALID_WHITE_SPACE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014315 "Type definition '%s': The value '%s' of the "
14316 "facet 'whiteSpace' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000014317 name, facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014318 }
14319 ret = -1;
14320 }
14321 }
14322 default:
14323 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000014324 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014325 return (ret);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000014326}
14327
14328/**
Daniel Veillard4255d502002-04-16 15:50:10 +000014329 * xmlSchemaCheckDefaults:
14330 * @typeDecl: the schema type definition
14331 * @ctxt: the schema parser context
14332 *
14333 * Checks the default values types, especially for facets
14334 */
14335static void
14336xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014337 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000014338{
Daniel Veillard4255d502002-04-16 15:50:10 +000014339 if (name == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014340 name = typeDecl->name;
14341 /*
14342 * NOTE: It is intended to use the facets list, instead
14343 * of facetSet.
14344 */
14345 if (typeDecl->facets != NULL) {
14346 xmlSchemaFacetPtr facet = typeDecl->facets;
14347
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014348 /*
14349 * Temporarily assign the "schema" to the validation context
14350 * of the parser context. This is needed for NOTATION validation.
14351 */
14352 if (ctxt->vctxt == NULL) {
14353 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
14354 return;
14355 }
14356 ctxt->vctxt->schema = ctxt->schema;
14357
Daniel Veillard01fa6152004-06-29 17:04:39 +000014358 while (facet != NULL) {
14359 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
14360 facet = facet->next;
14361 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014362
14363 ctxt->vctxt->schema = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014364 }
Daniel Veillard4255d502002-04-16 15:50:10 +000014365}
14366
14367/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014368 * xmlSchemaGetCircModelGrDefRef:
14369 * @ctxtGr: the searched model group
14370 * @list: the list of model groups to be processed
14371 *
14372 * This one is intended to be used by
14373 * xmlSchemaCheckGroupDefCircular only.
14374 *
14375 * Returns the circular model group definition reference, otherwise NULL.
14376 */
14377static xmlSchemaTypePtr
14378xmlSchemaGetCircModelGrDefRef(xmlSchemaTypePtr ctxtGrDef,
14379 xmlSchemaTypePtr gr)
14380{
14381 xmlSchemaTypePtr circ = NULL;
14382 int marked;
14383 /*
14384 * We will search for an model group reference which
14385 * references the context model group definition.
14386 */
14387 while (gr != NULL) {
14388 if (((gr->type == XML_SCHEMA_TYPE_GROUP) ||
14389 (gr->type == XML_SCHEMA_TYPE_ALL) ||
14390 (gr->type == XML_SCHEMA_TYPE_SEQUENCE) ||
14391 (gr->type == XML_SCHEMA_TYPE_CHOICE)) &&
14392 (gr->subtypes != NULL)) {
14393 marked = 0;
14394 if ((gr->type == XML_SCHEMA_TYPE_GROUP) &&
14395 (gr->ref != NULL)) {
14396 if (gr->subtypes == ctxtGrDef)
14397 return (gr);
14398 else if (gr->subtypes->flags &
14399 XML_SCHEMAS_TYPE_MARKED) {
14400 gr = gr->next;
14401 continue;
14402 } else {
14403 /*
14404 * Mark to avoid infinite recursion on
14405 * circular references not yet examined.
14406 */
14407 gr->subtypes->flags |= XML_SCHEMAS_TYPE_MARKED;
14408 marked = 1;
14409 }
14410 if (gr->subtypes->subtypes != NULL)
14411 circ = xmlSchemaGetCircModelGrDefRef(ctxtGrDef,
14412 gr->subtypes->subtypes);
14413 /*
14414 * Unmark the visited model group definition.
14415 */
14416 if (marked)
14417 gr->subtypes->flags ^= XML_SCHEMAS_TYPE_MARKED;
14418 if (circ != NULL)
14419 return (circ);
14420 } else {
14421 circ = xmlSchemaGetCircModelGrDefRef(ctxtGrDef,
14422 (xmlSchemaTypePtr) gr->subtypes);
14423 if (circ != NULL)
14424 return (circ);
14425 }
14426
14427 }
14428 gr = gr->next;
14429 }
14430 return (NULL);
14431}
14432
14433/**
14434 * xmlSchemaCheckGroupDefCircular:
14435 * attrGr: the model group definition
14436 * @ctxt: the parser context
14437 * @name: the name
14438 *
14439 * Checks for circular references to model group definitions.
14440 */
14441static void
14442xmlSchemaCheckGroupDefCircular(xmlSchemaTypePtr modelGrDef,
14443 xmlSchemaParserCtxtPtr ctxt,
14444 const xmlChar * name ATTRIBUTE_UNUSED)
14445{
14446 /*
14447 * Schema Component Constraint: Model Group Correct
14448 * 2 Circular groups are disallowed. That is, within the {particles}
14449 * of a group there must not be at any depth a particle whose {term}
14450 * is the group itself.
14451 */
14452 /*
14453 * NOTE: "gr->subtypes" holds the referenced group.
14454 */
14455 if ((modelGrDef->type != XML_SCHEMA_TYPE_GROUP) ||
14456 ((modelGrDef->flags & XML_SCHEMAS_TYPE_GLOBAL) == 0) ||
14457 (modelGrDef->subtypes == NULL))
14458 return;
14459 else {
14460 xmlSchemaTypePtr circ;
14461
14462 circ = xmlSchemaGetCircModelGrDefRef(modelGrDef, modelGrDef->subtypes);
14463 if (circ != NULL) {
14464 /*
14465 * TODO: Report the referenced attr group as QName.
14466 */
14467 xmlSchemaPCustomErr(ctxt,
14468 XML_SCHEMAP_MG_PROPS_CORRECT_2,
14469 NULL, NULL, circ->node,
14470 "Circular reference to the model group definition '%s' "
14471 "defined", modelGrDef->name);
14472 /*
14473 * NOTE: We will cut the reference to avoid further
14474 * confusion of the processor.
14475 * TODO: SPEC: Does the spec define how to process here?
14476 */
14477 circ->subtypes = NULL;
14478 }
14479 }
14480}
14481
14482
14483/**
14484 * xmlSchemaGetCircAttrGrRef:
14485 * @ctxtGr: the searched attribute group
14486 * @attr: the current attribute list to be processed
14487 *
14488 * This one is intended to be used by
14489 * xmlSchemaCheckSRCAttributeGroupCircular only.
14490 *
14491 * Returns the circular attribute grou reference, otherwise NULL.
14492 */
14493static xmlSchemaAttributeGroupPtr
14494xmlSchemaGetCircAttrGrRef(xmlSchemaAttributeGroupPtr ctxtGr,
14495 xmlSchemaAttributePtr attr)
14496{
14497 xmlSchemaAttributeGroupPtr circ = NULL, gr;
14498 int marked;
14499 /*
14500 * We will search for an attribute group reference which
14501 * references the context attribute group.
14502 */
14503 while (attr != NULL) {
14504 marked = 0;
14505 if (attr->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
14506 gr = (xmlSchemaAttributeGroupPtr) attr;
14507 if (gr->refItem != NULL) {
14508 if (gr->refItem == ctxtGr)
14509 return (gr);
14510 else if (gr->refItem->flags &
14511 XML_SCHEMAS_ATTRGROUP_MARKED) {
14512 attr = attr->next;
14513 continue;
14514 } else {
14515 /*
14516 * Mark as visited to avoid infinite recursion on
14517 * circular references not yet examined.
14518 */
14519 gr->refItem->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
14520 marked = 1;
14521 }
14522 }
14523 if (gr->attributes != NULL)
14524 circ = xmlSchemaGetCircAttrGrRef(ctxtGr, gr->attributes);
14525 /*
14526 * Unmark the visited group's attributes.
14527 */
14528 if (marked)
14529 gr->refItem->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
14530 if (circ != NULL)
14531 return (circ);
14532 }
14533 attr = attr->next;
14534 }
14535 return (NULL);
14536}
14537
14538/**
14539 * xmlSchemaCheckSRCAttributeGroupCircular:
14540 * attrGr: the attribute group definition
14541 * @ctxt: the parser context
14542 * @name: the name
14543 *
14544 * Checks for circular references of attribute groups.
14545 */
14546static void
14547xmlSchemaCheckAttributeGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
14548 xmlSchemaParserCtxtPtr ctxt,
14549 const xmlChar * name ATTRIBUTE_UNUSED)
14550{
14551 /*
14552 * Schema Representation Constraint:
14553 * Attribute Group Definition Representation OK
14554 * 3 Circular group reference is disallowed outside <redefine>.
14555 * That is, unless this element information item's parent is
14556 * <redefine>, then among the [children], if any, there must
14557 * not be an <attributeGroup> with ref [attribute] which resolves
14558 * to the component corresponding to this <attributeGroup>. Indirect
14559 * circularity is also ruled out. That is, when QName resolution
14560 * (Schema Document) (§3.15.3) is applied to a ·QName· arising from
14561 * any <attributeGroup>s with a ref [attribute] among the [children],
14562 * it must not be the case that a ·QName· is encountered at any depth
14563 * which resolves to the component corresponding to this <attributeGroup>.
14564 */
14565 /*
14566 * Only global components can be referenced.
14567 */
14568 if (((attrGr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) == 0) ||
14569 (attrGr->attributes == NULL))
14570 return;
14571 else {
14572 xmlSchemaAttributeGroupPtr circ;
14573
14574 circ = xmlSchemaGetCircAttrGrRef(attrGr, attrGr->attributes);
14575 if (circ != NULL) {
14576 /*
14577 * TODO: Report the referenced attr group as QName.
14578 */
14579 xmlSchemaPCustomErr(ctxt,
14580 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
14581 NULL, NULL, circ->node,
14582 "Circular reference to the attribute group '%s' "
14583 "defined", attrGr->name);
14584 /*
14585 * NOTE: We will cut the reference to avoid further
14586 * confusion of the processor.
14587 * BADSPEC: The spec should define how to process in this case.
14588 */
14589 circ->attributes = NULL;
14590 circ->refItem = NULL;
14591 }
14592 }
14593}
14594
14595/**
Daniel Veillard13e04c62002-04-23 17:51:29 +000014596 * xmlSchemaAttrGrpFixup:
14597 * @attrgrpDecl: the schema attribute definition
14598 * @ctxt: the schema parser context
14599 * @name: the attribute name
14600 *
14601 * Fixes finish doing the computations on the attributes definitions
14602 */
14603static void
Daniel Veillard3646d642004-06-02 19:19:14 +000014604xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014605 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +000014606{
14607 if (name == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000014608 name = attrgrp->name;
14609 if (attrgrp->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014610 return;
Daniel Veillard3646d642004-06-02 19:19:14 +000014611 if (attrgrp->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014612 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +000014613
Daniel Veillardc0826a72004-08-10 14:17:33 +000014614 ref = xmlSchemaGetAttributeGroup(ctxt->schema, attrgrp->ref,
14615 attrgrp->refNs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014616 if (ref == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014617 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014618 XML_SCHEMAP_SRC_RESOLVE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014619 NULL, (xmlSchemaTypePtr) attrgrp, attrgrp->node,
14620 "ref", attrgrp->ref, attrgrp->refNs,
14621 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014622 return;
14623 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014624 attrgrp->refItem = ref;
14625 /*
14626 * Check for self reference!
14627 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014628 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000014629 attrgrp->attributes = ref->attributes;
14630 attrgrp->attributeWildcard = ref->attributeWildcard;
14631 }
Daniel Veillard13e04c62002-04-23 17:51:29 +000014632}
14633
14634/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014635 * xmlSchemaAttrCheckValConstr:
14636 * @item: an schema attribute declaration/use
14637 * @ctxt: a schema parser context
14638 * @name: the name of the attribute
14639 *
14640 * Validates the value constraints of an attribute declaration/use.
Daniel Veillard4255d502002-04-16 15:50:10 +000014641 *
14642 * Fixes finish doing the computations on the attributes definitions
14643 */
14644static void
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014645xmlSchemaCheckAttrValConstr(xmlSchemaAttributePtr item,
14646 xmlSchemaParserCtxtPtr ctxt,
14647 const xmlChar * name ATTRIBUTE_UNUSED)
14648{
14649
14650 /*
14651 * a-props-correct
14652 * Schema Component Constraint: Attribute Declaration Properties Correct
14653 *
14654 * 2 if there is a {value constraint}, the canonical lexical
14655 * representation of its value must be ·valid· with respect
14656 * to the {type definition} as defined in String Valid (§3.14.4).
14657 */
14658
14659 if (item->defValue != NULL) {
14660 int ret;
14661 xmlNodePtr node;
14662 xmlSchemaTypePtr type;
14663
14664 if (item->subtypes == NULL) {
14665 xmlSchemaPErr(ctxt, item->node,
14666 XML_SCHEMAP_INTERNAL,
14667 "Internal error: xmlSchemaCheckAttrValConstr, "
14668 "type is missing... skipping validation of "
14669 "value constraint", NULL, NULL);
14670 return;
14671 }
14672
14673 /*
14674 * TODO: Try to avoid creating a new context.
14675 * TODO: This all is not very performant.
14676 */
14677 type = item->subtypes;
14678 /*
14679 * Ensure there's validation context.
14680 */
14681 if (ctxt->vctxt == NULL) {
14682 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1) {
14683 xmlSchemaPErr(ctxt, item->node,
14684 XML_SCHEMAP_INTERNAL,
14685 "Internal error: xmlSchemaCheckAttrValConstr, "
14686 "creating a new validation context.\n",
14687 NULL, NULL);
14688 return;
14689 }
14690 }
14691
14692 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
14693 node = (xmlNodePtr) xmlHasProp(item->node, BAD_CAST "fixed");
14694 else
14695 node = (xmlNodePtr) xmlHasProp(item->node, BAD_CAST "default");
14696 ctxt->vctxt->node = node;
14697 ctxt->vctxt->cur = NULL;
14698 /*
14699 * NOTE: This call does not check the content nodes,
14700 * since they are not available:
14701 * facet->node is just the node holding the facet
14702 * definition, *not* the attribute holding the *value*
14703 * of the facet.
14704 */
14705 ret = xmlSchemaValidateSimpleTypeValue(ctxt->vctxt, type,
14706 item->defValue, 0, 1, 1, 0);
14707 if (ret == 0) {
14708 /*
14709 * Store the computed value.
14710 */
14711 item->defVal = ctxt->vctxt->value;
14712 ctxt->vctxt->value = NULL;
14713 } else if (ret > 0) {
14714 if (ctxt != NULL) {
14715 xmlSchemaPSimpleTypeErr(ctxt,
14716 XML_SCHEMAP_A_PROPS_CORRECT_2,
14717 NULL, NULL, node,
14718 type, NULL, item->defValue,
14719 NULL, NULL, NULL);
14720 }
14721 } else if (ret < 0) {
14722 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
14723 NULL, NULL, node,
14724 "Internal error: xmlSchemaAttrCheckValConstr, "
14725 "failed to validate the value constraint of the "
14726 "attribute decl/use against the type '%s'",
14727 type->name);
14728 }
14729 }
14730}
14731
14732#if 0 /* Not used yet. */
14733static int
14734xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
14735 xmlSchemaElementPtr edecl)
14736{
14737 /*
14738 * TODO: 1 The values of the properties of an element declaration must be as
14739 * described in the property tableau in The Element Declaration Schema
14740 * Component (§3.3.1), modulo the impact of Missing Sub-components (§5.3).
14741 */
14742 /*
14743 * 2 If there is a {value constraint}, the canonical lexical
14744 * representation of its value must be ·valid· with respect to the {type
14745 * definition} as defined in Element Default Valid (Immediate) (§3.3.6).
14746 *
14747 * NOTE: This is done in xmlSchemaCheckElemValConstr.
14748 */
14749 /*
14750 * 3 If there is a non-·absent· {substitution group affiliation},
14751 * then {scope} must be global.
14752 *
14753 * NOTE: This is done in xmlSchemaParseElement.
14754 * TODO: Move it to this layer here.
14755 */
14756 /*
14757 * TODO: 4 If there is a {substitution group affiliation}, the {type definition}
14758 * of the element declaration must be validly derived from the {type
14759 * definition} of the {substitution group affiliation}, given the value
14760 * of the {substitution group exclusions} of the {substitution group
14761 * affiliation}, as defined in Type Derivation OK (Complex) (§3.4.6)
14762 * (if the {type definition} is complex) or as defined in
14763 * Type Derivation OK (Simple) (§3.14.6) (if the {type definition} is
14764 * simple).
14765 */
14766 /*
14767 * TODO: 5 If the {type definition} or {type definition}'s {content type}
14768 * is or is derived from ID then there must not be a {value constraint}.
14769 * Note: The use of ID as a type definition for elements goes beyond
14770 * XML 1.0, and should be avoided if backwards compatibility is desired
14771 */
14772 /*
14773 * TODO: 6 Circular substitution groups are disallowed. That is, it must not
14774 * be possible to return to an element declaration by repeatedly following
14775 * the {substitution group affiliation} property.
14776 */
14777}
14778#endif
14779
14780/**
14781 * xmlSchemaCheckElemValConstr:
14782 * @item: an schema element declaration/particle
14783 * @ctxt: a schema parser context
14784 * @name: the name of the attribute
14785 *
14786 * Validates the value constraints of an element declaration.
14787 *
14788 * Fixes finish doing the computations on the element declarations.
14789 */
14790static void
14791xmlSchemaCheckElemValConstr(xmlSchemaElementPtr decl,
14792 xmlSchemaParserCtxtPtr ctxt,
14793 const xmlChar * name ATTRIBUTE_UNUSED)
14794{
14795 if (decl->value != NULL) {
14796 int ret;
14797 xmlNodePtr node = NULL;
14798 xmlSchemaTypePtr type;
14799
14800 /*
14801 * 2 If there is a {value constraint}, the canonical lexical
14802 * representation of its value must be ·valid· with respect to the {type
14803 * definition} as defined in Element Default Valid (Immediate) (§3.3.6).
14804 */
14805 if (decl->subtypes == NULL) {
14806 xmlSchemaPErr(ctxt, decl->node,
14807 XML_SCHEMAP_INTERNAL,
14808 "Internal error: xmlSchemaCheckElemValConstr, "
14809 "type is missing... skipping validation of "
14810 "the value constraint", NULL, NULL);
14811 return;
14812 }
14813 /*
14814 * Ensure there's a validation context.
14815 */
14816 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
14817 return;
14818
14819 type = decl->subtypes;
14820
14821 if (decl->node != NULL) {
14822 if (decl->flags & XML_SCHEMAS_ELEM_FIXED)
14823 node = (xmlNodePtr) xmlHasProp(decl->node, BAD_CAST "fixed");
14824 else
14825 node = (xmlNodePtr) xmlHasProp(decl->node, BAD_CAST "default");
14826 }
14827 ctxt->vctxt->node = node;
14828 ctxt->vctxt->cur = NULL;
14829 ret = xmlSchemaCheckCOSValidDefault(ctxt, ctxt->vctxt, type, decl->value,
14830 node);
14831 if (ret == 0) {
14832 /*
14833 * Consume the computed value.
14834 */
14835 decl->defVal = ctxt->vctxt->value;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000014836 ctxt->vctxt->value = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014837 } else if (ret < 0) {
14838 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
14839 NULL, NULL, node,
14840 "Internal error: xmlSchemaElemCheckValConstr, "
14841 "failed to validate the value constraint of the "
14842 "element declaration '%s'",
14843 decl->name);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000014844 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014845 }
14846}
14847
14848/**
14849 * xmlSchemaAttrFixup:
14850 * @item: an schema attribute declaration/use.
14851 * @ctxt: a schema parser context
14852 * @name: the name of the attribute
14853 *
14854 * Fixes finish doing the computations on attribute declarations/uses.
14855 */
14856static void
14857xmlSchemaAttrFixup(xmlSchemaAttributePtr item,
14858 xmlSchemaParserCtxtPtr ctxt,
14859 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000014860{
Daniel Veillardc0826a72004-08-10 14:17:33 +000014861 /*
14862 * TODO: If including this is done twice (!) for every attribute.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014863 * -> Hmm, check if this is still done.
Daniel Veillardc0826a72004-08-10 14:17:33 +000014864 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014865 /*
14866 * The simple type definition corresponding to the <simpleType> element
14867 * information item in the [children], if present, otherwise the simple
14868 * type definition ·resolved· to by the ·actual value· of the type
14869 * [attribute], if present, otherwise the ·simple ur-type definition·.
14870 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014871 if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
Daniel Veillardc0826a72004-08-10 14:17:33 +000014872 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014873 item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
14874 if (item->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014875 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014876 if (item->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014877 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000014878
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014879 type = xmlSchemaGetType(ctxt->schema, item->typeName,
14880 item->typeNs);
14881 if ((type == NULL) || (! IS_SIMPLE_TYPE(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014882 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014883 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014884 NULL, (xmlSchemaTypePtr) item, item->node,
14885 "type", item->typeName, item->typeNs,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014886 XML_SCHEMA_TYPE_SIMPLE, NULL);
14887 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014888 item->subtypes = type;
14889
14890 } else if (item->ref != NULL) {
14891 xmlSchemaAttributePtr decl;
Daniel Veillard4255d502002-04-16 15:50:10 +000014892
Daniel Veillardc0826a72004-08-10 14:17:33 +000014893 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014894 * We have an attribute use here; assign the referenced
14895 * attribute declaration.
14896 */
14897 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000014898 * TODO: Evaluate, what errors could occur if the declaration is not
14899 * found. It might be possible that the "typefixup" might crash if
14900 * no ref declaration was found.
14901 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014902 decl = xmlSchemaGetAttribute(ctxt->schema, item->ref, item->refNs);
14903 if (decl == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014904 xmlSchemaPResCompAttrErr(ctxt,
14905 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014906 NULL, (xmlSchemaTypePtr) item, item->node,
14907 "ref", item->ref, item->refNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014908 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014909 return;
14910 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014911 item->refDecl = decl;
14912 xmlSchemaAttrFixup(decl, ctxt, NULL);
14913
14914 item->subtypes = decl->subtypes;
14915 /*
14916 * Attribute Use Correct
14917 * au-props-correct.2: If the {attribute declaration} has a fixed
14918 * {value constraint}, then if the attribute use itself has a
14919 * {value constraint}, it must also be fixed and its value must match
14920 * that of the {attribute declaration}'s {value constraint}.
14921 */
14922 if ((decl->flags & XML_SCHEMAS_ATTR_FIXED) &&
14923 (item->defValue != NULL)) {
14924 if (((item->flags & XML_SCHEMAS_ATTR_FIXED) == 0) ||
14925 (!xmlStrEqual(item->defValue, decl->defValue))) {
14926 xmlSchemaPCustomErr(ctxt,
14927 XML_SCHEMAP_AU_PROPS_CORRECT_2,
14928 NULL, NULL, item->node,
14929 "The value constraint must be fixed "
14930 "and match the referenced attribute "
14931 "declarations's value constraint '%s'",
14932 decl->defValue);
14933 }
14934 /*
14935 * FUTURE: One should change the values of the attr. use
14936 * if ever validation should be attempted even if the
14937 * schema itself was not fully valid.
14938 */
14939 }
Daniel Veillard3646d642004-06-02 19:19:14 +000014940 } else {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014941 item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
14942 }
Daniel Veillard4255d502002-04-16 15:50:10 +000014943}
14944
14945/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000014946 * xmlSchemaResolveIDCKeyRef:
14947 * @idc: the identity-constraint definition
14948 * @ctxt: the schema parser context
14949 * @name: the attribute name
14950 *
14951 * Resolve keyRef references to key/unique IDCs.
14952 */
14953static void
14954xmlSchemaResolveIDCKeyRef(xmlSchemaIDCPtr idc,
14955 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000014956 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000014957{
14958 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
14959 return;
14960 if (idc->ref->name != NULL) {
14961 idc->ref->item = (xmlSchemaBasicItemPtr) xmlHashLookup2(
14962 ctxt->schema->idcDef,
14963 idc->ref->name,
14964 idc->ref->targetNamespace);
14965 if (idc->ref->item == NULL) {
14966 /*
14967 * TODO: It is actually not an error to fail to resolve.
14968 */
14969 xmlSchemaPResCompAttrErr(ctxt,
14970 XML_SCHEMAP_SRC_RESOLVE,
14971 NULL, (xmlSchemaTypePtr) idc, idc->node,
14972 "refer", idc->ref->name,
14973 idc->ref->targetNamespace,
14974 XML_SCHEMA_TYPE_IDC_KEYREF, NULL);
14975 return;
14976 }
14977 }
14978}
14979
14980/**
Daniel Veillard4255d502002-04-16 15:50:10 +000014981 * xmlSchemaParse:
14982 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000014983 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000014984 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +000014985 * XML Shema struture which can be used to validate instances.
14986 * *WARNING* this interface is highly subject to change
14987 *
14988 * Returns the internal XML Schema structure built from the resource or
14989 * NULL in case of error
14990 */
14991xmlSchemaPtr
14992xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
14993{
14994 xmlSchemaPtr ret = NULL;
14995 xmlDocPtr doc;
Daniel Veillardbd2904b2003-11-25 15:38:59 +000014996 xmlNodePtr root;
Daniel Veillarddda22c12004-01-24 08:31:30 +000014997 int preserve = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000014998
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014999 /*
15000 * This one is used if the schema to be parsed was specified via
15001 * the API; i.e. not automatically by the validated instance document.
15002 */
15003
Daniel Veillard4255d502002-04-16 15:50:10 +000015004 xmlSchemaInitTypes();
15005
Daniel Veillard6045c902002-10-09 21:13:59 +000015006 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +000015007 return (NULL);
15008
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000015009 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000015010 ctxt->counter = 0;
15011 ctxt->container = NULL;
15012
15013 /*
15014 * First step is to parse the input document into an DOM/Infoset
15015 */
Daniel Veillard6045c902002-10-09 21:13:59 +000015016 if (ctxt->URL != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000015017 doc = xmlReadFile((const char *) ctxt->URL, NULL,
15018 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015019 if (doc == NULL) {
15020 xmlSchemaPErr(ctxt, NULL,
15021 XML_SCHEMAP_FAILED_LOAD,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015022 "xmlSchemaParse: could not load '%s'.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015023 ctxt->URL, NULL);
15024 return (NULL);
15025 }
Daniel Veillard6045c902002-10-09 21:13:59 +000015026 } else if (ctxt->buffer != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000015027 doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
15028 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015029 if (doc == NULL) {
15030 xmlSchemaPErr(ctxt, NULL,
15031 XML_SCHEMAP_FAILED_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015032 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015033 NULL, NULL);
15034 return (NULL);
15035 }
15036 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard65765282004-01-08 16:59:30 +000015037 ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
Daniel Veillard9d751502003-10-29 13:21:47 +000015038 } else if (ctxt->doc != NULL) {
15039 doc = ctxt->doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000015040 preserve = 1;
Daniel Veillard6045c902002-10-09 21:13:59 +000015041 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015042 xmlSchemaPErr(ctxt, NULL,
15043 XML_SCHEMAP_NOTHING_TO_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015044 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015045 NULL, NULL);
15046 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000015047 }
15048
15049 /*
15050 * Then extract the root and Schema parse it
15051 */
15052 root = xmlDocGetRootElement(doc);
15053 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015054 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
15055 XML_SCHEMAP_NOROOT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015056 "The schema has no document element.\n", NULL, NULL);
Daniel Veillarddda22c12004-01-24 08:31:30 +000015057 if (!preserve) {
15058 xmlFreeDoc(doc);
15059 }
Daniel Veillard4255d502002-04-16 15:50:10 +000015060 return (NULL);
15061 }
15062
15063 /*
15064 * Remove all the blank text nodes
15065 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +000015066 xmlSchemaCleanupDoc(ctxt, root);
Daniel Veillard4255d502002-04-16 15:50:10 +000015067
15068 /*
15069 * Then do the parsing for good
15070 */
15071 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillard1d913862003-11-21 00:28:39 +000015072 if (ret == NULL) {
Daniel Veillarddda22c12004-01-24 08:31:30 +000015073 if (!preserve) {
15074 xmlFreeDoc(doc);
15075 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015076 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +000015077 }
Daniel Veillard4255d502002-04-16 15:50:10 +000015078 ret->doc = doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000015079 ret->preserve = preserve;
Daniel Veillard4255d502002-04-16 15:50:10 +000015080 ctxt->schema = ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015081 ctxt->ctxtType = NULL;
15082 ctxt->parentItem = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000015083 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +000015084 * Then fixup all attributes declarations
15085 */
15086 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
15087
15088 /*
15089 * Then fixup all attributes group declarations
15090 */
15091 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
15092 ctxt);
15093
15094 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015095 * Resolve identity-constraint keyRefs.
15096 */
15097 xmlHashScan(ret->idcDef, (xmlHashScanner) xmlSchemaResolveIDCKeyRef, ctxt);
15098
15099 /*
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015100 * Check attribute groups for circular references.
15101 */
15102 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner)
15103 xmlSchemaCheckAttributeGroupCircular, ctxt);
15104
15105 /*
15106 * Then fixup all model group definitions.
15107 */
15108 xmlHashScan(ret->groupDecl, (xmlHashScanner) xmlSchemaGroupDefFixup, ctxt);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015109
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015110 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000015111 * Then fix references of element declaration; apply constraints.
15112 */
15113 xmlHashScanFull(ret->elemDecl,
15114 (xmlHashScannerFull) xmlSchemaRefFixupCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000015115
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000015116 /*
15117 * We will stop here if the schema was not valid to avoid internal errors
15118 * on missing sub-components. This is not conforming to the spec, since it
15119 * allows missing components, but it might make further processing crash.
15120 * So see it as a very strict handling, which might be made more lax in the
15121 * future.
15122 */
15123 if (ctxt->nberrors != 0)
15124 goto exit;
15125 /*
15126 * Then fixup all types properties
15127 */
15128 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015129 /*
15130 * Check model groups defnitions for circular references.
15131 */
15132 xmlHashScan(ret->groupDecl, (xmlHashScanner)
15133 xmlSchemaCheckGroupDefCircular, ctxt);
15134
Daniel Veillard4255d502002-04-16 15:50:10 +000015135 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015136 * Then build the content model for all complex types
Daniel Veillard4255d502002-04-16 15:50:10 +000015137 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015138 xmlHashScan(ret->typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015139 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000015140
15141 /*
15142 * Then check the defaults part of the type like facets values
15143 */
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000015144 /* OLD: xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaCheckDefaults, ctxt); */
Daniel Veillard4255d502002-04-16 15:50:10 +000015145
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015146 /*
15147 * Validate the value constraint of attribute declarations/uses.
15148 */
15149 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaCheckAttrValConstr, ctxt);
15150
15151 /*
15152 * Validate the value constraint of element declarations.
15153 */
15154 xmlHashScan(ret->elemDecl, (xmlHashScanner) xmlSchemaCheckElemValConstr, ctxt);
15155
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000015156exit:
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000015157 if (ctxt->nberrors != 0) {
15158 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015159 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000015160 }
Daniel Veillard4255d502002-04-16 15:50:10 +000015161 return (ret);
15162}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015163
Daniel Veillard4255d502002-04-16 15:50:10 +000015164/**
Daniel Veillard01c13b52002-12-10 15:19:08 +000015165 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +000015166 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +000015167 * @err: the error callback
15168 * @warn: the warning callback
15169 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +000015170 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000015171 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000015172 */
15173void
15174xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015175 xmlSchemaValidityErrorFunc err,
15176 xmlSchemaValidityWarningFunc warn, void *ctx)
15177{
Daniel Veillard4255d502002-04-16 15:50:10 +000015178 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015179 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000015180 ctxt->error = err;
15181 ctxt->warning = warn;
15182 ctxt->userData = ctx;
15183}
15184
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000015185/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000015186 * xmlSchemaGetParserErrors:
15187 * @ctxt: a XMl-Schema parser context
15188 * @err: the error callback result
15189 * @warn: the warning callback result
15190 * @ctx: contextual data for the callbacks result
15191 *
15192 * Get the callback information used to handle errors for a parser context
15193 *
15194 * Returns -1 in case of failure, 0 otherwise
15195 */
15196int
15197xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
15198 xmlSchemaValidityErrorFunc * err,
15199 xmlSchemaValidityWarningFunc * warn, void **ctx)
15200{
15201 if (ctxt == NULL)
15202 return(-1);
15203 if (err != NULL)
15204 *err = ctxt->error;
15205 if (warn != NULL)
15206 *warn = ctxt->warning;
15207 if (ctx != NULL)
15208 *ctx = ctxt->userData;
15209 return(0);
15210}
15211
15212/**
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000015213 * xmlSchemaFacetTypeToString:
15214 * @type: the facet type
15215 *
15216 * Convert the xmlSchemaTypeType to a char string.
15217 *
15218 * Returns the char string representation of the facet type if the
15219 * type is a facet and an "Internal Error" string otherwise.
15220 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000015221static const xmlChar *
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000015222xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
15223{
15224 switch (type) {
15225 case XML_SCHEMA_FACET_PATTERN:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000015226 return (BAD_CAST "pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015227 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000015228 return (BAD_CAST "maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015229 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000015230 return (BAD_CAST "maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015231 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000015232 return (BAD_CAST "minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015233 case XML_SCHEMA_FACET_MININCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000015234 return (BAD_CAST "minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015235 case XML_SCHEMA_FACET_WHITESPACE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000015236 return (BAD_CAST "whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015237 case XML_SCHEMA_FACET_ENUMERATION:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000015238 return (BAD_CAST "enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015239 case XML_SCHEMA_FACET_LENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000015240 return (BAD_CAST "length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015241 case XML_SCHEMA_FACET_MAXLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000015242 return (BAD_CAST "maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015243 case XML_SCHEMA_FACET_MINLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000015244 return (BAD_CAST "minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015245 case XML_SCHEMA_FACET_TOTALDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000015246 return (BAD_CAST "totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015247 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000015248 return (BAD_CAST "fractionDigits");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000015249 default:
15250 break;
15251 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000015252 return (BAD_CAST "Internal Error");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000015253}
15254
Daniel Veillardc0826a72004-08-10 14:17:33 +000015255static int
15256xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
15257{
15258 xmlSchemaTypePtr anc;
15259
15260 /*
15261 * The normalization type can be changed only for types which are derived
15262 * from xsd:string.
15263 */
15264 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000015265 if (type->builtInType == XML_SCHEMAS_STRING)
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000015266 return(XML_SCHEMAS_FACET_PRESERVE);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000015267 else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000015268 return(XML_SCHEMAS_FACET_REPLACE);
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000015269 else if (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)
15270 /*
15271 * Note that we assume a whitespace of preserve for anySimpleType.
15272 */
15273 return(XML_SCHEMAS_FACET_PRESERVE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015274 else {
15275 /*
15276 * For all ·atomic· datatypes other than string (and types ·derived·
15277 * by ·restriction· from it) the value of whiteSpace is fixed to
15278 * collapse
15279 */
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000015280 return(XML_SCHEMAS_FACET_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015281 }
15282 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
15283 /*
15284 * For list types the facet "whiteSpace" is fixed to "collapse".
15285 */
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000015286 return (XML_SCHEMAS_FACET_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015287 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000015288 return (XML_SCHEMAS_FACET_UNKNOWN);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015289 } else if (type->facetSet != NULL) {
15290 xmlSchemaTypePtr anyST;
15291 xmlSchemaFacetLinkPtr lin;
15292
15293 /*
15294 * Atomic types.
15295 */
15296 anyST = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
15297 anc = type->baseType;
15298 do {
15299 /*
15300 * For all ·atomic· datatypes other than string (and types ·derived·
15301 * by ·restriction· from it) the value of whiteSpace is fixed to
15302 * collapse
15303 */
15304 if ((anc->type == XML_SCHEMA_TYPE_BASIC) &&
15305 (anc->builtInType == XML_SCHEMAS_STRING)) {
15306
15307 lin = type->facetSet;
15308 do {
15309 if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000015310 return(lin->facet->whitespace);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015311 break;
15312 }
15313 lin = lin->next;
15314 } while (lin != NULL);
15315 break;
15316 }
15317 anc = anc->baseType;
15318 } while (anc != anyST);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000015319 return (XML_SCHEMAS_FACET_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015320 }
15321 return (-1);
15322}
15323
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000015324/**
Daniel Veillard377e1a92004-04-16 16:30:05 +000015325 * xmlSchemaValidateFacetsInternal:
15326 * @ctxt: a schema validation context
Daniel Veillardc0826a72004-08-10 14:17:33 +000015327 * @type: the type holding the facets
Daniel Veillard377e1a92004-04-16 16:30:05 +000015328 * @facets: the list of facets to check
15329 * @value: the lexical repr of the value to validate
15330 * @val: the precomputed value
William M. Bracke7091952004-05-11 15:09:58 +000015331 * @fireErrors: if 0, only internal errors will be fired;
15332 * otherwise all errors will be fired.
Daniel Veillard377e1a92004-04-16 16:30:05 +000015333 *
15334 * Check a value against all facet conditions
15335 *
15336 * Returns 0 if the element is schemas valid, a positive error code
15337 * number otherwise and -1 in case of internal or API error.
15338 */
15339static int
15340xmlSchemaValidateFacetsInternal(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015341 xmlSchemaTypePtr type,
15342 const xmlChar * value,
15343 unsigned long length,
15344 int fireErrors)
Daniel Veillard377e1a92004-04-16 16:30:05 +000015345{
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000015346 int ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015347 xmlNodePtr node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015348 xmlSchemaTypePtr biType; /* The build-in type. */
15349 xmlSchemaTypePtr tmpType;
15350 xmlSchemaFacetLinkPtr facetLink;
Daniel Veillardc7e3cc42004-09-28 12:33:52 +000015351 int retFacet;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015352 xmlSchemaFacetPtr facet;
15353 unsigned long len = 0;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000015354
Daniel Veillardc0826a72004-08-10 14:17:33 +000015355#ifdef DEBUG_UNION_VALIDATION
15356 printf("Facets of type: '%s'\n", (const char *) type->name);
15357 printf(" fireErrors: %d\n", fireErrors);
15358#endif
15359
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015360 node = ctxt->node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015361 /*
15362 * NOTE: Do not jump away, if the facetSet of the given type is
15363 * empty: until now, "pattern" facets of the *base types* need to
15364 * be checked as well.
15365 */
15366 biType = type->baseType;
15367 while ((biType != NULL) && (biType->type != XML_SCHEMA_TYPE_BASIC))
15368 biType = biType->baseType;
15369 if (biType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015370 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015371 "Internal error: xmlSchemaValidateFacetsInternal, "
15372 "the base type axis of the given type '%s' does not resolve to "
15373 "a built-in type.\n",
15374 type->name, NULL);
15375 return (-1);
15376 }
15377
15378 if (type->facetSet != NULL) {
15379 facetLink = type->facetSet;
15380 while (facetLink != NULL) {
15381 facet = facetLink->facet;
15382 /*
15383 * Skip the pattern "whiteSpace": it is used to
15384 * format the character content beforehand.
15385 */
15386 switch (facet->type) {
15387 case XML_SCHEMA_FACET_WHITESPACE:
15388 case XML_SCHEMA_FACET_PATTERN:
15389 case XML_SCHEMA_FACET_ENUMERATION:
15390 break;
15391 case XML_SCHEMA_FACET_LENGTH:
15392 case XML_SCHEMA_FACET_MINLENGTH:
15393 case XML_SCHEMA_FACET_MAXLENGTH:
15394 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
15395 ret = xmlSchemaValidateListSimpleTypeFacet(facet,
15396 value, length, 0);
15397 len = length;
15398 } else
15399 ret = xmlSchemaValidateLengthFacet(biType, facet,
15400 value, ctxt->value, &len);
15401 break;
15402 default:
15403 ret = xmlSchemaValidateFacet(biType, facet, value,
15404 ctxt->value);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015405 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000015406 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015407 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015408 "Internal error: xmlSchemaValidateFacetsInternal, "
15409 "validating facet of type '%s'.\n",
15410 type->name, NULL);
15411 break;
15412 } else if ((ret > 0) && (fireErrors)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015413 xmlSchemaVFacetErr(ctxt, ret, node, value, len,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015414 type, facet, NULL, NULL, NULL, NULL);
15415 }
15416
15417 facetLink = facetLink->next;
15418 }
15419 if (ret >= 0) {
15420 /*
15421 * Process enumerations.
15422 */
15423 retFacet = 0;
15424 facetLink = type->facetSet;
15425 while (facetLink != NULL) {
15426 if (facetLink->facet->type == XML_SCHEMA_FACET_ENUMERATION) {
15427 retFacet = xmlSchemaValidateFacet(biType, facetLink->facet,
15428 value, ctxt->value);
15429 if (retFacet <= 0)
15430 break;
15431 }
15432 facetLink = facetLink->next;
15433 }
15434 if (retFacet > 0) {
15435 ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
15436 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015437 xmlSchemaVFacetErr(ctxt, ret, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015438 value, 0, type, NULL, NULL, NULL, NULL, NULL);
15439 } else if (retFacet < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015440 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015441 "Internal error: xmlSchemaValidateFacetsInternal, "
15442 "validating facet of type '%s'.\n",
15443 BAD_CAST "enumeration", NULL);
15444 ret = -1;
15445 }
15446 }
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000015447 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000015448 if (ret >= 0) {
15449 /*
15450 * Process patters. Pattern facets are ORed at type level
15451 * and ANDed if derived. Walk the base type axis.
15452 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000015453 tmpType = type;
15454 facet = NULL;
15455 do {
15456 retFacet = 0;
15457 for (facetLink = tmpType->facetSet; facetLink != NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015458 facetLink = facetLink->next) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015459 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
15460 continue;
15461 retFacet = xmlSchemaValidateFacet(biType, facetLink->facet,
15462 value, ctxt->value);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015463 if (retFacet == 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +000015464 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015465 else if (retFacet < 0) {
15466 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
15467 "Internal error: xmlSchemaValidateFacetsInternal, "
15468 "validating 'pattern' facet '%s' of type '%s'.\n",
15469 facetLink->facet->value, tmpType->name);
15470 ret = -1;
15471 break;
15472 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +000015473 /* Save the last non-validating facet. */
15474 facet = facetLink->facet;
15475 }
15476 if (retFacet != 0)
15477 break;
15478 tmpType = tmpType->baseType;
15479 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015480 if (retFacet > 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015481 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
15482 if (fireErrors) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015483 xmlSchemaVFacetErr(ctxt, ret, node, value, 0, type, facet,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015484 NULL, NULL, NULL, NULL);
15485 }
15486 }
15487 }
15488
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000015489 return (ret);
15490}
15491
Daniel Veillard4255d502002-04-16 15:50:10 +000015492/************************************************************************
15493 * *
15494 * Simple type validation *
15495 * *
15496 ************************************************************************/
Daniel Veillard377e1a92004-04-16 16:30:05 +000015497
Daniel Veillard4255d502002-04-16 15:50:10 +000015498
15499/************************************************************************
15500 * *
15501 * DOM Validation code *
15502 * *
15503 ************************************************************************/
15504
Daniel Veillard4255d502002-04-16 15:50:10 +000015505static int xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015506 xmlNodePtr elem,
Daniel Veillard3646d642004-06-02 19:19:14 +000015507 xmlSchemaTypePtr type);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015508static int xmlSchemaValidateElementByType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015509 xmlSchemaTypePtr type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000015510 int isNil,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015511 int valSimpleContent);
Daniel Veillard4255d502002-04-16 15:50:10 +000015512
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015513static void xmlSchemaBeginElement(xmlSchemaValidCtxtPtr vctxt);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000015514static int xmlSchemaEndElement(xmlSchemaValidCtxtPtr vctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015515
15516#ifdef ELEM_INFO_ENABLED
15517/**
15518 * xmlSchemaGetFreshElemInfo:
15519 * @vctxt: the schema validation context
15520 *
15521 * Creates/reuses and initializes the element info item for
15522 * the currect tree depth.
15523 *
15524 * Returns the element info item or NULL on API or internal errors.
15525 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000015526static xmlSchemaNodeInfoPtr
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000015527xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt,
15528 int depth)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015529{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000015530 xmlSchemaNodeInfoPtr info = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015531
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000015532 if (depth > vctxt->sizeElemInfos) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015533 xmlSchemaVErr(vctxt, NULL, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000015534 "Internal error: xmlSchemaGetFreshElemInfo, "
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015535 "an inconsistent depth encountered.\n",
15536 NULL, NULL);
15537 return (NULL);
15538 }
15539 if (vctxt->elemInfos == NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000015540 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
15541 xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015542 if (vctxt->elemInfos == NULL) {
15543 xmlSchemaVErrMemory(vctxt,
15544 "allocating the element info array", NULL);
15545 return (NULL);
15546 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000015547 memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015548 vctxt->sizeElemInfos = 10;
15549 } else if (vctxt->sizeElemInfos == vctxt->depth) {
15550 int i = vctxt->sizeElemInfos;
15551
15552 vctxt->sizeElemInfos *= 2;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000015553 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015554 xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000015555 sizeof(xmlSchemaNodeInfoPtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015556 if (vctxt->elemInfos == NULL) {
15557 xmlSchemaVErrMemory(vctxt,
15558 "re-allocating the element info array", NULL);
15559 return (NULL);
15560 }
15561 /*
15562 * We need the new memory to be NULLed.
15563 * TODO: Use memset instead?
15564 */
15565 for (; i < vctxt->sizeElemInfos; i++)
15566 vctxt->elemInfos[i] = NULL;
15567 } else
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000015568 info = vctxt->elemInfos[depth];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015569
15570 if (info == NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000015571 info = (xmlSchemaNodeInfoPtr)
15572 xmlMalloc(sizeof(xmlSchemaNodeInfo));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015573 if (info == NULL) {
15574 xmlSchemaVErrMemory(vctxt,
15575 "allocating an element info", NULL);
15576 return (NULL);
15577 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000015578 vctxt->elemInfos[depth] = info;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015579 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000015580 memset(info, 0, sizeof(xmlSchemaNodeInfo));
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000015581 info->depth = depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015582
15583 return (info);
15584}
15585#endif /* ELEM_INFO_ENABLED */
15586
Daniel Veillard3646d642004-06-02 19:19:14 +000015587
15588/**
15589 * xmlSchemaFreeAttrStates:
15590 * @state: a list of attribute states
15591 *
15592 * Free the given list of attribute states
15593 *
15594 */
15595static void
15596xmlSchemaFreeAttributeStates(xmlSchemaAttrStatePtr state)
15597{
15598 xmlSchemaAttrStatePtr tmp;
15599 while (state != NULL) {
15600 tmp = state;
15601 state = state->next;
15602 xmlFree(tmp);
15603 }
15604}
15605
Daniel Veillard4255d502002-04-16 15:50:10 +000015606/**
15607 * xmlSchemaRegisterAttributes:
15608 * @ctxt: a schema validation context
15609 * @attrs: a list of attributes
15610 *
15611 * Register the list of attributes as the set to be validated on that element
15612 *
15613 * Returns -1 in case of error, 0 otherwise
15614 */
15615static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015616xmlSchemaRegisterAttributes(xmlSchemaValidCtxtPtr ctxt, xmlAttrPtr attrs)
15617{
Daniel Veillard3646d642004-06-02 19:19:14 +000015618 xmlSchemaAttrStatePtr tmp;
15619
15620 ctxt->attr = NULL;
15621 ctxt->attrTop = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000015622 while (attrs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015623 if ((attrs->ns != NULL) &&
15624 (xmlStrEqual(attrs->ns->href, xmlSchemaInstanceNs))) {
15625 attrs = attrs->next;
15626 continue;
15627 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000015628 tmp = (xmlSchemaAttrStatePtr)
15629 xmlMalloc(sizeof(xmlSchemaAttrState));
15630 if (tmp == NULL) {
15631 xmlSchemaVErrMemory(ctxt, "registering attributes", NULL);
15632 return (-1);
15633 }
Daniel Veillard3646d642004-06-02 19:19:14 +000015634 tmp->attr = attrs;
15635 tmp->state = XML_SCHEMAS_ATTR_UNKNOWN;
15636 tmp->next = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015637 tmp->decl = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000015638 if (ctxt->attr == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015639 ctxt->attr = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000015640 else
15641 ctxt->attrTop->next = tmp;
15642 ctxt->attrTop = tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015643 attrs = attrs->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000015644 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015645 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000015646}
15647
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015648#if 0 /* Currently not used */
Daniel Veillard4255d502002-04-16 15:50:10 +000015649/**
Daniel Veillard4255d502002-04-16 15:50:10 +000015650 * xmlSchemaValidateCheckNodeList
15651 * @nodelist: the list of nodes
15652 *
15653 * Check the node list is only made of text nodes and entities pointing
15654 * to text nodes
15655 *
15656 * Returns 1 if true, 0 if false and -1 in case of error
15657 */
15658static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015659xmlSchemaValidateCheckNodeList(xmlNodePtr nodelist)
15660{
Daniel Veillard4255d502002-04-16 15:50:10 +000015661 while (nodelist != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015662 if (nodelist->type == XML_ENTITY_REF_NODE) {
15663 TODO /* implement recursion in the entity content */
15664 }
15665 if ((nodelist->type != XML_TEXT_NODE) &&
15666 (nodelist->type != XML_COMMENT_NODE) &&
15667 (nodelist->type != XML_PI_NODE) &&
William M. Bracke7091952004-05-11 15:09:58 +000015668 (nodelist->type != XML_CDATA_SECTION_NODE)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015669 return (0);
15670 }
15671 nodelist = nodelist->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000015672 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015673 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +000015674}
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015675#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000015676
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015677static void
15678xmlSchemaPostSchemaAssembleFixup(xmlSchemaParserCtxtPtr ctxt)
15679{
15680 int i, nbItems;
15681 xmlSchemaTypePtr item, *items;
15682
15683
15684 /*
15685 * During the Assemble of the schema ctxt->curItems has
15686 * been filled with the relevant new items. Fix those up.
15687 */
15688 nbItems = ctxt->assemble->nbItems;
15689 items = (xmlSchemaTypePtr *) ctxt->assemble->items;
15690
15691 for (i = 0; i < nbItems; i++) {
15692 item = items[i];
15693 switch (item->type) {
15694 case XML_SCHEMA_TYPE_ATTRIBUTE:
15695 xmlSchemaAttrFixup((xmlSchemaAttributePtr) item, ctxt, NULL);
15696 break;
15697 case XML_SCHEMA_TYPE_ELEMENT:
15698 xmlSchemaRefFixupCallback((xmlSchemaElementPtr) item, ctxt,
15699 NULL, NULL, NULL);
15700 break;
15701 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
15702 xmlSchemaAttrGrpFixup((xmlSchemaAttributeGroupPtr) item,
15703 ctxt, NULL);
15704 break;
15705 case XML_SCHEMA_TYPE_GROUP:
15706 xmlSchemaGroupDefFixup(item, ctxt, NULL);
15707 default:
15708 break;
15709 }
15710 }
15711 /*
15712 * Circularity checks.
15713 */
15714 for (i = 0; i < nbItems; i++) {
15715 item = items[i];
15716 switch (item->type) {
15717 case XML_SCHEMA_TYPE_GROUP:
15718 xmlSchemaCheckGroupDefCircular(item, ctxt, NULL);
15719 break;
15720 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
15721 xmlSchemaCheckAttributeGroupCircular(
15722 (xmlSchemaAttributeGroupPtr) item, ctxt, NULL);
15723 break;
15724 default:
15725 break;
15726 }
15727 }
15728 /*
15729 * Fixup for all other item.
15730 * TODO: Hmm, not sure if starting from complex/simple types,
15731 * all subsequent items will be reached.
15732 */
15733 for (i = 0; i < nbItems; i++) {
15734 item = items[i];
15735 switch (item->type) {
15736 case XML_SCHEMA_TYPE_SIMPLE:
15737 case XML_SCHEMA_TYPE_COMPLEX:
15738 xmlSchemaTypeFixup(item, ctxt, NULL);
15739 break;
15740 default:
15741 break;
15742 }
15743 }
15744 /*
15745 * Check facet values. Note that facets are
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000015746 * hold by simple type components only (and
15747 * by complex types in the current implementation).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015748 */
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000015749 /* OLD:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015750 for (i = 0; i < nbItems; i++) {
15751 item = items[i];
15752 switch (item->type) {
15753 case XML_SCHEMA_TYPE_SIMPLE:
15754 case XML_SCHEMA_TYPE_COMPLEX:
15755 xmlSchemaCheckDefaults(item, ctxt, NULL);
15756 break;
15757 default:
15758 break;
15759 }
15760 }
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000015761 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015762 /*
15763 * Build the content model for complex types.
15764 */
15765 for (i = 0; i < nbItems; i++) {
15766 item = items[i];
15767 switch (item->type) {
15768 case XML_SCHEMA_TYPE_COMPLEX:
15769 xmlSchemaBuildContentModel(item, ctxt, NULL);
15770 break;
15771 default:
15772 break;
15773 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015774 }
15775 /*
15776 * Validate value contraint values.
15777 */
15778 for (i = 0; i < nbItems; i++) {
15779 item = items[i];
15780 switch (item->type) {
15781 case XML_SCHEMA_TYPE_ATTRIBUTE:
15782 xmlSchemaCheckAttrValConstr((xmlSchemaAttributePtr) item, ctxt, NULL);
15783 break;
15784 case XML_SCHEMA_TYPE_ELEMENT:
15785 xmlSchemaCheckElemValConstr((xmlSchemaElementPtr) item, ctxt, NULL);
15786 break;
15787 default:
15788 break;
15789 }
15790 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015791}
15792
15793/**
15794 * xmlSchemaAssembleByLocation:
15795 * @pctxt: a schema parser context
15796 * @vctxt: a schema validation context
15797 * @schema: the existing schema
15798 * @node: the node that fired the assembling
15799 * @nsName: the namespace name of the new schema
15800 * @location: the location of the schema
15801 *
15802 * Expands an existing schema by an additional schema.
15803 *
15804 * Returns 0 if the new schema is correct, a positive error code
15805 * number otherwise and -1 in case of an internal or API error.
15806 */
15807static int
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015808xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
15809 xmlSchemaPtr schema,
15810 xmlNodePtr node,
15811 const xmlChar *nsName,
15812 const xmlChar *location)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015813{
15814 const xmlChar *targetNs, *oldtns;
15815 xmlDocPtr doc, olddoc;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015816 int oldflags, ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015817 xmlNodePtr docElem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015818 xmlSchemaParserCtxtPtr pctxt;
15819
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015820 /*
15821 * This should be used:
15822 * 1. on <import>(s)
15823 * 2. if requested by the validated instance
15824 * 3. if requested via the API
15825 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015826 if ((vctxt == NULL) || (schema == NULL))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015827 return (-1);
15828 /*
15829 * Create a temporary parser context.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015830 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015831 if ((vctxt->pctxt == NULL) &&
15832 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1)) {
15833 xmlSchemaVErr(vctxt, node,
15834 XML_SCHEMAV_INTERNAL,
15835 "Internal error: xmlSchemaAssembleByLocation, "
15836 "failed to create a temp. parser context.\n",
15837 NULL, NULL);
15838 return (-1);
15839 }
15840 pctxt = vctxt->pctxt;
15841 /*
15842 * Set the counter to produce unique names for anonymous items.
15843 */
15844 pctxt->counter = schema->counter;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015845 /*
15846 * Acquire the schema document.
15847 */
15848 ret = xmlSchemaAcquireSchemaDoc(pctxt, schema, node,
15849 nsName, location, &doc, &targetNs, 0);
15850 if (ret != 0) {
15851 if (doc != NULL)
15852 xmlFreeDoc(doc);
15853 } else if (doc != NULL) {
15854 docElem = xmlDocGetRootElement(doc);
15855 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015856 * Create new assemble info.
15857 */
15858 if (pctxt->assemble == NULL) {
15859 pctxt->assemble = xmlSchemaNewAssemble();
15860 if (pctxt->assemble == NULL) {
15861 xmlSchemaVErrMemory(vctxt,
15862 "Memory error: xmlSchemaAssembleByLocation, "
15863 "allocating assemble info", NULL);
15864 xmlFreeDoc(doc);
15865 return (-1);
15866 }
15867 }
15868 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015869 * Save and reset the context & schema.
15870 */
15871 oldflags = schema->flags;
15872 oldtns = schema->targetNamespace;
15873 olddoc = schema->doc;
15874
15875 xmlSchemaClearSchemaDefaults(schema);
15876 schema->targetNamespace = targetNs;
15877 /* schema->nbCurItems = 0; */
15878 pctxt->schema = schema;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015879 pctxt->ctxtType = NULL;
15880 pctxt->parentItem = NULL;
15881
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015882 xmlSchemaParseSchemaDefaults(pctxt, schema, docElem);
15883 xmlSchemaParseSchemaTopLevel(pctxt, schema, docElem->children);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015884 xmlSchemaPostSchemaAssembleFixup(pctxt);
15885 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015886 * Set the counter of items.
15887 */
15888 schema->counter = pctxt->counter;
15889 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015890 * Free the list of assembled components.
15891 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015892 pctxt->assemble->nbItems = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015893 /*
15894 * Restore the context & schema.
15895 */
15896 schema->flags = oldflags;
15897 schema->targetNamespace = oldtns;
15898 schema->doc = olddoc;
15899 ret = pctxt->err;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015900 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015901 return (ret);
15902}
15903
15904/**
15905 * xmlSchemaAssembleByXSIAttr:
15906 * @vctxt: a schema validation context
15907 * @xsiAttr: an xsi attribute
15908 * @noNamespace: whether a schema with no target namespace is exptected
15909 *
15910 * Expands an existing schema by an additional schema using
15911 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
15912 * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
15913 * must be set to 1.
15914 *
15915 * Returns 0 if the new schema is correct, a positive error code
15916 * number otherwise and -1 in case of an internal or API error.
15917 */
15918static int
15919xmlSchemaAssembleByXSIAttr(xmlSchemaValidCtxtPtr vctxt,
15920 xmlAttrPtr xsiAttr,
15921 int noNamespace)
15922{
15923 xmlChar *value;
15924 const xmlChar *cur, *end;
15925 const xmlChar *nsname = NULL, *location;
15926 int count = 0;
15927 int ret = 0;
15928
15929 if (xsiAttr == NULL) {
15930 xmlSchemaVCustomErr(vctxt, XML_SCHEMAV_INTERNAL,
15931 NULL, NULL,
15932 "Internal error: xmlSchemaAssembleByXSIAttr, "
15933 "bad arguments", NULL);
15934 return (-1);
15935 }
15936 /*
15937 * Parse the value; we will assume an even number of values
15938 * to be given (this is how Xerces and XSV work).
15939 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015940 value = xmlNodeGetContent((xmlNodePtr) xsiAttr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015941 cur = value;
15942 do {
15943 if (noNamespace != 1) {
15944 /*
15945 * Get the namespace name.
15946 */
15947 while (IS_BLANK_CH(*cur))
15948 cur++;
15949 end = cur;
15950 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
15951 end++;
15952 if (end == cur)
15953 break;
15954 count++;
15955 nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
15956 cur = end;
15957 }
15958 /*
15959 * Get the URI.
15960 */
15961 while (IS_BLANK_CH(*cur))
15962 cur++;
15963 end = cur;
15964 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
15965 end++;
15966 if (end == cur)
15967 break;
15968 count++;
15969 location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015970 cur = end;
15971 ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015972 xsiAttr->parent, nsname, location);
15973 if (ret == -1) {
15974 xmlSchemaVCustomErr(vctxt,
15975 XML_SCHEMAV_INTERNAL,
15976 (xmlNodePtr) xsiAttr, NULL,
15977 "Internal error: xmlSchemaAssembleByXSIAttr, "
15978 "assembling schemata", NULL);
15979 if (value != NULL)
15980 xmlFree(value);
15981 return (-1);
15982 }
15983 } while (*cur != 0);
15984 if (value != NULL)
15985 xmlFree(value);
15986 return (ret);
15987}
15988
15989/**
15990 * xmlSchemaAssembleByXSIElem:
15991 * @vctxt: a schema validation context
15992 * @elem: an element node possibly holding xsi attributes
15993 * @noNamespace: whether a schema with no target namespace is exptected
15994 *
15995 * Assembles an existing schema by an additional schema using
15996 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attributes
15997 * of the given @elem.
15998 *
15999 * Returns 0 if the new schema is correct, a positive error code
16000 * number otherwise and -1 in case of an internal or API error.
16001 */
16002static int
16003xmlSchemaAssembleByXSIElem(xmlSchemaValidCtxtPtr vctxt,
16004 xmlNodePtr elem)
16005{
16006 int ret = 0, retNs = 0;
16007 xmlAttrPtr attr;
16008
16009 attr = xmlHasNsProp(elem, BAD_CAST "schemaLocation", xmlSchemaInstanceNs);
16010 if (attr != NULL) {
16011 retNs = xmlSchemaAssembleByXSIAttr(vctxt, attr, 0);
16012 if (retNs == -1)
16013 return (-1);
16014 }
16015 attr = xmlHasNsProp(elem, BAD_CAST "noNamespaceSchemaLocation", xmlSchemaInstanceNs);
16016 if (attr != NULL) {
16017 ret = xmlSchemaAssembleByXSIAttr(vctxt, attr, 1);
16018 if (ret == -1)
16019 return (-1);
16020 }
16021 if (retNs != 0)
16022 return (retNs);
16023 else
16024 return (ret);
16025}
16026
Daniel Veillard4255d502002-04-16 15:50:10 +000016027/**
Daniel Veillard4255d502002-04-16 15:50:10 +000016028 * xmlSchemaValidateCallback:
16029 * @ctxt: a schema validation context
16030 * @name: the name of the element detected (might be NULL)
16031 * @type: the type
16032 *
16033 * A transition has been made in the automata associated to an element
16034 * content model
16035 */
16036static void
16037xmlSchemaValidateCallback(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016038 const xmlChar * name ATTRIBUTE_UNUSED,
16039 xmlSchemaTypePtr type, xmlNodePtr node)
16040{
Daniel Veillard4255d502002-04-16 15:50:10 +000016041 xmlSchemaTypePtr oldtype = ctxt->type;
16042 xmlNodePtr oldnode = ctxt->node;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016043
Daniel Veillard4255d502002-04-16 15:50:10 +000016044#ifdef DEBUG_CONTENT
Daniel Veillard8651f532002-04-17 09:06:27 +000016045 xmlGenericError(xmlGenericErrorContext,
16046 "xmlSchemaValidateCallback: %s, %s, %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016047 name, type->name, node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +000016048#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016049 /*
16050 * @type->type will be XML_SCHEMA_TYPE_ANY or XML_SCHEMA_TYPE_ELEMENT.
16051 */
Daniel Veillard4255d502002-04-16 15:50:10 +000016052 ctxt->type = type;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016053 ctxt->node = node;
16054 ctxt->cur = node->children;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016055
16056#ifdef ELEM_INFO_ENABLED
16057 xmlSchemaBeginElement(ctxt);
16058#endif
16059
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016060 /*
16061 * Assemble new schemata using xsi.
16062 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016063 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016064 int ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016065
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016066 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
16067 if (ret == -1) {
16068 xmlSchemaVCustomErr(ctxt,
16069 XML_SCHEMAV_INTERNAL,
16070 ctxt->node, NULL,
16071 "Internal error: xmlSchemaValidateElement, "
16072 "assembling schema by xsi", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016073 goto leave;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016074 }
16075 /*
16076 * NOTE: We won't react on schema parser errors here.
16077 * TODO: But a warning would be nice.
16078 */
16079 }
16080 switch (type->type) {
16081 case XML_SCHEMA_TYPE_ELEMENT: {
16082 /*
16083 * NOTE: The build of the content model
16084 * (xmlSchemaBuildAContentModel) ensures that the element
16085 * declaration (and not a reference to it) will be given.
16086 */
16087 if (((xmlSchemaElementPtr) ctxt->type)->ref != NULL) {
16088 /*
16089 * This is paranoid coding ;-)... it should not
16090 * happen here any more.
16091 */
16092 xmlSchemaVCustomErr(ctxt,
16093 XML_SCHEMAV_INTERNAL,
16094 node, NULL,
16095 "Internal error: xmlSchemaValidateCallback, "
16096 "element declaration 'reference' encountered, "
16097 "but an element declaration was expected",
16098 NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016099 goto leave;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016100 }
16101 xmlSchemaValidateElementByDeclaration(ctxt,
16102 (xmlSchemaElementPtr) type);
16103 break;
16104 }
16105 case XML_SCHEMA_TYPE_ANY:
16106 xmlSchemaValidateElementByWildcard(ctxt, type);
16107 break;
16108 default:
16109 break;
16110 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016111leave:
16112
16113#ifdef ELEM_INFO_ENABLED
16114 xmlSchemaEndElement(ctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016115#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000016116 ctxt->type = oldtype;
16117 ctxt->node = oldnode;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016118}
Daniel Veillard4255d502002-04-16 15:50:10 +000016119
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016120static int
16121xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
16122 const xmlChar *value,
16123 xmlSchemaValPtr *val,
16124 xmlNodePtr node)
16125{
16126 int ret;
16127
16128 ret = xmlValidateQName(value, 1);
16129 if (ret != 0)
16130 return (ret);
16131
16132 {
16133 xmlChar *uri = NULL;
16134 xmlChar *local = NULL;
16135 xmlChar *prefix;
16136
16137 local = xmlSplitQName2(value, &prefix);
16138 if (prefix != NULL) {
16139 xmlNsPtr ns;
16140
16141 /*
16142 * TODO: Make this streamable.
16143 */
16144 if ((node == NULL) || (node->doc == NULL)) {
16145 xmlFree(prefix);
16146 xmlFree(local);
16147 return (3);
16148 }
16149
16150 ns = xmlSearchNs(node->doc, node, prefix);
16151 if (ns == NULL) {
16152 xmlFree(prefix);
16153 xmlFree(local);
16154 return (1);
16155 }
16156 }
16157 if (prefix != NULL) {
16158 if (xmlHashLookup2(vctxt->schema->notaDecl, local, uri) == NULL)
16159 ret = 1;
16160 } else if (xmlHashLookup2(vctxt->schema->notaDecl, value,
16161 NULL) == NULL)
16162 ret = 1;
16163
16164 if ((ret == 0) && (val != NULL)) {
16165 if (prefix != NULL) {
16166 (*val) = xmlSchemaNewNOTATIONValue(BAD_CAST local,
16167 BAD_CAST xmlStrdup(uri));
16168 local = NULL;
16169 } else
16170 (*val) = xmlSchemaNewNOTATIONValue(BAD_CAST xmlStrdup(value),
16171 NULL);
16172 if (*val == NULL)
16173 ret = -1;
16174 }
16175 if (local != NULL)
16176 xmlFree(local);
16177 }
16178
16179 return (ret);
16180}
16181
Daniel Veillard01fa6152004-06-29 17:04:39 +000016182/**
16183 * xmlSchemaValidateSimpleTypeValue:
16184 * @ctxt: a schema validation context
16185 * @value: the value to be validated
16186 * @fireErrors: shall errors be reported?
16187 * @applyFacets: shall facets be applied?
Daniel Veillardc0826a72004-08-10 14:17:33 +000016188 * @normalize: shall the value be normalized?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016189 * @checkNodes: shall the content nodes be checked?
Daniel Veillard01fa6152004-06-29 17:04:39 +000016190 *
16191 * Validates a value by the given type (user derived or built-in).
16192 *
16193 * Returns 0 if the value is valid, a positive error code
16194 * number otherwise and -1 in case of an internal or API error.
Daniel Veillard01fa6152004-06-29 17:04:39 +000016195 */
16196static int
16197xmlSchemaValidateSimpleTypeValue(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016198 xmlSchemaTypePtr type,
16199 const xmlChar *value,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016200 int fireErrors,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016201 int applyFacets,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016202 int normalize,
16203 int checkNodes)
Daniel Veillard01fa6152004-06-29 17:04:39 +000016204{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016205 xmlNodePtr node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000016206 int ret = 0;
16207 xmlChar *normValue = NULL;
16208 int wtsp;
16209
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016210 node = ctxt->node;
16211 /* Save the current whitespace normalization type. */
Daniel Veillardc0826a72004-08-10 14:17:33 +000016212 wtsp = ctxt->valueWS;
16213 /*
16214 * Normalize the value.
16215 */
16216 if (normalize &&
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000016217 (ctxt->valueWS != XML_SCHEMAS_FACET_COLLAPSE)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000016218 int norm = xmlSchemaGetWhiteSpaceFacetValue(type);
16219
16220 if ((norm != -1) && (norm > ctxt->valueWS)) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000016221 if (norm == XML_SCHEMAS_FACET_COLLAPSE)
Daniel Veillardc0826a72004-08-10 14:17:33 +000016222 normValue = xmlSchemaCollapseString(value);
16223 else
16224 normValue = xmlSchemaWhiteSpaceReplace(value);
16225 ctxt->valueWS = norm;
16226 if (normValue != NULL)
16227 value = (const xmlChar *) normValue;
16228 }
16229 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016230 /*
16231 * The nodes of a content must be checked only once,
16232 * this is not working since list types will fire this
16233 * multiple times.
16234 */
16235 if ((checkNodes == 1) && (ctxt->cur != NULL)) {
16236 xmlNodePtr cur = ctxt->cur;
16237
16238 do {
16239 switch (cur->type) {
16240 case XML_TEXT_NODE:
16241 case XML_CDATA_SECTION_NODE:
16242 case XML_PI_NODE:
16243 case XML_COMMENT_NODE:
16244 case XML_XINCLUDE_START:
16245 case XML_XINCLUDE_END:
16246 break;
16247 case XML_ENTITY_REF_NODE:
16248 case XML_ENTITY_NODE:
16249 /* TODO: Scour the entities for illegal nodes. */
16250 TODO break;
16251 case XML_ELEMENT_NODE: {
16252 /* NOTE: Changed to an internal error, since the
16253 * existence of an element node will be already checked in
16254 * xmlSchemaValidateElementBySimpleType and in
16255 * xmlSchemaValidateElementByComplexType.
16256 */
16257 xmlSchemaVCustomErr(ctxt,
16258 XML_SCHEMAV_INTERNAL,
16259 /* XML_SCHEMAS_ERR_INVALIDELEM, */
16260 node, type,
16261 "Element '%s' found in simple type content",
16262 cur->name);
16263 return (XML_SCHEMAV_INTERNAL);
16264 }
16265 case XML_ATTRIBUTE_NODE:
16266 case XML_DOCUMENT_NODE:
16267 case XML_DOCUMENT_TYPE_NODE:
16268 case XML_DOCUMENT_FRAG_NODE:
16269 case XML_NOTATION_NODE:
16270 case XML_HTML_DOCUMENT_NODE:
16271 case XML_DTD_NODE:
16272 case XML_ELEMENT_DECL:
16273 case XML_ATTRIBUTE_DECL:
16274 case XML_ENTITY_DECL:
16275 case XML_NAMESPACE_DECL:
16276#ifdef LIBXML_DOCB_ENABLED
16277 case XML_DOCB_DOCUMENT_NODE:
16278#endif
16279 xmlSchemaVCustomErr(ctxt,
16280 XML_SCHEMAV_INTERNAL,
16281 /* XML_SCHEMAS_ERR_INVALIDELEM, */
16282 node, NULL,
16283 "Node of unexpected type found in simple type content",
16284 NULL);
16285 return (XML_SCHEMAV_INTERNAL);
16286 }
16287 cur = cur->next;
16288 } while (cur != NULL);
16289 }
16290
William M. Brack2f2a6632004-08-20 23:09:47 +000016291 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
16292 xmlSchemaTypePtr base, anyType;
16293
16294 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
16295
16296 base = type->baseType;
16297 while ((base != NULL) &&
16298 (base->type != XML_SCHEMA_TYPE_SIMPLE) &&
16299 (base->type != XML_SCHEMA_TYPE_BASIC) &&
16300 (base != anyType)) {
16301 base = base->baseType;
16302 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016303 ret = xmlSchemaValidateSimpleTypeValue(ctxt, base, value, 1, 0, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000016304 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016305 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000016306 "Internal error: xmlSchemaValidateSimpleTypeValue, "
16307 "validating complex type '%s'\n",
16308 type->name, NULL);
16309 } else if ((ret == 0) && (applyFacets) && (type->facetSet != NULL)) {
16310 /*
16311 * Check facets.
16312 */
16313 /*
16314 * This is somehow not nice, since if an error occurs
16315 * the reported type will be the complex type; the spec
16316 * wants a simple type to be created on the complex type
16317 * if it has a simple content. For now we have to live with
16318 * it.
16319 */
16320 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
16321 value, 0, fireErrors);
16322 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016323 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000016324 "Internal error: xmlSchemaValidateSimpleTypeValue, "
16325 "validating facets of complex type '%s'\n",
16326 type->name, NULL);
16327 } else if (ret > 0) {
16328 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
William M. Brack2f2a6632004-08-20 23:09:47 +000016329 if (fireErrors)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016330 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
William M. Brack2f2a6632004-08-20 23:09:47 +000016331 }
16332 }
16333 } else if (type->type == XML_SCHEMA_TYPE_BASIC) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016334
16335 if (ctxt->value != NULL) {
16336 xmlSchemaFreeValue(ctxt->value);
16337 ctxt->value = NULL;
16338 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016339 /*
16340 * STREAM-READ-CHILDREN.
16341 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016342 if ((type->builtInType == XML_SCHEMAS_NOTATION) &&
16343 (ctxt->schema != NULL)) {
16344 /*
16345 * NOTATIONs need to be processed here, since they need
16346 * to lookup in the hashtable of NOTATION declarations.
16347 */
16348 ret = xmlSchemaValidateNotation(ctxt, value, &(ctxt->value), node);
16349 } else
16350 ret = xmlSchemaValPredefTypeNodeNoNorm(type, value, &(ctxt->value), node);
Daniel Veillardc0826a72004-08-10 14:17:33 +000016351 if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016352 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
16353 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
16354 else
16355 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000016356 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016357 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016358 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016359 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016360 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000016361 "validating built-in type '%s'\n", type->name, NULL);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000016362 } else if ((ctxt->value == NULL) &&
16363 (type->builtInType == XML_SCHEMAS_STRING) &&
16364 (ctxt->nodeInfo != NULL) &&
16365 (ctxt->nodeInfo->flags & XML_SCHEMA_ELEM_INFO_VALUE_NEEDED)) {
16366#ifdef IDC_VALUE_SUPPORT
16367 xmlChar *valdup;
16368 /*
16369 * Create a precomputed string value for "string" as well if
16370 * requested.
16371 */
16372 valdup = xmlStrdup(value);
16373 ctxt->value = xmlSchemaNewStringValue(XML_SCHEMAS_STRING,
16374 BAD_CAST valdup);
16375 if ((valdup != NULL) && (ctxt->value == NULL))
16376 xmlFree(valdup);
16377#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +000016378 }
16379 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
16380 /* 1.2.1 if {variety} is ·atomic· then the string must ·match·
16381 * a literal in the ·lexical space· of {base type definition}
16382 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016383 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type->baseType, value, 0, 0, 0, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016384 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016385 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016386 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000016387 "validating atomic simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000016388 type->name, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000016389 } else if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016390 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000016391 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016392 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillardc0826a72004-08-10 14:17:33 +000016393 } else if ((applyFacets) && (type->facetSet != NULL)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016394 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000016395 * Check facets.
Daniel Veillard01fa6152004-06-29 17:04:39 +000016396 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000016397 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
16398 value, 0, fireErrors);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016399 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016400 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016401 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000016402 "validating facets of atomic simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000016403 type->name, NULL);
16404 } else if (ret > 0) {
16405 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000016406 /*
16407 Disabled, since the facet validation already reports errors.
16408 if (fireErrors)
16409 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
16410 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000016411 }
16412 }
16413 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
16414
16415 xmlSchemaTypePtr tmpType;
16416 const xmlChar *cur, *end;
16417 xmlChar *tmp;
Daniel Veillardc0826a72004-08-10 14:17:33 +000016418 unsigned long len = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016419
16420 /* 1.2.2 if {variety} is ·list· then the string must be a sequence
16421 * of white space separated tokens, each of which ·match·es a literal
16422 * in the ·lexical space· of {item type definition}
16423 */
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +000016424
Kasimier T. Buchcikde938cd2005-01-13 12:25:57 +000016425 if (value == NULL)
16426 value = BAD_CAST "";
Daniel Veillardc0826a72004-08-10 14:17:33 +000016427 tmpType = xmlSchemaGetListSimpleTypeItemType(type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016428 cur = value;
16429 do {
16430 while (IS_BLANK_CH(*cur))
16431 cur++;
16432 end = cur;
16433 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
16434 end++;
16435 if (end == cur)
16436 break;
16437 tmp = xmlStrndup(cur, end - cur);
16438 len++;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016439 ret = xmlSchemaValidateSimpleTypeValue(ctxt, tmpType, tmp, 0, 1, 0, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016440 xmlFree(tmp);
Daniel Veillardc0826a72004-08-10 14:17:33 +000016441 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016442 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016443 "Internal error: xmlSchemaValidateSimpleTypeValue, "
16444 "validating an item of list simple type '%s'\n",
16445 type->name, NULL);
16446 break;
16447 } else if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016448 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
Daniel Veillardc0826a72004-08-10 14:17:33 +000016449 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016450 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016451 break;
Daniel Veillardc0826a72004-08-10 14:17:33 +000016452 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000016453 cur = end;
16454 } while (*cur != 0);
16455 /*
16456 * Check facets.
16457 */
16458 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016459 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016460 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000016461 "validating list simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000016462 type->name, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000016463 } else if ((ret == 0) && (applyFacets)) {
16464 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
16465 value, len, fireErrors);
16466 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016467 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016468 "Internal error: xmlSchemaValidateSimpleTypeValue, "
16469 "validating facets of list simple type '%s'\n",
16470 type->name, NULL);
16471 } else if (ret > 0) {
16472 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016473 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000016474 Disabled, since the facet validation already reports errors.
16475 if (fireErrors)
16476 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016477 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000016478 }
16479
Daniel Veillard01fa6152004-06-29 17:04:39 +000016480 }
16481 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
16482 xmlSchemaTypeLinkPtr memberLink;
16483
16484 /*
16485 * TODO: For all datatypes ·derived· by ·union· whiteSpace does
16486 * not apply directly; however, the normalization behavior of ·union·
16487 * types is controlled by the value of whiteSpace on that one of the
16488 * ·memberTypes· against which the ·union· is successfully validated.
16489 *
16490 * This means that the value is normalized by the first validating
16491 * member type, then the facets of the union type are applied. This
16492 * needs changing of the value!
16493 */
16494
16495 /*
16496 * 1.2.3 if {variety} is ·union· then the string must ·match· a
16497 * literal in the ·lexical space· of at least one member of
16498 * {member type definitions}
16499 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000016500#ifdef DEBUG_UNION_VALIDATION
16501 printf("Union ST : '%s'\n", (const char *) type->name);
16502 printf(" fireErrors : %d\n", fireErrors);
16503 printf(" applyFacets: %d\n", applyFacets);
16504#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +000016505 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
16506 if (memberLink == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016507 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016508 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000016509 "union simple type '%s' has no member types\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000016510 type->name, NULL);
16511 ret = -1;
16512 }
16513 if (ret == 0) {
16514 while (memberLink != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016515 ret = xmlSchemaValidateSimpleTypeValue(ctxt, memberLink->type,
16516 value, 0, 1, 1, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016517 if ((ret <= 0) || (ret == 0))
16518 break;
16519 memberLink = memberLink->next;
16520 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000016521 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016522 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016523 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000016524 "validating members of union simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000016525 type->name, NULL);
16526 } else if (ret > 0) {
16527 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
Daniel Veillardc0826a72004-08-10 14:17:33 +000016528 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016529 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillardc0826a72004-08-10 14:17:33 +000016530 }
16531 }
16532 /*
16533 * Apply facets (pattern, enumeration).
16534 */
16535 if ((ret == 0) && (applyFacets) && (type->facetSet != NULL)) {
16536 int mws;
16537 /*
16538 * The normalization behavior of ·union· types is controlled by
16539 * the value of whiteSpace on that one of the ·memberTypes·
16540 * against which the ·union· is successfully validated.
16541 */
16542 if (normValue != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016543 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016544 "Internal error: xmlSchemaValidateSimpleTypeValue, "
16545 "the value was already normalized for the union simple "
16546 "type '%s'.\n", type->name, NULL);
16547 }
16548 mws = xmlSchemaGetWhiteSpaceFacetValue(memberLink->type);
16549 if (mws > ctxt->valueWS) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000016550 if (mws == XML_SCHEMAS_FACET_COLLAPSE)
Daniel Veillardc0826a72004-08-10 14:17:33 +000016551 normValue = xmlSchemaCollapseString(value);
16552 else
16553 normValue = xmlSchemaWhiteSpaceReplace(value);
16554 if (normValue != NULL)
16555 value = (const xmlChar *) normValue;
16556 }
16557
16558 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
16559 value, 0, fireErrors);
16560 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016561 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016562 "Internal error: xmlSchemaValidateSimpleTypeValue, "
16563 "validating facets of union simple type '%s'\n",
16564 type->name, NULL);
16565 } else if (ret > 0) {
16566 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
16567 /*
16568 if (fireErrors)
16569 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
16570 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000016571 }
16572 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000016573 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000016574 ctxt->valueWS = wtsp;
16575 if (normValue != NULL)
16576 xmlFree(normValue);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016577 return (ret);
16578}
16579
16580/**
16581 * xmlSchemaValidateSimpleTypeElement:
16582 * @ctxt: a schema validation context
16583 * @node: the element node to be validated.
16584 *
16585 * Validate the element against a simple type.
16586 *
16587 * Returns 0 if the element is valid, a positive error code
16588 * number otherwise and -1 in case of an internal or API error.
16589 */
16590static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016591xmlSchemaValidateElementBySimpleType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016592 xmlSchemaTypePtr type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000016593 int isNil,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016594 int valSimpleContent)
Daniel Veillard01fa6152004-06-29 17:04:39 +000016595{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016596 xmlSchemaTypePtr oldtype;
16597 xmlNodePtr node;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016598 xmlAttrPtr attr;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016599 xmlNodePtr cur;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016600 int ret = 0, retval = 0;
16601
Daniel Veillard01fa6152004-06-29 17:04:39 +000016602 if ((ctxt == NULL) || (type == NULL)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016603 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_INTERNAL, NULL, NULL,
16604 "Internal error: xmlSchemaValidateElementBySimpleType, "
16605 "bad arguments", NULL);
16606 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016607 }
16608
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016609 oldtype = ctxt->type;
16610 node = ctxt->node;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016611 /*
16612 * cvc-type: 3.1.2 The element information item must have no element
16613 * information item [children].
16614 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016615 /*
16616 * STREAM: Child nodes are processed.
16617 */
16618 cur = node->children;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016619 while (cur != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016620 /*
16621 * TODO: Entities, will they produce elements as well?
16622 */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016623 if (cur->type == XML_ELEMENT_NODE) {
16624 xmlSchemaVCustomErr(ctxt,
16625 XML_SCHEMAV_CVC_TYPE_3_1_2,
16626 node, type,
16627 "No element content allowed", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016628 ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016629 }
16630 cur = cur->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016631 }
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016632
Daniel Veillard01fa6152004-06-29 17:04:39 +000016633 /*
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016634 * cvc-type 3.1.1:
16635 *
16636 * The attributes of must be empty, excepting those whose namespace name
16637 * is identical to http://www.w3.org/2001/XMLSchema-instance and whose local
16638 * name is one of type, nil, schemaLocation or noNamespaceSchemaLocation.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016639 */
16640 /*
16641 * STREAM: Attribute nodes are processed.
16642 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000016643 attr = node->properties;
16644 while (attr != NULL) {
16645 if ((attr->ns == NULL) ||
16646 (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
16647 ((!xmlStrEqual(attr->name, BAD_CAST "type")) &&
16648 (!xmlStrEqual(attr->name, BAD_CAST "nil")) &&
16649 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation")) &&
16650 (!xmlStrEqual
16651 (attr->name, BAD_CAST "noNamespaceSchemaLocation")))) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016652 xmlSchemaVIllegalAttrErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016653 XML_SCHEMAV_CVC_TYPE_3_1_1, attr);
16654 ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016655 }
16656 attr = attr->next;
16657 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016658 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016659 * This will skip validation if the type is 'anySimpleType' and
16660 * if the value was already validated (e.g. default values).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016661 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000016662 if ((! isNil) &&
16663 (valSimpleContent == 1) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016664 ((type->type != XML_SCHEMA_TYPE_BASIC) ||
16665 (type->builtInType != XML_SCHEMAS_ANYSIMPLETYPE))) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016666 xmlChar *value;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016667
16668 value = xmlNodeGetContent(node);
16669 /*
16670 * NOTE: This call will not check the content nodes, since
16671 * this should be checked here already.
16672 */
16673 retval = xmlSchemaValidateSimpleTypeValue(ctxt, type, value,
16674 1, 1, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000016675 if (value != NULL)
16676 xmlFree(value);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016677 if (retval != 0)
16678 ret = retval;
William M. Brack2f2a6632004-08-20 23:09:47 +000016679 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016680 ctxt->type = oldtype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016681 return (ret);
16682}
Daniel Veillard4255d502002-04-16 15:50:10 +000016683
16684/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016685 * xmlSchemaValQNameAcquire:
16686 * @value: the lexical represantation of the QName value
16687 * @node: the node to search for the corresponding namespace declaration
16688 * @nsName: the resulting namespace name if found
16689 *
16690 * Checks that a value conforms to the lexical space of the type QName;
16691 * if valid, the corresponding namespace name is searched and retured
16692 * as a copy in @nsName. The local name is returned in @localName as
16693 * a copy.
16694 *
16695 * Returns 0 if valid, 1 if not valid by type, 2 if no corresponding
16696 * namespace declaration was found in scope; -1 in case of an internal or
16697 * API error.
16698 */
16699static int
16700xmlSchemaValQNameAcquire(const xmlChar *value, xmlNodePtr node,
16701 xmlChar **nsName, xmlChar **localName)
16702{
16703 int ret;
16704 xmlChar *local = NULL;
16705
16706 if ((nsName == NULL) || (localName == NULL) || (node == NULL))
16707 return (-1);
16708 *nsName = NULL;
16709 *localName = NULL;
16710 ret = xmlValidateQName(value, 1);
16711 if (ret == 0) {
16712 xmlChar *prefix;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016713 xmlNsPtr ns;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016714
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016715 /*
16716 * NOTE: xmlSplitQName2 will return a duplicated
16717 * string.
16718 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016719 local = xmlSplitQName2(value, &prefix);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016720 if (local == NULL)
16721 local = xmlStrdup(value);
16722 ns = xmlSearchNs(node->doc, node, prefix);
16723 /*
16724 * A namespace need not to be found if the prefix is NULL.
16725 */
16726 if (ns != NULL) {
16727 /*
16728 * TODO: Is it necessary to duplicate the URI here?
16729 */
16730 *nsName = xmlStrdup(ns->href);
16731 } else if (prefix != NULL) {
16732 xmlFree(prefix);
16733 if (local != NULL)
16734 xmlFree(local);
16735 return (2);
16736 }
16737 *localName = local;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016738 if (prefix != NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016739 xmlFree(prefix);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016740 } else
16741 return (1);
16742 return (ret);
16743}
16744
16745/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016746 * xmlSchemaHasElemContent:
16747 * @node: the node
16748 *
16749 * Scours the content of the given node for element
16750 * nodes.
16751 *
16752 * Returns 1 if an element node is found,
16753 * 0 otherwise.
16754 */
16755static int
16756xmlSchemaHasElemContent(xmlNodePtr node)
16757{
16758 if (node == NULL)
16759 return (0);
16760 node = node->children;
16761 while (node != NULL) {
16762 if (node->type == XML_ELEMENT_NODE)
16763 return (1);
16764 node = node->next;
16765 }
16766 return (0);
16767}
16768/**
16769 * xmlSchemaHasElemOrCharContent:
16770 * @node: the node
16771 *
16772 * Scours the content of the given node for element
16773 * and character nodes.
16774 *
16775 * Returns 1 if an element or character node is found,
16776 * 0 otherwise.
16777 */
16778static int
16779xmlSchemaHasElemOrCharContent(xmlNodePtr node)
16780{
16781 if (node == NULL)
16782 return (0);
16783 node = node->children;
16784 while (node != NULL) {
16785 switch (node->type) {
16786 case XML_ELEMENT_NODE:
16787 /*
16788 * TODO: Ask Daniel if these are all character nodes.
16789 */
16790 case XML_TEXT_NODE:
16791 case XML_CDATA_SECTION_NODE:
16792 /*
16793 * TODO: How XML_ENTITY_NODEs evaluated?
16794 */
16795 case XML_ENTITY_REF_NODE:
16796 case XML_ENTITY_NODE:
16797 return (1);
16798 break;
16799 default:
16800 break;
16801 }
16802 node = node->next;
16803 }
16804 return (0);
16805}
16806
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016807/************************************************************************
16808 * *
16809 * Identity-constraints (IDC) *
16810 * *
16811 ************************************************************************/
16812
16813#ifdef IDC_ENABLED
16814
16815/**
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016816 * xmlSchemaAugmentIDC:
16817 * @idcDef: the IDC definition
16818 *
16819 * Creates an augmented IDC definition item.
16820 *
16821 * Returns the item, or NULL on internal errors.
16822 */
16823static void
16824xmlSchemaAugmentIDC(xmlSchemaIDCPtr idcDef,
16825 xmlSchemaValidCtxtPtr vctxt)
16826{
16827 xmlSchemaIDCAugPtr aidc;
16828
16829 aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
16830 if (aidc == NULL) {
16831 xmlSchemaVErrMemory(vctxt,
16832 "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
16833 NULL);
16834 return;
16835 }
16836 aidc->bubbleDepth = -1;
16837 aidc->def = idcDef;
16838 aidc->next = NULL;
16839 if (vctxt->aidcs == NULL)
16840 vctxt->aidcs = aidc;
16841 else {
16842 aidc->next = vctxt->aidcs;
16843 vctxt->aidcs = aidc;
16844 }
16845}
16846
16847/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016848 * xmlSchemaIDCNewBinding:
16849 * @idcDef: the IDC definition of this binding
16850 *
16851 * Creates a new IDC binding.
16852 *
16853 * Returns the new binding in case of succeeded, NULL on internal errors.
16854 */
16855static xmlSchemaPSVIIDCBindingPtr
16856xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
16857{
16858 xmlSchemaPSVIIDCBindingPtr ret;
16859
16860 ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
16861 sizeof(xmlSchemaPSVIIDCBinding));
16862 if (ret == NULL) {
16863 xmlSchemaVErrMemory(NULL,
16864 "allocating a PSVI IDC binding item", NULL);
16865 return (NULL);
16866 }
16867 memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
16868 ret->definition = idcDef;
16869 return (ret);
16870}
16871
16872/**
16873 * xmlSchemaIDCStoreNodeTableItem:
16874 * @vctxt: the WXS validation context
16875 * @item: the IDC node table item
16876 *
16877 * The validation context is used to store an IDC node table items.
16878 * They are stored to avoid copying them if IDC node-tables are merged
16879 * with corresponding parent IDC node-tables (bubbling).
16880 *
16881 * Returns 0 if succeeded, -1 on internal errors.
16882 */
16883static int
16884xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
16885 xmlSchemaPSVIIDCNodePtr item)
16886{
16887 /*
16888 * Add to gobal list.
16889 */
16890 if (vctxt->idcNodes == NULL) {
16891 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
16892 xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
16893 if (vctxt->idcNodes == NULL) {
16894 xmlSchemaVErrMemory(vctxt,
16895 "allocating the IDC node table item list", NULL);
16896 return (-1);
16897 }
16898 vctxt->sizeIdcNodes = 20;
16899 } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
16900 vctxt->sizeIdcNodes *= 2;
16901 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
16902 xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
16903 sizeof(xmlSchemaPSVIIDCNodePtr));
16904 if (vctxt->idcNodes == NULL) {
16905 xmlSchemaVErrMemory(vctxt,
16906 "re-allocating the IDC node table item list", NULL);
16907 return (-1);
16908 }
16909 }
16910 vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
16911
16912 return (0);
16913}
16914
16915/**
16916 * xmlSchemaIDCStoreKey:
16917 * @vctxt: the WXS validation context
16918 * @item: the IDC key
16919 *
16920 * The validation context is used to store an IDC key.
16921 *
16922 * Returns 0 if succeeded, -1 on internal errors.
16923 */
16924static int
16925xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
16926 xmlSchemaPSVIIDCKeyPtr key)
16927{
16928 /*
16929 * Add to gobal list.
16930 */
16931 if (vctxt->idcKeys == NULL) {
16932 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
16933 xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
16934 if (vctxt->idcKeys == NULL) {
16935 xmlSchemaVErrMemory(vctxt,
16936 "allocating the IDC key storage list", NULL);
16937 return (-1);
16938 }
16939 vctxt->sizeIdcKeys = 40;
16940 } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
16941 vctxt->sizeIdcKeys *= 2;
16942 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
16943 xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
16944 sizeof(xmlSchemaPSVIIDCKeyPtr));
16945 if (vctxt->idcKeys == NULL) {
16946 xmlSchemaVErrMemory(vctxt,
16947 "re-allocating the IDC key storage list", NULL);
16948 return (-1);
16949 }
16950 }
16951 vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
16952
16953 return (0);
16954}
16955
16956/**
16957 * xmlSchemaIDCAppendNodeTableItem:
16958 * @bind: the IDC binding
16959 * @ntItem: the node-table item
16960 *
16961 * Appends the IDC node-table item to the binding.
16962 *
16963 * Returns 0 on success and -1 on internal errors.
16964 */
16965static int
16966xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
16967 xmlSchemaPSVIIDCNodePtr ntItem)
16968{
16969 if (bind->nodeTable == NULL) {
16970 bind->sizeNodes = 10;
16971 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
16972 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
16973 if (bind->nodeTable == NULL) {
16974 xmlSchemaVErrMemory(NULL,
16975 "allocating an array of IDC node-table items", NULL);
16976 return(-1);
16977 }
16978 } else if (bind->sizeNodes <= bind->nbNodes) {
16979 bind->sizeNodes *= 2;
16980 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
16981 xmlRealloc(bind->nodeTable, bind->sizeNodes *
16982 sizeof(xmlSchemaPSVIIDCNodePtr));
16983 if (bind->nodeTable == NULL) {
16984 xmlSchemaVErrMemory(NULL,
16985 "re-allocating an array of IDC node-table items", NULL);
16986 return(-1);
16987 }
16988 }
16989 bind->nodeTable[bind->nbNodes++] = ntItem;
16990 return(0);
16991}
16992
16993/**
16994 * xmlSchemaIDCAquireBinding:
16995 * @vctxt: the WXS validation context
16996 * @matcher: the IDC matcher
16997 *
16998 * Looks up an PSVI IDC binding, for the IDC definition and
16999 * of the given matcher. If none found, a new one is created
17000 * and added to the IDC table.
17001 *
17002 * Returns an IDC binding or NULL on internal errors.
17003 */
17004static xmlSchemaPSVIIDCBindingPtr
17005xmlSchemaIDCAquireBinding(xmlSchemaValidCtxtPtr vctxt,
17006 xmlSchemaIDCMatcherPtr matcher)
17007{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017008 xmlSchemaNodeInfoPtr info;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017009
17010 info = vctxt->elemInfos[matcher->depth];
17011
17012 if (info->idcTable == NULL) {
17013 info->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
17014 if (info->idcTable == NULL)
17015 return (NULL);
17016 return(info->idcTable);
17017 } else {
17018 xmlSchemaPSVIIDCBindingPtr bind = NULL;
17019
17020 bind = info->idcTable;
17021 do {
17022 if (bind->definition == matcher->aidc->def)
17023 return(bind);
17024 if (bind->next == NULL) {
17025 bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
17026 if (bind->next == NULL)
17027 return (NULL);
17028 return(bind->next);
17029 }
17030 bind = bind->next;
17031 } while (bind != NULL);
17032 }
17033 return (NULL);
17034}
17035
17036/**
17037 * xmlSchemaIDCFreeKey:
17038 * @key: the IDC key
17039 *
17040 * Frees an IDC key together with its compiled value.
17041 */
17042static void
17043xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
17044{
17045 if (key->compValue != NULL)
17046 xmlSchemaFreeValue(key->compValue);
17047 xmlFree(key);
17048}
17049
17050/**
17051 * xmlSchemaIDCFreeBinding:
17052 *
17053 * Frees an IDC binding. Note that the node table-items
17054 * are not freed.
17055 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017056static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017057xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
17058{
17059 if (bind->nodeTable != NULL) {
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017060 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
17061 int i;
17062 /*
17063 * Node-table items for keyrefs are not stored globally
17064 * to the validation context, since they are not bubbled.
17065 * We need to free them here.
17066 */
17067 for (i = 0; i < bind->nbNodes; i++) {
17068 xmlFree(bind->nodeTable[i]->keys);
17069 xmlFree(bind->nodeTable[i]);
17070 }
17071 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017072 xmlFree(bind->nodeTable);
17073 }
17074 xmlFree(bind);
17075}
17076
17077/**
17078 * xmlSchemaIDCFreeIDCTable:
17079 * @bind: the first IDC binding in the list
17080 *
17081 * Frees an IDC table, i.e. all the IDC bindings in the list.
17082 */
17083static void
17084xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
17085{
17086 xmlSchemaPSVIIDCBindingPtr prev;
17087
17088 while (bind != NULL) {
17089 prev = bind;
17090 bind = bind->next;
17091 xmlSchemaIDCFreeBinding(prev);
17092 }
17093}
17094
17095/**
17096 * xmlSchemaIDCFreeMatcherList:
17097 * @matcher: the first IDC matcher in the list
17098 *
17099 * Frees a list of IDC matchers.
17100 */
17101static void
17102xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
17103{
17104 xmlSchemaIDCMatcherPtr next;
17105
17106 while (matcher != NULL) {
17107 next = matcher->next;
17108 if (matcher->keySeqs != NULL) {
17109 int i;
17110 for (i = 0; i < matcher->sizeKeySeqs; i++)
17111 if (matcher->keySeqs[i] != NULL)
17112 xmlFree(matcher->keySeqs[i]);
17113 xmlFree(matcher->keySeqs);
17114 }
17115 xmlFree(matcher);
17116 matcher = next;
17117 }
17118}
17119
17120/**
17121 * xmlSchemaAreValuesEqual:
17122 * @ta: the first type
17123 * @a: the first value
17124 * @tb: the second type
17125 * @b: the second value
17126 *
17127 * Compares two values.
17128 *
17129 * Returns 1 if they are equal, 0 if not and -1 on internal errors.
17130 */
17131static int
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017132xmlSchemaAreValuesEqual(xmlSchemaValidCtxtPtr vctxt,
17133 xmlSchemaTypePtr ta,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017134 xmlSchemaValPtr a,
17135 xmlSchemaTypePtr tb,
17136 xmlSchemaValPtr b)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017137{
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017138 /* Same user derived/built-in derived/built-in primitive types. */
17139 if (ta == tb)
17140 goto compareValue;
17141
17142 /*
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017143 * Note that comparison with anySimpleTypes with be supported for
17144 * string based types as well.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017145 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017146#if 0
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017147 if ((ta->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
17148 (tb->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
17149 return(0);
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017150#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017151
17152 /*
17153 * 4.2.1 equal (data-types)
17154 *
17155 * the ·value space·s of all ·primitive· datatypes are disjoint
17156 * (they do not share any values)
17157 */
17158 if ((ta->builtInType != 0) && (tb->builtInType != 0) &&
17159 (ta->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE) &&
17160 (tb->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
17161 return(0);
17162
17163 if ((ta->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
17164 (ta->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) ||
17165 (tb->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
17166 (tb->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)) {
17167 TODO
17168 return(0);
17169 }
17170 /*
17171 * (1) if a datatype T' is ·derived· by ·restriction· from an atomic datatype
17172 * T then the ·value space· of T' is a subset of the ·value space· of T.
17173 */
17174 /*
17175 * (2) if datatypes T' and T'' are ·derived· by ·restriction· from a common
17176 * atomic ancestor T then the ·value space·s of T' and T'' may overlap.
17177 */
17178
17179 {
17180 xmlSchemaTypePtr pta = ta, ptb = tb;
17181
17182 /* Note that we will compare the primitives here. */
17183 while ((pta->builtInType == 0) ||
17184 ((pta->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE) == 0))
17185 pta = pta->baseType;
17186 while ((ptb->builtInType == 0) ||
17187 ((ptb->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE) == 0))
17188 ptb = ptb->baseType;
17189 if (pta == ptb)
17190 goto compareValue;
17191 return(0);
17192 }
17193compareValue:
17194 {
17195#ifdef IDC_VALUE_SUPPORT
17196 int ret;
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000017197 int aws, bws;
17198
17199 aws = xmlSchemaGetWhiteSpaceFacetValue(ta);
17200 bws = xmlSchemaGetWhiteSpaceFacetValue(tb);
17201
17202 ret = xmlSchemaCompareValuesWhtsp(
17203 a, (xmlSchemaWhitespaceValueType) aws,
17204 b, (xmlSchemaWhitespaceValueType) bws);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017205 if (ret == 0)
17206 return(1);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017207 else if (ret == -2) {
17208 xmlSchemaVErr(vctxt, vctxt->node,
17209 XML_SCHEMAV_INTERNAL,
17210 "Internal error: xmlSchemaAreValuesEqual, "
17211 "failed to compare the values.\n",
17212 NULL, NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017213 return(-1);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017214 } else
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017215 return(0);
17216#else
17217 return (1);
17218#endif
17219 }
17220}
17221
17222/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017223 * xmlSchemaIDCAddStateObject:
17224 * @vctxt: the WXS validation context
17225 * @matcher: the IDC matcher
17226 * @sel: the XPath information
17227 * @parent: the parent "selector" state object if any
17228 * @type: "selector" or "field"
17229 *
17230 * Creates/reuses and activates state objects for the given
17231 * XPath information; if the XPath expression consists of unions,
17232 * multiple state objects are created for every unioned expression.
17233 *
17234 * Returns 0 on success and -1 on internal errors.
17235 */
17236static int
17237xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
17238 xmlSchemaIDCMatcherPtr matcher,
17239 xmlSchemaIDCSelectPtr sel,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017240 int type)
17241{
17242 xmlSchemaIDCStateObjPtr sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017243
17244 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017245 * Reuse the state objects from the pool.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017246 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017247 if (vctxt->xpathStatePool != NULL) {
17248 sto = vctxt->xpathStatePool;
17249 vctxt->xpathStatePool = sto->next;
17250 sto->next = NULL;
17251 } else {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017252 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017253 * Create a new state object.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017254 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017255 sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
17256 if (sto == NULL) {
17257 xmlSchemaVErrMemory(NULL,
17258 "allocating an IDC state object", NULL);
17259 return (-1);
17260 }
17261 memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
17262 }
17263 /*
17264 * Add to global list.
17265 */
17266 if (vctxt->xpathStates != NULL)
17267 sto->next = vctxt->xpathStates;
17268 vctxt->xpathStates = sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017269
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017270 /*
17271 * Free the old xpath validation context.
17272 */
17273 if (sto->xpathCtxt != NULL)
17274 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
17275
17276 /*
17277 * Create a new XPath (pattern) validation context.
17278 */
17279 sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
17280 (xmlPatternPtr) sel->xpathComp);
17281 if (sto->xpathCtxt == NULL) {
17282 xmlSchemaVErr(vctxt, vctxt->node,
17283 XML_SCHEMAV_INTERNAL,
17284 "Internal error: xmlSchemaIDCAddStateObject, "
17285 "failed to create the XPath validation context.\n",
17286 NULL, NULL);
17287 return (-1);
17288 }
17289 sto->type = type;
17290 sto->depth = vctxt->depth;
17291 sto->matcher = matcher;
17292 sto->sel = sel;
17293 sto->nbHistory = 0;
17294
17295#if DEBUG_IDC
17296 xmlGenericError(xmlGenericErrorContext, "IDC: STO push '%s'\n",
17297 sto->sel->xpath);
17298#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017299 return (0);
17300}
17301
17302/**
17303 * xmlSchemaXPathEvaluate:
17304 * @vctxt: the WXS validation context
17305 * @nodeType: the nodeType of the current node
17306 *
17307 * Evaluates all active XPath state objects.
17308 *
17309 * Returns the number of IC "field" state objects which resolved to
17310 * this node, 0 if none resolved and -1 on internal errors.
17311 */
17312static int
17313xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017314 xmlElementType nodeType)
17315{
17316 xmlSchemaIDCStateObjPtr sto, head = NULL, first;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017317 int res, resolved = 0, depth = vctxt->depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017318
17319 if (vctxt->xpathStates == NULL)
17320 return (0);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017321
17322 if (nodeType == XML_ATTRIBUTE_NODE)
17323 depth++;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017324#if DEBUG_IDC
17325 {
17326 xmlChar *str = NULL;
17327 xmlGenericError(xmlGenericErrorContext,
17328 "IDC: EVAL on %s, depth %d, type %d\n",
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017329 xmlSchemaFormatNsUriLocal(&str, vctxt->nodeInfo->namespaceName,
17330 vctxt->nodeInfo->localName), depth, nodeType);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017331 FREE_AND_NULL(str)
17332 }
17333#endif
17334 /*
17335 * Process all active XPath state objects.
17336 */
17337 first = vctxt->xpathStates;
17338 sto = first;
17339 while (sto != head) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017340#if DEBUG_IDC
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017341 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017342 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] selector '%s'\n",
17343 sto->matcher->aidc->def->name, sto->sel->xpath);
17344 else
17345 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] field '%s'\n",
17346 sto->matcher->aidc->def->name, sto->sel->xpath);
17347#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017348
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017349#ifdef IDC_XPATH_SUPPORT
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017350 if (nodeType == XML_ELEMENT_NODE)
17351 res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
17352 vctxt->nodeInfo->localName, vctxt->nodeInfo->namespaceName);
17353 else
17354 res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
17355 vctxt->nodeInfo->localName, vctxt->nodeInfo->namespaceName);
17356
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017357#else
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017358 res = 0;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017359#endif
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017360 if (res == -1) {
17361 xmlSchemaVErr(vctxt, vctxt->node,
17362 XML_SCHEMAV_INTERNAL,
17363 "Internal error: xmlSchemaXPathEvaluate, "
17364 "failed to evaluate a node.\n",
17365 NULL, NULL);
17366 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017367 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017368 if (res == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017369 goto next_sto;
17370 /*
17371 * Full match.
17372 */
17373#if DEBUG_IDC
17374 xmlGenericError(xmlGenericErrorContext, "IDC: "
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017375 "MATCH\n");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017376#endif
17377 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017378 * Register a match in the state object history.
17379 */
17380 if (sto->history == NULL) {
17381 sto->history = (int *) xmlMalloc(5 * sizeof(int));
17382 if (sto->history == NULL) {
17383 xmlSchemaVErrMemory(NULL,
17384 "allocating the state object history", NULL);
17385 return(-1);
17386 }
17387 sto->sizeHistory = 10;
17388 } else if (sto->sizeHistory <= sto->nbHistory) {
17389 sto->sizeHistory *= 2;
17390 sto->history = (int *) xmlRealloc(sto->history,
17391 sto->sizeHistory * sizeof(int));
17392 if (sto->history == NULL) {
17393 xmlSchemaVErrMemory(NULL,
17394 "re-allocating the state object history", NULL);
17395 return(-1);
17396 }
17397 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017398 sto->history[sto->nbHistory++] = depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017399
17400#ifdef DEBUG_IDC
17401 xmlGenericError(xmlGenericErrorContext, "IDC: push match '%d'\n",
17402 vctxt->depth);
17403#endif
17404
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017405 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
17406 xmlSchemaIDCSelectPtr sel;
17407 /*
17408 * Activate state objects for the IDC fields of
17409 * the IDC selector.
17410 */
17411#if DEBUG_IDC
17412 xmlGenericError(xmlGenericErrorContext, "IDC: "
17413 "activating field states\n");
17414#endif
17415 sel = sto->matcher->aidc->def->fields;
17416 while (sel != NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017417 if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
17418 sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
17419 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017420 sel = sel->next;
17421 }
17422 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
17423 /*
17424 * An IDC key node was found.
17425 */
17426#if DEBUG_IDC
17427 xmlGenericError(xmlGenericErrorContext,
17428 "IDC: key found\n");
17429#endif
17430 /*
17431 * Notify that the character value of this node is
17432 * needed.
17433 */
17434 if (resolved == 0)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017435 vctxt->nodeInfo->flags |= XML_SCHEMA_ELEM_INFO_VALUE_NEEDED;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017436 resolved++;
17437 }
17438next_sto:
17439 if (sto->next == NULL) {
17440 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017441 * Evaluate field state objects created on this node as well.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017442 */
17443 head = first;
17444 sto = vctxt->xpathStates;
17445 } else
17446 sto = sto->next;
17447 }
17448 return (resolved);
17449}
17450
17451/**
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017452 * xmlSchemaXPathProcessHistory:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017453 * @vctxt: the WXS validation context
17454 * @type: the simple/complex type of the current node if any at all
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017455 * @compValue: the precompiled value
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017456 *
17457 * Processes and pops the history items of the IDC state objects.
17458 * IDC key-sequences are validated/created on IDC bindings.
17459 *
17460 * Returns 0 on success and -1 on internal errors.
17461 */
17462static int
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017463xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017464 int depth)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017465{
17466 xmlSchemaIDCStateObjPtr sto, nextsto;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017467 int res, matchDepth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017468 xmlSchemaPSVIIDCKeyPtr key = NULL;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017469 xmlSchemaTypePtr type = vctxt->nodeInfo->typeDef;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017470
17471 if (vctxt->xpathStates == NULL)
17472 return (0);
17473 sto = vctxt->xpathStates;
17474
17475#if DEBUG_IDC
17476 {
17477 xmlChar *str = NULL;
17478 xmlGenericError(xmlGenericErrorContext,
17479 "IDC: BACK on %s, depth %d\n",
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017480 xmlSchemaFormatNsUriLocal(&str, vctxt->nodeInfo->namespaceName,
17481 vctxt->nodeInfo->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017482 FREE_AND_NULL(str)
17483 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017484#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017485 /*
17486 * Evaluate the state objects.
17487 */
17488 while (sto != NULL) {
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017489#ifdef IDC_XPATH_SUPPORT
17490 xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
17491 #if DEBUG_IDC
17492 xmlGenericError(xmlGenericErrorContext, "IDC: stream pop '%s'\n",
17493 sto->sel->xpath);
17494 #endif
17495#endif
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017496 if (sto->nbHistory == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017497 goto deregister_check;
17498
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017499 matchDepth = sto->history[sto->nbHistory -1];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017500
17501 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017502 * Only matches at the current depth are of interest.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017503 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017504 if (matchDepth != depth) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017505 sto = sto->next;
17506 continue;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017507 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017508 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
17509 if (! IS_SIMPLE_TYPE(type)) {
17510 /*
17511 * Not qualified if the field resolves to a node of non
17512 * simple type.
17513 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017514 xmlSchemaStreamVCustomErr(vctxt,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017515 XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017516 vctxt->nodeInfo,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017517 (xmlSchemaTypePtr) sto->matcher->aidc->def,
17518 "The field '%s' does evaluate to a node of "
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017519 "non-simple type", sto->sel->xpath, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017520
17521 sto->nbHistory--;
17522 goto deregister_check;
17523 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017524 if ((key == NULL) && (vctxt->nodeInfo->value == NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017525 /*
17526 * Failed to provide the normalized value; maby
17527 * the value was invalid.
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017528 */
17529 xmlSchemaStreamVCustomErr(vctxt,
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000017530 XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017531 vctxt->nodeInfo,
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000017532 (xmlSchemaTypePtr) sto->matcher->aidc->def,
17533 "Warning: No precomputed value available, the value "
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017534 "was either invalid or something strange happend",
17535 NULL, NULL);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000017536 /*
17537 xmlSchemaVErr(vctxt, vctxt->nodeInfo->node,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017538 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017539 "Internal error: xmlSchemaXPathProcessHistory, "
17540 "computed value not available.\n",
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017541 NULL, NULL);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000017542 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017543 sto->nbHistory--;
17544 goto deregister_check;
17545 } else {
17546 xmlSchemaIDCMatcherPtr matcher = sto->matcher;
17547 xmlSchemaPSVIIDCKeyPtr *keySeq;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017548 int pos, idx;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017549
17550 /*
17551 * The key will be anchored on the matcher's list of
17552 * key-sequences. The position in this list is determined
17553 * by the target node's depth relative to the matcher's
17554 * depth of creation (i.e. the depth of the scope element).
17555 */
17556 pos = sto->depth - matcher->depth;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017557 idx = sto->sel->index;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017558
17559 /*
17560 * Create/grow the array of key-sequences.
17561 */
17562 if (matcher->keySeqs == NULL) {
17563 if (pos > 9)
17564 matcher->sizeKeySeqs = pos * 2;
17565 else
17566 matcher->sizeKeySeqs = 10;
17567 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
17568 xmlMalloc(matcher->sizeKeySeqs *
17569 sizeof(xmlSchemaPSVIIDCKeyPtr *));
17570 if (matcher->keySeqs == NULL) {
17571 xmlSchemaVErrMemory(NULL,
17572 "allocating an array of key-sequences",
17573 NULL);
17574 return(-1);
17575 }
17576 memset(matcher->keySeqs, 0,
17577 matcher->sizeKeySeqs *
17578 sizeof(xmlSchemaPSVIIDCKeyPtr *));
17579 } else if (pos >= matcher->sizeKeySeqs) {
17580 int i = matcher->sizeKeySeqs;
17581
17582 matcher->sizeKeySeqs *= 2;
17583 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
17584 xmlRealloc(matcher->keySeqs,
17585 matcher->sizeKeySeqs *
17586 sizeof(xmlSchemaPSVIIDCKeyPtr *));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017587 if (matcher->keySeqs == NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017588 xmlSchemaVErrMemory(NULL,
17589 "reallocating an array of key-sequences",
17590 NULL);
17591 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017592 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017593 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017594 * The array needs to be NULLed.
17595 * TODO: Use memset?
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017596 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017597 for (; i < matcher->sizeKeySeqs; i++)
17598 matcher->keySeqs[i] = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017599 }
17600
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017601 /*
17602 * Get/create the key-sequence.
17603 */
17604 keySeq = matcher->keySeqs[pos];
17605 if (keySeq == NULL) {
17606 goto create_sequence;
17607 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017608 if (keySeq[idx] != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017609 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017610 * cvc-identity-constraint:
17611 * 3 For each node in the ·target node set· all
17612 * of the {fields}, with that node as the context
17613 * node, evaluate to either an empty node-set or
17614 * a node-set with exactly one member, which must
17615 * have a simple type.
17616 *
17617 * The key was already set; report an error.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017618 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017619 xmlSchemaStreamVCustomErr(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017620 XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017621 vctxt->nodeInfo,
17622 (xmlSchemaTypePtr) matcher->aidc->def,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017623 "The field '%s' evaluates to a node-set "
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017624 "with more than one member",
17625 sto->sel->xpath, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017626 sto->nbHistory--;
17627 goto deregister_check;
17628 } else {
17629 goto create_key;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017630 }
17631 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017632
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017633create_sequence:
17634 /*
17635 * Create a key-sequence.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017636 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017637 keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
17638 matcher->aidc->def->nbFields *
17639 sizeof(xmlSchemaPSVIIDCKeyPtr));
17640 if (keySeq == NULL) {
17641 xmlSchemaVErrMemory(NULL,
17642 "allocating an IDC key-sequence", NULL);
17643 return(-1);
17644 }
17645 memset(keySeq, 0, matcher->aidc->def->nbFields *
17646 sizeof(xmlSchemaPSVIIDCKeyPtr));
17647 matcher->keySeqs[pos] = keySeq;
17648create_key:
17649 /*
17650 * Created a key once per node only.
17651 */
17652 if (key == NULL) {
17653 key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
17654 sizeof(xmlSchemaPSVIIDCKey));
17655 if (key == NULL) {
17656 xmlSchemaVErrMemory(NULL,
17657 "allocating a IDC key", NULL);
17658 xmlFree(keySeq);
17659 matcher->keySeqs[pos] = NULL;
17660 return(-1);
17661 }
17662 /*
17663 * Consume the compiled value.
17664 */
17665 key->type = type;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017666 key->compValue = vctxt->nodeInfo->value;
17667 vctxt->nodeInfo->value = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017668 /*
17669 * Store the key in a global list.
17670 */
17671 if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
17672 xmlSchemaIDCFreeKey(key);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017673 return (-1);
17674 }
17675 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017676 keySeq[idx] = key;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017677 }
17678 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017679
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017680 xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
17681 xmlSchemaPSVIIDCBindingPtr bind;
17682 xmlSchemaPSVIIDCNodePtr ntItem;
17683 xmlSchemaIDCMatcherPtr matcher;
17684 xmlSchemaIDCPtr idc;
17685 int pos, i, j, nbKeys;
17686 /*
17687 * Here we have the following scenario:
17688 * An IDC 'selector' state object resolved to a target node,
17689 * during the time this target node was in the
17690 * ancestor-or-self axis, the 'field' state object(s) looked
17691 * out for matching nodes to create a key-sequence for this
17692 * target node. Now we are back to this target node and need
17693 * to put the key-sequence, together with the target node
17694 * itself, into the node-table of the corresponding IDC
17695 * binding.
17696 */
17697 matcher = sto->matcher;
17698 idc = matcher->aidc->def;
17699 nbKeys = idc->nbFields;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017700 pos = depth - matcher->depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017701 /*
17702 * Check if the matcher has any key-sequences at all, plus
17703 * if it has a key-sequence for the current target node.
17704 */
17705 if ((matcher->keySeqs == NULL) ||
17706 (matcher->sizeKeySeqs <= pos)) {
17707 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
17708 goto selector_key_error;
17709 else
17710 goto selector_leave;
17711 }
17712
17713 keySeq = &(matcher->keySeqs[pos]);
17714 if (*keySeq == NULL) {
17715 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
17716 goto selector_key_error;
17717 else
17718 goto selector_leave;
17719 }
17720
17721 for (i = 0; i < nbKeys; i++) {
17722 if ((*keySeq)[i] == NULL) {
17723 /*
17724 * Not qualified, if not all fields did resolve.
17725 */
17726 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
17727 /*
17728 * All fields of a "key" IDC must resolve.
17729 */
17730 goto selector_key_error;
17731 }
17732 goto selector_leave;
17733 }
17734 }
17735 /*
17736 * All fields did resolve.
17737 */
17738
17739 /*
17740 * 4.1 If the {identity-constraint category} is unique(/key),
17741 * then no two members of the ·qualified node set· have
17742 * ·key-sequences· whose members are pairwise equal, as
17743 * defined by Equal in [XML Schemas: Datatypes].
17744 *
17745 * Get the IDC binding from the matcher and check for
17746 * duplicate key-sequences.
17747 */
17748 bind = xmlSchemaIDCAquireBinding(vctxt, matcher);
17749 if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
17750 (bind->nbNodes != 0)) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017751 xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017752
17753 i = 0;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017754 res = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017755 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017756 * Compare the key-sequences, key by key.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017757 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017758 do {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017759 bkeySeq = bind->nodeTable[i]->keys;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017760 for (j = 0; j < nbKeys; j++) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017761 ckey = (*keySeq)[j];
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017762 bkey = bkeySeq[j];
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017763 res = xmlSchemaAreValuesEqual(vctxt, ckey->type,
17764 ckey->compValue, bkey->type, bkey->compValue);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017765 if (res == -1) {
17766 return (-1);
17767 } else if (res == 0)
17768 break;
17769 }
17770 if (res == 1) {
17771 /*
17772 * Duplicate found.
17773 */
17774 break;
17775 }
17776 i++;
17777 } while (i < bind->nbNodes);
17778 if (i != bind->nbNodes) {
17779 /*
17780 * TODO: Try to report the key-sequence.
17781 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017782 xmlSchemaStreamVCustomErr(vctxt,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017783 XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017784 vctxt->nodeInfo,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017785 (xmlSchemaTypePtr) idc,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017786 "Duplicate key-sequence found", NULL, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017787
17788 goto selector_leave;
17789 }
17790 }
17791 /*
17792 * Add a node-table item to the IDC binding.
17793 */
17794 ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
17795 sizeof(xmlSchemaPSVIIDCNode));
17796 if (ntItem == NULL) {
17797 xmlSchemaVErrMemory(NULL,
17798 "allocating an IDC node-table item", NULL);
17799 xmlFree(*keySeq);
17800 *keySeq = NULL;
17801 return(-1);
17802 }
17803 memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
17804
17805 /*
17806 * Store the node-table item on global list.
17807 */
17808 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
17809 if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
17810 xmlFree(ntItem);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017811 xmlFree(*keySeq);
17812 *keySeq = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017813 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017814 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017815 }
17816 /*
17817 * Init the node-table item. Consume the key-sequence.
17818 */
17819 ntItem->node = vctxt->node;
17820 ntItem->keys = *keySeq;
17821 *keySeq = NULL;
17822 if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1) {
17823 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
17824 /*
17825 * Free the item, since keyref items won't be
17826 * put on a global list.
17827 */
17828 xmlFree(ntItem->keys);
17829 xmlFree(ntItem);
17830 }
17831 return (-1);
17832 }
17833
17834 goto selector_leave;
17835selector_key_error:
17836 /*
17837 * 4.2.1 (KEY) The ·target node set· and the
17838 * ·qualified node set· are equal, that is, every
17839 * member of the ·target node set· is also a member
17840 * of the ·qualified node set· and vice versa.
17841 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017842 xmlSchemaStreamVCustomErr(vctxt,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017843 XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017844 vctxt->nodeInfo,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017845 (xmlSchemaTypePtr) idc,
17846 "All 'key' fields must evaluate to a node",
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017847 NULL, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017848selector_leave:
17849 /*
17850 * Free the key-sequence if not added to the IDC table.
17851 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017852 if ((keySeq != NULL) && (*keySeq != NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017853 xmlFree(*keySeq);
17854 *keySeq = NULL;
17855 }
17856 } /* if selector */
17857
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017858 sto->nbHistory--;
17859
17860deregister_check:
17861 /*
17862 * Deregister state objects if they reach the depth of creation.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017863 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017864 if ((sto->nbHistory == 0) && (sto->depth == depth)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017865#if DEBUG_IDC
17866 xmlGenericError(xmlGenericErrorContext, "IDC: STO pop '%s'\n",
17867 sto->sel->xpath);
17868#endif
17869 if (vctxt->xpathStates != sto) {
17870 xmlSchemaVErr(vctxt, vctxt->node,
17871 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017872 "Internal error: xmlSchemaXPathProcessHistory, "
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017873 "The state object to be removed is not the first "
17874 "in the list.\n",
17875 NULL, NULL);
17876 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017877 nextsto = sto->next;
17878 /*
17879 * Unlink from the list of active XPath state objects.
17880 */
17881 vctxt->xpathStates = sto->next;
17882 sto->next = vctxt->xpathStatePool;
17883 /*
17884 * Link it to the pool of reusable state objects.
17885 */
17886 vctxt->xpathStatePool = sto;
17887 sto = nextsto;
17888 } else
17889 sto = sto->next;
17890 } /* while (sto != NULL) */
17891 return (0);
17892}
17893
17894/**
17895 * xmlSchemaIDCRegisterMatchers:
17896 * @vctxt: the WXS validation context
17897 * @elemDecl: the element declaration
17898 *
17899 * Creates helper objects to evaluate IDC selectors/fields
17900 * successively.
17901 *
17902 * Returns 0 if OK and -1 on internal errors.
17903 */
17904static int
17905xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
17906 xmlSchemaElementPtr elemDecl)
17907{
17908 xmlSchemaIDCMatcherPtr matcher, last = NULL;
17909 xmlSchemaIDCPtr idc, refIdc;
17910 xmlSchemaIDCAugPtr aidc;
17911
17912 idc = (xmlSchemaIDCPtr) elemDecl->idcs;
17913 if (idc == NULL)
17914 return (0);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017915
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017916#if DEBUG_IDC
17917 {
17918 xmlChar *str = NULL;
17919 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017920 "IDC: REGISTER on %s, depth %d\n",
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017921 (char *) xmlSchemaFormatNsUriLocal(&str, vctxt->nodeInfo->namespaceName,
17922 vctxt->nodeInfo->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017923 FREE_AND_NULL(str)
17924 }
17925#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017926 if (vctxt->nodeInfo->idcMatchers != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017927 xmlSchemaVErr(vctxt, vctxt->node,
17928 XML_SCHEMAV_INTERNAL,
17929 "Internal error: xmlSchemaIDCRegisterMatchers: "
17930 "The chain of IDC matchers is expected to be empty.\n",
17931 NULL, NULL);
17932 return (-1);
17933 }
17934 do {
17935 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
17936 /*
17937 * Since IDCs bubbles are expensive we need to know the
17938 * depth at which the bubbles should stop; this will be
17939 * the depth of the top-most keyref IDC. If no keyref
17940 * references a key/unique IDC, the bubbleDepth will
17941 * be -1, indicating that no bubbles are needed.
17942 */
17943 refIdc = (xmlSchemaIDCPtr) idc->ref->item;
17944 if (refIdc != NULL) {
17945 /*
17946 * Lookup the augmented IDC.
17947 */
17948 aidc = vctxt->aidcs;
17949 while (aidc != NULL) {
17950 if (aidc->def == refIdc)
17951 break;
17952 aidc = aidc->next;
17953 }
17954 if (aidc == NULL) {
17955 xmlSchemaVErr(vctxt, vctxt->node,
17956 XML_SCHEMAV_INTERNAL,
17957 "Internal error: xmlSchemaIDCRegisterMatchers: "
17958 "Could not find an augmented IDC item for an IDC "
17959 "definition.\n",
17960 NULL, NULL);
17961 return (-1);
17962 }
17963 if ((aidc->bubbleDepth == -1) ||
17964 (vctxt->depth < aidc->bubbleDepth))
17965 aidc->bubbleDepth = vctxt->depth;
17966 }
17967 }
17968 /*
17969 * Lookup the augmented IDC item for the IDC definition.
17970 */
17971 aidc = vctxt->aidcs;
17972 while (aidc != NULL) {
17973 if (aidc->def == idc)
17974 break;
17975 aidc = aidc->next;
17976 }
17977 if (aidc == NULL) {
17978 xmlSchemaVErr(vctxt, vctxt->node,
17979 XML_SCHEMAV_INTERNAL,
17980 "Internal error: xmlSchemaIDCRegisterMatchers: "
17981 "Could not find an augmented IDC item for an IDC definition.\n",
17982 NULL, NULL);
17983 return (-1);
17984 }
17985 /*
17986 * Create an IDC matcher for every IDC definition.
17987 */
17988 matcher = (xmlSchemaIDCMatcherPtr)
17989 xmlMalloc(sizeof(xmlSchemaIDCMatcher));
17990 if (matcher == NULL) {
17991 xmlSchemaVErrMemory(vctxt,
17992 "allocating an IDC matcher", NULL);
17993 return (-1);
17994 }
17995 memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
17996 if (last == NULL)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017997 vctxt->nodeInfo->idcMatchers = matcher;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017998 else
17999 last->next = matcher;
18000 last = matcher;
18001
18002 matcher->type = IDC_MATCHER;
18003 matcher->depth = vctxt->depth;
18004 matcher->aidc = aidc;
18005#if DEBUG_IDC
18006 xmlGenericError(xmlGenericErrorContext, "IDC: register matcher\n");
18007#endif
18008 /*
18009 * Init the automaton state object.
18010 */
18011 if (xmlSchemaIDCAddStateObject(vctxt, matcher,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018012 idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018013 return (-1);
18014
18015 idc = idc->next;
18016 } while (idc != NULL);
18017 return (0);
18018}
18019
18020/**
18021 * xmlSchemaBubbleIDCNodeTables:
18022 * @depth: the current tree depth
18023 *
18024 * Merges IDC bindings of an element at @depth into the corresponding IDC
18025 * bindings of its parent element. If a duplicate note-table entry is found,
18026 * both, the parent node-table entry and child entry are discarded from the
18027 * node-table of the parent.
18028 *
18029 * Returns 0 if OK and -1 on internal errors.
18030 */
18031static int
18032xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
18033{
18034 xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018035 xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL, lastParBind = NULL; /* parent IDC bindings. */
18036 xmlSchemaPSVIIDCNodePtr node, parNode = NULL; /* node-table entries. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018037 xmlSchemaPSVIIDCKeyPtr key, parKey; /* keys of in a key-sequence. */
18038 xmlSchemaIDCAugPtr aidc;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018039 int i, j, k, ret = 0, oldNum, newDupls = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018040 int duplTop;
18041
18042 /*
18043 * The node table has the following sections:
18044 *
18045 * O --> old node-table entries (first)
18046 * O
18047 * + --> new node-table entries
18048 * +
18049 * % --> new duplicate node-table entries
18050 * %
18051 * # --> old duplicate node-table entries
18052 * # (last)
18053 *
18054 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018055 bind = vctxt->nodeInfo->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018056 if (bind == NULL) {
18057 /* Fine, no table, no bubbles. */
18058 return (0);
18059 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018060
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018061 parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
18062 /*
18063 * Walk all bindings; create new or add to existing bindings.
18064 * Remove duplicate key-sequences.
18065 */
18066start_binding:
18067 while (bind != NULL) {
18068 /*
18069 * Skip keyref IDCs.
18070 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018071 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
18072 bind = bind->next;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018073 continue;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018074 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018075 /*
18076 * Check if the key/unique IDC table needs to be bubbled.
18077 */
18078 aidc = vctxt->aidcs;
18079 do {
18080 if (aidc->def == bind->definition) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018081 if (aidc->bubbleDepth >= vctxt->depth) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018082 bind = bind->next;
18083 goto start_binding;
18084 }
18085 break;
18086 }
18087 aidc = aidc->next;
18088 } while (aidc != NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018089
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018090 if (parTable != NULL)
18091 parBind = *parTable;
18092 while (parBind != NULL) {
18093 /*
18094 * Search a matching parent binding for the
18095 * IDC definition.
18096 */
18097 if (parBind->definition == bind->definition) {
18098
18099 /*
18100 * Compare every node-table entry of the child node,
18101 * i.e. the key-sequence within, ...
18102 */
18103 oldNum = parBind->nbNodes; /* Skip newly added items. */
18104 duplTop = oldNum + parBind->nbDupls;
18105
18106 for (i = 0; i < bind->nbNodes; i++) {
18107 node = bind->nodeTable[i];
18108 if (node == NULL)
18109 continue;
18110 /*
18111 * ...with every key-sequence of the parent node, already
18112 * evaluated to be a duplicate key-sequence.
18113 */
18114 if (parBind->nbDupls != 0) {
18115 j = bind->nbNodes + newDupls;
18116 while (j < duplTop) {
18117 parNode = parBind->nodeTable[j];
18118 for (k = 0; k < bind->definition->nbFields; k++) {
18119 key = node->keys[k];
18120 parKey = parNode->keys[k];
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018121 ret = xmlSchemaAreValuesEqual(vctxt, key->type,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018122 key->compValue,
18123 parKey->type, parKey->compValue);
18124 if (ret == -1) {
18125 /* TODO: Internal error */
18126 return(-1);
18127 } else if (ret == 0)
18128 break;
18129
18130 }
18131 if (ret == 1)
18132 /* Duplicate found. */
18133 break;
18134 j++;
18135 }
18136 if (j != duplTop) {
18137 /* Duplicate found. */
18138 continue;
18139 }
18140 }
18141 /*
18142 * ... and with every key-sequence of the parent node.
18143 */
18144 j = 0;
18145 while (j < oldNum) {
18146 parNode = parBind->nodeTable[j];
18147 /*
18148 * Compare key by key.
18149 */
18150 for (k = 0; k < parBind->definition->nbFields; k++) {
18151 key = node->keys[k];
18152 parKey = parNode->keys[k];
18153
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018154 ret = xmlSchemaAreValuesEqual(vctxt, key->type,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018155 key->compValue,
18156 parKey->type, parKey->compValue);
18157 if (ret == -1) {
18158 /* TODO: Internal error */
18159 } else if (ret == 0)
18160 break;
18161
18162 }
18163 if (ret == 1)
18164 /*
18165 * The key-sequences are equal.
18166 */
18167 break;
18168 j++;
18169 }
18170 if (j != oldNum) {
18171 /*
18172 * Handle duplicates.
18173 */
18174 newDupls++;
18175 oldNum--;
18176 parBind->nbNodes--;
18177 /*
18178 * Move last old item to pos of duplicate.
18179 */
18180 parBind->nodeTable[j] =
18181 parBind->nodeTable[oldNum];
18182
18183 if (parBind->nbNodes != oldNum) {
18184 /*
18185 * If new items exist, move last new item to
18186 * last of old items.
18187 */
18188 parBind->nodeTable[oldNum] =
18189 parBind->nodeTable[parBind->nbNodes];
18190 }
18191 /*
18192 * Move duplicate to last pos of new/old items.
18193 */
18194 parBind->nodeTable[parBind->nbNodes] = parNode;
18195
18196 } else {
18197 /*
18198 * Add the node-table entry (node and key-sequence) of
18199 * the child node to the node table of the parent node.
18200 */
18201 if (parBind->nodeTable == NULL) {
18202 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
18203 xmlMalloc(1 * sizeof(xmlSchemaPSVIIDCNodePtr));
18204 if (parBind->nodeTable == NULL) {
18205 xmlSchemaVErrMemory(NULL,
18206 "allocating IDC list of node-table items", NULL);
18207 return(-1);
18208 }
18209 parBind->sizeNodes = 1;
18210 } else if (duplTop >= parBind->sizeNodes) {
18211 parBind->sizeNodes++;
18212 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
18213 xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
18214 sizeof(xmlSchemaPSVIIDCNodePtr));
18215 if (parBind->nodeTable == NULL) {
18216 xmlSchemaVErrMemory(NULL,
18217 "re-allocating IDC list of node-table items", NULL);
18218 return(-1);
18219 }
18220 }
18221
18222 /*
18223 * Move first old duplicate to last position
18224 * of old duplicates +1.
18225 */
18226 if (parBind->nbDupls != 0) {
18227 parBind->nodeTable[duplTop] =
18228 parBind->nodeTable[parBind->nbNodes + newDupls];
18229 }
18230 /*
18231 * Move first new duplicate to last position of
18232 * new duplicates +1.
18233 */
18234 if (newDupls != 0) {
18235 parBind->nodeTable[parBind->nbNodes + newDupls] =
18236 parBind->nodeTable[parBind->nbNodes];
18237 }
18238 /*
18239 * Append the new node-table entry to the 'new node-table
18240 * entries' section.
18241 */
18242 parBind->nodeTable[parBind->nbNodes] = node;
18243 parBind->nbNodes++;
18244 duplTop++;
18245 }
18246 }
18247 parBind->nbDupls += newDupls;
18248 break;
18249 }
18250 if (parBind->next == NULL)
18251 lastParBind = parBind;
18252 parBind = parBind->next;
18253 }
18254 if (parBind == NULL) {
18255 /*
18256 * No binding for the IDC was found: create a new one and
18257 * copy all node-tables.
18258 */
18259 parBind = xmlSchemaIDCNewBinding(bind->definition);
18260 if (parBind == NULL)
18261 return(-1);
18262
18263 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
18264 xmlMalloc(bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
18265 if (parBind->nodeTable == NULL) {
18266 xmlSchemaVErrMemory(NULL,
18267 "allocating an array of IDC node-table items", NULL);
18268 xmlSchemaIDCFreeBinding(parBind);
18269 return(-1);
18270 }
18271 parBind->sizeNodes = bind->nbNodes;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018272 parBind->nbNodes = bind->nbNodes;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018273 memcpy(parBind->nodeTable, bind->nodeTable,
18274 bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018275 if (*parTable == NULL)
18276 *parTable = parBind;
18277 else
18278 lastParBind->next = parBind;
18279 }
18280 bind = bind->next;
18281 }
18282 return (0);
18283}
18284
18285/**
18286 * xmlSchemaCheckCVCIDCKeyRef:
18287 * @vctxt: the WXS validation context
18288 * @elemDecl: the element declaration
18289 *
18290 * Check the cvc-idc-keyref constraints.
18291 */
18292static int
18293xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
18294{
18295 xmlSchemaPSVIIDCBindingPtr refbind, bind;
18296
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018297 refbind = vctxt->nodeInfo->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018298 /*
18299 * Find a keyref.
18300 */
18301 while (refbind != NULL) {
18302 if (refbind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
18303 int i, j, k, res;
18304 xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
18305 xmlSchemaPSVIIDCKeyPtr refKey, key;
18306
18307 /*
18308 * Find the referred key/unique.
18309 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018310 bind = vctxt->nodeInfo->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018311 do {
18312 if ((xmlSchemaIDCPtr) refbind->definition->ref->item ==
18313 bind->definition)
18314 break;
18315 bind = bind->next;
18316 } while (bind != NULL);
18317
18318 /*
18319 * Search for a matching key-sequences.
18320 */
18321 for (i = 0; i < refbind->nbNodes; i++) {
18322 res = 0;
18323 if (bind != NULL) {
18324 refKeys = refbind->nodeTable[i]->keys;
18325 for (j = 0; j < bind->nbNodes; j++) {
18326 keys = bind->nodeTable[j]->keys;
18327 for (k = 0; k < bind->definition->nbFields; k++) {
18328 refKey = refKeys[k];
18329 key = keys[k];
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018330 res = xmlSchemaAreValuesEqual(vctxt,
18331 key->type, key->compValue,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018332 refKey->type, refKey->compValue);
18333 if (res == 0)
18334 break;
18335 else if (res == -1) {
18336 return (-1);
18337 }
18338 }
18339 if (res == 1) {
18340 /*
18341 * Match found.
18342 */
18343 break;
18344 }
18345 }
18346 }
18347 if (res == 0) {
18348 /* TODO: Report the key-sequence. */
18349 xmlSchemaVCustomErr(vctxt,
18350 XML_SCHEMAV_CVC_IDC,
18351 refbind->nodeTable[i]->node,
18352 (xmlSchemaTypePtr) refbind->definition,
18353 "No matching key-sequence found", NULL);
18354 }
18355 }
18356 }
18357 refbind = refbind->next;
18358 }
18359 return (0);
18360}
18361#endif /* IDC_ENABLED */
18362
18363#ifdef ELEM_INFO_ENABLED
18364/**
18365 * xmlSchemaBeginElement:
18366 * @vctxt: the WXS validation context
18367 *
18368 * Just a temporary workaround to simulate streaming validation
18369 * a bit.
18370 */
18371static void
18372xmlSchemaBeginElement(xmlSchemaValidCtxtPtr vctxt)
18373{
18374 vctxt->depth++;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018375 vctxt->nodeInfo = xmlSchemaGetFreshElemInfo(vctxt, vctxt->depth);
18376 vctxt->nodeInfo->node = vctxt->node;
18377 vctxt->nodeInfo->localName = vctxt->node->name;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018378 if (vctxt->node->ns != NULL)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018379 vctxt->nodeInfo->namespaceName = vctxt->node->ns->href;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018380 else
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018381 vctxt->nodeInfo->namespaceName = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018382}
18383
18384/**
18385 * xmlSchemaEndElement:
18386 * @vctxt: the WXS validation context
18387 *
18388 * Just a temporary workaround to simulate streaming validation
18389 * a bit.
18390 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018391static int
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018392xmlSchemaEndElement(xmlSchemaValidCtxtPtr vctxt)
18393{
18394 if (vctxt->depth < 0) {
18395 /* TODO: raise error? */
18396 vctxt->depth--;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018397 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018398 }
18399#ifdef IDC_ENABLED
18400 /*
18401 * Evaluate the history of changes of active state objects.
18402 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018403 if (xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1)
18404 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018405
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018406 if (vctxt->nodeInfo->value != NULL) {
18407 xmlSchemaFreeValue(vctxt->nodeInfo->value);
18408 vctxt->nodeInfo->value = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018409 }
18410 /*
18411 * TODO: 6 The element information item must be ·valid· with respect to each of
18412 * the {identity-constraint definitions} as per Identity-constraint
18413 * Satisfied (§3.11.4).
18414 */
18415 /*
18416 * Validate IDC keyrefs.
18417 */
18418 xmlSchemaCheckCVCIDCKeyRef(vctxt);
18419#endif
18420
18421 /*
18422 * Merge/free the IDC table.
18423 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018424 if (vctxt->nodeInfo->idcTable != NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018425#ifdef IDC_ENABLED
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018426#ifdef DEBUG_IDC
18427 xmlSchemaDebugDumpIDCTable(stdout,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018428 vctxt->nodeInfo->namespaceName,
18429 vctxt->nodeInfo->localName,
18430 vctxt->nodeInfo->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018431#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018432 if (vctxt->depth > 0) {
18433 /*
18434 * Merge the IDC node table with the table of the parent node.
18435 */
18436 xmlSchemaBubbleIDCNodeTables(vctxt);
18437 }
18438 /*
18439 * TODO: Don't free the PSVI IDC tables if they are
18440 * requested for the PSVI.
18441 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018442 xmlSchemaIDCFreeIDCTable(vctxt->nodeInfo->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018443#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018444 vctxt->nodeInfo->idcTable = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018445 }
18446
18447 /*
18448 * Cleanup IDC matchers.
18449 */
18450#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018451 if (vctxt->nodeInfo->idcMatchers != NULL) {
18452 xmlSchemaIDCFreeMatcherList(vctxt->nodeInfo->idcMatchers);
18453 vctxt->nodeInfo->idcMatchers = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018454 }
18455#endif
18456
18457 /*
18458 * Skip further processing if we are on the validation root.
18459 */
18460 if (vctxt->depth == 0) {
18461 vctxt->depth--;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018462 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018463 }
18464
18465 /*
18466 * Reset the bubbleDepth if needed.
18467 */
18468#ifdef IDC_ENABLED
18469 if (vctxt->aidcs != NULL) {
18470 xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
18471 do {
18472 if (aidc->bubbleDepth == vctxt->depth) {
18473 /*
18474 * A bubbleDepth of a key/unique IDC matches the current
18475 * depth, this means that we are leaving the scope of the
18476 * top-most keyref IDC.
18477 */
18478 aidc->bubbleDepth = -1;
18479 }
18480 aidc = aidc->next;
18481 } while (aidc != NULL);
18482 }
18483#endif
18484 vctxt->depth--;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018485 /*
18486 * Clear the current elemInfo.
18487 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018488 if (vctxt->nodeInfo->value != NULL) {
18489 xmlSchemaFreeValue(vctxt->nodeInfo->value);
18490 vctxt->nodeInfo->value = NULL;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018491 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018492 vctxt->nodeInfo = vctxt->elemInfos[vctxt->depth];
18493 vctxt->node = vctxt->nodeInfo->node;
18494
18495 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018496}
18497
18498#endif /* ELEM_INFO_ENABLED */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018499
18500/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018501 * xmlSchemaValidateElementByDeclaration:
Daniel Veillard4255d502002-04-16 15:50:10 +000018502 * @ctxt: a schema validation context
18503 * @node: the top node.
18504 *
18505 * Validate the content of an element type.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018506 * Validation Rule: Element Locally Valid (Element)
Daniel Veillard4255d502002-04-16 15:50:10 +000018507 *
18508 * Returns 0 if the element is schemas valid, a positive error code
18509 * number otherwise and -1 in case of internal or API error.
18510 */
18511static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018512xmlSchemaValidateElementByDeclaration(xmlSchemaValidCtxtPtr ctxt,
18513 xmlSchemaElementPtr elemDecl)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018514{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018515 xmlNodePtr elem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018516 int ret = 0;
18517 xmlSchemaTypePtr actualType = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018518 xmlAttrPtr attr;
18519 xmlChar *attrValue;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018520 int nilled = 0, elemHasContent = -1;
Daniel Veillard3646d642004-06-02 19:19:14 +000018521
18522 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018523 * This one is called by xmlSchemaValidateElementByWildcardInternal,
18524 * xmlSchemaValidateElementByAnyType and xmlSchemaValidateElement.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018525 * Note that @elemDecl will be the declaration and never the
18526 * reference to a declaration.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018527 */
Daniel Veillard3646d642004-06-02 19:19:14 +000018528
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018529 if (ctxt == NULL) {
18530 xmlSchemaVErr(ctxt, NULL, XML_SCHEMAV_INTERNAL,
18531 "Internal error: xmlSchemaValidateElementByDeclaration, "
18532 "bad arguments.\n",
18533 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018534 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000018535 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018536
18537 elem = ctxt->node;
18538
18539 /*
18540 * cvc-elt (3.3.4) : 1
18541 */
18542 if (elemDecl == NULL) {
18543 xmlSchemaVCustomErr(ctxt,
18544 XML_SCHEMAV_CVC_ELT_1,
18545 elem, NULL,
18546 "No matching declaration available", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018547 /*
18548 * Evaluate IDCs even if an error occured.
18549 */
18550#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018551 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018552 return (-1);
18553#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018554 return (ctxt->err);
18555 }
18556 /*
18557 * cvc-elt (3.3.4) : 2
18558 */
18559 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
18560 xmlSchemaVCustomErr(ctxt,
18561 XML_SCHEMAV_CVC_ELT_2,
18562 elem, NULL,
18563 "The element declaration is abstract", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018564 /*
18565 * Evaluate IDCs even if an error occured.
18566 */
18567#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018568 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018569 return (-1);
18570#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018571 return (ctxt->err);
18572 }
18573
18574 /*
18575 * cvc-elt (3.3.4) : 3
18576 * Handle 'xsi:nil'.
18577 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018578
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018579 attr = xmlHasNsProp(elem, BAD_CAST "nil", xmlSchemaInstanceNs);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018580 if (attr != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018581 attrValue = xmlNodeGetContent((xmlNodePtr) attr);
18582 ctxt->node = (xmlNodePtr) attr;
18583 ctxt->cur = attr->children;
18584 ret = xmlSchemaValidateSimpleTypeValue(ctxt,
18585 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
18586 BAD_CAST attrValue, 1, 1, 1, 1);
18587 ctxt->node = elem;
18588 ctxt->type = (xmlSchemaTypePtr) elemDecl;
18589 if (ret < 0) {
18590 xmlSchemaVCustomErr(ctxt,
18591 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018592 (xmlNodePtr) attr, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018593 "Internal error: xmlSchemaValidateElementByDeclaration, "
18594 "validating the attribute 'xsi:nil'", NULL);
18595 if (attrValue != NULL)
18596 xmlFree(attrValue);
18597 return (-1);
18598 }
18599 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018600 /*
18601 * cvc-elt (3.3.4) : 3.1
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018602 */
18603 xmlSchemaVCustomErr(ctxt,
18604 XML_SCHEMAV_CVC_ELT_3_1,
18605 elem, NULL,
18606 "The element is not 'nillable'", NULL);
18607 } else {
18608 if (xmlStrEqual(BAD_CAST attrValue, BAD_CAST "true") ||
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018609 xmlStrEqual(BAD_CAST attrValue, BAD_CAST "1")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018610 ret = 0;
18611 /*
18612 * cvc-elt (3.3.4) : 3.2.1
18613 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018614 elemHasContent = xmlSchemaHasElemOrCharContent(elem);
18615 if (elemHasContent == 1) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018616 xmlSchemaVCustomErr(ctxt,
18617 XML_SCHEMAV_CVC_ELT_3_2_1,
18618 /* XML_SCHEMAS_ERR_NOTEMPTY, */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018619 elem, (xmlSchemaTypePtr) elemDecl,
18620 "The 'nilled' element must have no character or "
18621 "element content", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018622 ret = XML_SCHEMAV_CVC_ELT_3_2_1;
18623 }
18624 /*
18625 * cvc-elt (3.3.4) : 3.2.2
18626 */
18627 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
18628 (elemDecl->value != NULL)) {
18629 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_CVC_ELT_3_2_2,
18630 /* XML_SCHEMAS_ERR_HAVEDEFAULT, */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018631 elem, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018632 "There is a fixed value constraint defined for "
18633 "the 'nilled' element", NULL);
18634 ret = XML_SCHEMAV_CVC_ELT_3_2_2;
18635 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018636 if (ret == 0)
18637 nilled = 1;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018638 }
18639 }
18640 if (attrValue != NULL)
18641 xmlFree(attrValue);
18642 }
18643
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018644
18645 actualType = elemDecl->subtypes;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018646 /*
18647 * cvc-elt (3.3.4) : 4
18648 * Handle 'xsi:type'.
18649 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018650
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018651 attr = xmlHasNsProp(elem, BAD_CAST "type", xmlSchemaInstanceNs);
18652 if (attr != NULL) {
18653 xmlChar *nsName = NULL, *local = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018654
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018655 /*
18656 * TODO: We should report a *warning* that the type was overriden
18657 * by the instance.
18658 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018659
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018660 /*
18661 * cvc-elt (3.3.4) : 4.1
18662 */
18663 attrValue = xmlNodeGetContent((xmlNodePtr) attr);
18664 ret = xmlSchemaValQNameAcquire(attrValue, attr->parent,
18665 &nsName, &local);
18666 if (ret < 0) {
18667 xmlSchemaVCustomErr(ctxt,
18668 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018669 (xmlNodePtr) attr, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018670 "Internal error: xmlSchemaValidateElementByDeclaration, "
18671 "validating the attribute 'xsi:type'", NULL);;
18672 FREE_AND_NULL(attrValue)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018673 FREE_AND_NULL(nsName)
18674 FREE_AND_NULL(local)
18675 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018676 } else if (ret == 1) {
18677 xmlSchemaVSimpleTypeErr(ctxt,
18678 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
18679 (xmlNodePtr) attr, attrValue,
18680 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME));
18681 } else if (ret == 2) {
18682 xmlSchemaVCustomErr(ctxt,
18683 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
18684 (xmlNodePtr) attr,
18685 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
18686 "The QName value '%s' has no "
18687 "corresponding namespace declaration in scope",
18688 attrValue);
18689 } else {
18690 /*
18691 * cvc-elt (3.3.4) : 4.2
18692 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018693 actualType = xmlSchemaGetType(ctxt->schema, local, nsName);
18694 if (actualType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018695 xmlChar *strA = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018696
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018697 xmlSchemaVCustomErr(ctxt,
18698 XML_SCHEMAV_CVC_ELT_4_2,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018699 (xmlNodePtr) attr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018700 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
18701 "The value %s does not resolve to a type "
18702 "definition",
18703 xmlSchemaFormatNsUriLocal(&strA, nsName, local));
18704 FREE_AND_NULL(strA);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018705 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018706 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018707 * URGENT TODO: cvc-elt (3.3.4) : 4.3 (Type Derivation OK)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018708 */
18709 }
18710 }
18711 FREE_AND_NULL(attrValue)
18712 FREE_AND_NULL(nsName)
18713 FREE_AND_NULL(local)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018714 }
18715 /* TODO: Change the handling of missing types according to
18716 * the spec.
18717 */
18718 if (actualType == NULL) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018719 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018720 XML_SCHEMAV_CVC_TYPE_1,
18721 elem, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018722 "The type definition is absent", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018723 /*
18724 * Evaluate IDCs even if an error occured.
18725 */
18726#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018727 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018728 return (-1);
18729#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018730 return (XML_SCHEMAV_CVC_TYPE_1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018731 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018732
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018733 /*
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018734 * Remember the actual-type definition.
18735 */
18736#ifdef ELEM_INFO_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018737 ctxt->nodeInfo->typeDef = actualType;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018738#endif
18739
18740 /*
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018741 * TODO: Since this should be already checked by the content model automaton,
18742 * and we want to get rid of the XML_SCHEMAS_ERR... types, the error code
18743 * has been changed to XML_SCHEMAV_INTERNAL.
18744 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018745 /*
Daniel Veillard4255d502002-04-16 15:50:10 +000018746 if (child == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000018747 if (decl->minOccurs > 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018748 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018749 XML_SCHEMAS_ERR_MISSING,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018750 "Element %s: missing child %s\n",
18751 node->name, decl->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018752 }
18753 return (ctxt->err);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018754 }
18755 */
Daniel Veillard4255d502002-04-16 15:50:10 +000018756 /*
18757 * Verify the element matches
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018758 * TODO, FIXME: Can this still happen here? Isn't this already checked
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018759 * by the content model automaton?
Daniel Veillardc0826a72004-08-10 14:17:33 +000018760 if (!xmlStrEqual(child->name, decl->name)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018761 xmlSchemaVErr3(ctxt, node, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018762 XML_SCHEMAS_ERR_WRONGELEM,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018763 "Element %s: missing child %s found %s\n",
18764 node->name, decl->name, child->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018765 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000018766 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018767 */
18768 if (elemHasContent == -1)
18769 elemHasContent = xmlSchemaHasElemOrCharContent(elem);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018770
18771 /*
18772 * IDC: Register identity-constraint XPath matchers.
18773 */
18774#ifdef IDC_ENABLED
18775 if (elemDecl->idcs != NULL)
18776 xmlSchemaIDCRegisterMatchers(ctxt, elemDecl);
18777 /*
18778 * Evaluate IDCs.
18779 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018780 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018781 return (-1);
18782#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018783 /*
18784 * cvc-elt (3.3.4) : 5
18785 * The appropriate case among the following must be true:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018786 */
Daniel Veillard4255d502002-04-16 15:50:10 +000018787 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018788 * cvc-elt (3.3.4) : 5.1
18789 * If the declaration has a {value constraint},
18790 * the item has neither element nor character [children] and
18791 * clause 3.2 has not applied, then all of the following must be true:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018792 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018793 if ((elemHasContent == 0) && (nilled == 0) && (elemDecl->value != NULL)) {
18794 /*
18795 * cvc-elt (3.3.4) : 5.1.1
18796 * If the ·actual type definition· is a ·local type definition·
18797 * then the canonical lexical representation of the {value constraint}
18798 * value must be a valid default for the ·actual type definition· as
18799 * defined in Element Default Valid (Immediate) (§3.3.6).
18800 */
18801 /*
18802 * NOTE: 'local' above means types aquired by xsi:type.
18803 */
18804 ret = 0;
18805 if (actualType != elemDecl->subtypes) {
18806 xmlSchemaCreatePCtxtOnVCtxt(ctxt);
18807 ret = xmlSchemaCheckCOSValidDefault(ctxt->pctxt, ctxt, actualType,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018808 elemDecl->value, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018809 if (ret < 0) {
18810 xmlSchemaVCustomErr(ctxt,
18811 XML_SCHEMAV_INTERNAL,
18812 elem, actualType,
18813 "Internal error: xmlSchemaValidateElementByDeclaration, "
18814 "validating a default value", NULL);
18815 return (-1);
18816 }
18817 }
18818 /*
18819 * cvc-elt (3.3.4) : 5.1.2
18820 * The element information item with the canonical lexical
18821 * representation of the {value constraint} value used as its
18822 * ·normalized value· must be ·valid· with respect to the
18823 * ·actual type definition· as defined by Element Locally Valid (Type)
18824 * (§3.3.4).
18825 */
18826 /*
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018827 * Disable validation of the simple content, if it was already
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018828 * done above.
18829 */
18830 if (ret == 0) {
18831 if (actualType != elemDecl->subtypes)
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018832 ret = xmlSchemaValidateElementByType(ctxt, actualType, 0, 0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018833 else
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018834 ret = xmlSchemaValidateElementByType(ctxt, actualType, 0, 1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018835 ctxt->node = elem;
18836 if (ret < 0) {
18837 xmlSchemaVCustomErr(ctxt,
18838 XML_SCHEMAV_INTERNAL,
18839 elem, actualType,
18840 "Internal error: xmlSchemaValidateElementByDeclaration, "
18841 "validating against the type", NULL);
18842 return (-1);
18843 }
18844 /*
18845 * PSVI: Create a text node on the instance element.
18846 */
18847 if (ctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
18848 xmlNodePtr textChild;
18849
18850 textChild = xmlNewText(elemDecl->value);
18851 if (textChild == NULL) {
18852 xmlSchemaVCustomErr(ctxt,
18853 XML_SCHEMAV_INTERNAL,
18854 elem, actualType,
18855 "Internal error: xmlSchemaValidateElementByDeclaration, "
18856 "could not create a default text node for the instance",
18857 NULL);
18858 } else
18859 xmlAddChild(elem, textChild);
18860 }
18861 }
18862
18863 } else {
18864 /*
18865 * 5.2.1 The element information item must be ·valid· with respect
18866 * to the ·actual type definition· as defined by Element Locally
18867 * Valid (Type) (§3.3.4).
18868 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018869 ret = xmlSchemaValidateElementByType(ctxt, actualType, nilled, 1);
18870 /*
18871 * Consume the computed value for IDCs, ect. Note that default
18872 * values are not supported yet.
18873 */
18874#ifdef ELEM_INFO_ENABLED
18875 if (ctxt->value != NULL) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018876 ctxt->nodeInfo->value = ctxt->value;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018877 ctxt->value = NULL;
18878 }
18879#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018880 ctxt->node = elem;
18881 if (ret < 0) {
18882 xmlSchemaVCustomErr(ctxt,
18883 XML_SCHEMAV_INTERNAL,
18884 elem, actualType,
18885 "Internal error: xmlSchemaValidateElementByDeclaration, "
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000018886 "calling validation by type", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018887 return (-1);
18888 }
18889 /*
18890 * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
18891 * not applied, all of the following must be true:
18892 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018893 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) && (nilled == 0)) {
18894 /*
18895 * 5.2.2.1 The element information item must have no element
18896 * information item [children].
18897 *
18898 * TODO REDUNDANT: If the actual type exists, the above call to
18899 * xmlSchemaValidateElementByType will already check for element
18900 * nodes.
18901 */
18902 if (xmlSchemaHasElemContent(elem)) {
18903 xmlSchemaVCustomErr(ctxt,
18904 XML_SCHEMAV_CVC_ELT_5_2_2_1,
18905 elem, (xmlSchemaTypePtr) elemDecl,
18906 "Elements in the content are not allowed if it is "
18907 "constrained by a fixed value", NULL);
18908 } else {
18909 /*
18910 * 5.2.2.2 The appropriate case among the following must
18911 * be true:
18912 */
18913
18914 if (actualType->contentType == XML_SCHEMA_CONTENT_MIXED) {
18915 xmlChar *value;
18916 /*
18917 * 5.2.2.2.1 If the {content type} of the ·actual type
18918 * definition· is mixed, then the *initial value* of the
18919 * item must match the canonical lexical representation
18920 * of the {value constraint} value.
18921 *
18922 * ... the *initial value* of an element information
18923 * item is the string composed of, in order, the
18924 * [character code] of each character information item in
18925 * the [children] of that element information item.
18926 */
18927 value = xmlNodeListGetString(elem->doc, elem->children, 1);
18928 if (! xmlStrEqual(BAD_CAST value, elemDecl->value)) {
18929 /*
18930 * TODO: Report invalid & expected values as well.
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018931 * TODO: Implement the canonical stuff.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018932 */
18933 xmlSchemaVCustomErr(ctxt,
18934 XML_SCHEMAV_CVC_ELT_5_2_2_2_1,
18935 elem, (xmlSchemaTypePtr) elemDecl,
18936 "The value does not match the cononical "
18937 "lexical representation of the fixed constraint",
18938 NULL);
18939 }
18940 if (value != NULL)
18941 xmlFree(value);
18942 } else if ((actualType->contentType ==
18943 XML_SCHEMA_CONTENT_SIMPLE) ||
18944 (actualType->contentType == XML_SCHEMA_CONTENT_BASIC)) {
18945 xmlChar *value;
18946
18947 /*
18948 * 5.2.2.2.2 If the {content type} of the ·actual type
18949 * definition· is a simple type definition, then the
18950 * *actual value* of the item must match the canonical
18951 * lexical representation of the {value constraint} value.
18952 */
18953 /*
18954 * TODO: *actual value* is the normalized value, impl. this.
18955 * TODO: Report invalid & expected values as well.
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018956 * TODO: Implement the canonical stuff.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018957 *
18958 */
18959 value = xmlNodeListGetString(elem->doc, elem->children, 1);
18960 if (! xmlStrEqual(BAD_CAST value, elemDecl->value)) {
18961 xmlSchemaVCustomErr(ctxt,
18962 XML_SCHEMAV_CVC_ELT_5_2_2_2_2,
18963 elem, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018964 "The normalized value does not match the canonical "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018965 "lexical representation of the fixed constraint",
18966 NULL);
18967 }
18968 if (value != NULL)
18969 xmlFree(value);
18970
18971 }
18972 /*
18973 * TODO: What if the content type is not 'mixed' or simple?
18974 */
18975
18976 }
18977
18978 }
18979 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018980 /*
18981 * TODO: 7 If the element information item is the ·validation root·, it must be
18982 * ·valid· per Validation Root Valid (ID/IDREF) (§3.3.4).
18983 */
18984
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018985 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000018986}
18987
Daniel Veillard4255d502002-04-16 15:50:10 +000018988/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018989 * xmlSchemaValidateElementByWildcardInternal:
Daniel Veillardc0826a72004-08-10 14:17:33 +000018990 * @ctxt: a schema validation context
18991 * @node: the top node.
18992 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018993 * Represents the recursive portion of xmlSchemaValidateElementByWildcard.
18994 * Not intended to be used by other functions.
Daniel Veillardc0826a72004-08-10 14:17:33 +000018995 *
18996 * Returns 0 if the element is valid, a positive error code
18997 * number otherwise and -1 in case of an internal error.
18998 */
18999static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019000xmlSchemaValidateElementByWildcardInternal(xmlSchemaValidCtxtPtr ctxt,
19001 xmlSchemaWildcardPtr wild,
19002 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +000019003{
19004 const xmlChar *uri;
19005 int ret = 0;
19006 xmlNodePtr child;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019007
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019008 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019009 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
19010 if (ret == -1) {
19011 xmlSchemaVCustomErr(ctxt,
19012 XML_SCHEMAV_INTERNAL,
19013 ctxt->node, NULL,
19014 "Internal error: xmlSchemaValidateElement, "
19015 "assembling schema by xsi", NULL);
19016 return (-1);
19017 }
19018 /*
19019 * NOTE: We won't react on schema parser errors here.
19020 * TODO: But a warning would be nice.
19021 */
19022 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000019023 if (wild->processContents != XML_SCHEMAS_ANY_SKIP) {
19024 xmlSchemaElementPtr decl = NULL;
19025
19026 if (node->ns != NULL)
19027 decl = xmlHashLookup3(ctxt->schema->elemDecl,
19028 node->name, node->ns->href, NULL);
19029 else
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019030 decl = xmlHashLookup3(ctxt->schema->elemDecl, node->name,
19031 NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000019032 if (decl != NULL) {
19033 ctxt->node = node;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019034 ret = xmlSchemaValidateElementByDeclaration(ctxt, decl);
Daniel Veillardc0826a72004-08-10 14:17:33 +000019035 if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000019036 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000019037 "Internal error: xmlSchemaValidateAnyInternal, "
19038 "validating an element in the context of a wildcard.",
19039 NULL, NULL);
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +000019040 }
19041 return (ret);
Daniel Veillardc0826a72004-08-10 14:17:33 +000019042 } else if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
19043 /* TODO: Change to proper error code. */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000019044 xmlSchemaVWildcardErr(ctxt, XML_SCHEMAV_CVC_ELT_1,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019045 node, wild, "No matching global declaration available");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019046 /*
19047 * Evaluate IDCs even if a validation error occured.
19048 */
19049#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019050 if (xmlSchemaXPathEvaluate(ctxt,XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019051 return(-1);
19052#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +000019053 return (ctxt->err);
19054 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019055 /*
19056 * Evaluate IDCs; we need to know if an IDC field resolves to
19057 * such a node. This node has no type definition and will
19058 * definitely result in an IDC validation error if an IDC field
19059 * resolves.
19060 */
19061#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019062 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019063 return(-1);
19064#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +000019065 }
19066 if (node->children != NULL) {
19067 child = node->children;
19068 do {
19069 if (child->type == XML_ELEMENT_NODE) {
19070 if (child->ns != NULL)
19071 uri = child->ns->href;
19072 else
19073 uri = NULL;
19074 if (xmlSchemaMatchesWildcardNs(wild, uri) == 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000019075 /* TODO: error code. */
19076 xmlSchemaVWildcardErr(ctxt, XML_SCHEMAV_ELEMENT_CONTENT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000019077 child, wild,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019078 "The namespace of the element is not allowed");
Daniel Veillardc0826a72004-08-10 14:17:33 +000019079 return (ctxt->err);
19080 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019081#ifdef ELEM_INFO_ENABLED
19082 ctxt->node = child;
19083 xmlSchemaBeginElement(ctxt);
19084#endif
19085 /*
19086 * Recurse over the children.
19087 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019088 ret = xmlSchemaValidateElementByWildcardInternal(ctxt,
19089 wild, child);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019090 if (ret == -1)
19091 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019092#ifdef ELEM_INFO_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019093 if (xmlSchemaEndElement(ctxt) == -1)
19094 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019095#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +000019096 if (ret != 0)
19097 return (ret);
19098 }
19099 child = child->next;
19100 } while (child != NULL);
19101 }
19102 return (0);
19103}
19104
19105/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019106 * xmlSchemaValidateElementContByWildcard:
Daniel Veillardc0826a72004-08-10 14:17:33 +000019107 * @ctxt: a schema validation context
19108 *
19109 * Returns 0 if the element is valid, a positive error code
19110 * number otherwise and -1 in case of an internal or API error.
19111 */
19112static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019113xmlSchemaValidateElementByWildcard(xmlSchemaValidCtxtPtr ctxt,
19114 xmlSchemaTypePtr type)
Daniel Veillardc0826a72004-08-10 14:17:33 +000019115{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019116 if ((type == NULL) || (type->type != XML_SCHEMA_TYPE_ANY) ||
19117 (ctxt->node == NULL)) {
19118 xmlSchemaVCustomErr(ctxt,
19119 XML_SCHEMAV_INTERNAL, ctxt->node, NULL,
19120 "Internal error: xmlSchemaValidateElementByWildcard, "
19121 "bad arguments", NULL);
19122 return (-1);
19123 }
19124 return(xmlSchemaValidateElementByWildcardInternal(ctxt,
19125 type->attributeWildcard, ctxt->node));
Daniel Veillardc0826a72004-08-10 14:17:33 +000019126}
19127
19128/**
William M. Brack2f2a6632004-08-20 23:09:47 +000019129 * xmlSchemaValidateAnyTypeContent:
19130 * @ctxt: a schema validation context
19131 * @node: the current element
19132 *
19133 * This one validates the content of an element of the type
19134 * 'anyType'. The process contents of the wildcard of 'anyType' is "lax",
19135 * thus elements in the subtree will be validated, if a corresponding
19136 * declaration in the schema exists.
19137 *
19138 * Returns 0 if the element and its subtree is valid, a positive error code
19139 * otherwise and -1 in case of an internal or API error.
19140 */
19141static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019142xmlSchemaValidateElementByAnyType(xmlSchemaValidCtxtPtr ctxt,
19143 xmlSchemaTypePtr type)
William M. Brack2f2a6632004-08-20 23:09:47 +000019144{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019145 xmlSchemaTypePtr oldtype;
19146 xmlNodePtr top, cur;
19147 xmlSchemaElementPtr decl;
William M. Brack2f2a6632004-08-20 23:09:47 +000019148 int skipContent, ret;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019149
19150 if ((type == NULL) || (ctxt->node == NULL))
19151 return (-1);
19152
19153 if (ctxt->node->children == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +000019154 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019155
19156 oldtype = ctxt->type;
19157 top = ctxt->node;
19158 /*
19159 * STREAM: Child nodes are processed.
19160 */
19161 cur = ctxt->node->children;
19162 while (cur != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +000019163 skipContent = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019164 if (cur->type == XML_ELEMENT_NODE) {
William M. Brack2f2a6632004-08-20 23:09:47 +000019165 /*
19166 * The process contents of the wildcard is "lax", thus
19167 * we need to validate the element if a declaration
19168 * exists.
19169 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019170 if (cur->ns != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +000019171 decl = xmlHashLookup3(ctxt->schema->elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019172 cur->name, cur->ns->href, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000019173 else
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019174 decl = xmlHashLookup3(ctxt->schema->elemDecl, cur->name, NULL, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000019175 if (decl != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019176 ctxt->node = cur;
19177 ret = xmlSchemaValidateElementByDeclaration(ctxt, decl);
19178 ctxt->node = top;
William M. Brack2f2a6632004-08-20 23:09:47 +000019179 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019180 xmlSchemaVErr(ctxt, cur, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000019181 "Internal error: xmlSchemaValidateAnyTypeContent, "
19182 "validating an element in the context of a wildcard.",
19183 NULL, NULL);
19184 return (ret);
19185 } else if (ret > 0)
19186 return (ret);
19187 skipContent = 1;
19188 }
19189 }
19190 /*
19191 * Browse the full subtree, deep first.
19192 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019193 if ((skipContent == 0) && (cur->children != NULL)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000019194 /* deep first */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019195 cur = cur->children;
19196 } else if ((cur != top) && (cur->next != NULL)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000019197 /* then siblings */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019198 cur = cur->next;
19199 } else if (cur != top) {
William M. Brack2f2a6632004-08-20 23:09:47 +000019200 /* go up to parents->next if needed */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019201 while (cur != top) {
19202 if (cur->parent != NULL)
19203 cur = cur->parent;
19204 if ((cur != top) && (cur->next != NULL)) {
19205 cur = cur->next;
William M. Brack2f2a6632004-08-20 23:09:47 +000019206 break;
19207 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019208 if (cur->parent == NULL) {
19209 cur = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000019210 break;
19211 }
19212 }
19213 /* exit condition */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019214 if (cur == top)
19215 cur = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000019216 } else
19217 break;
19218 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019219 ctxt->type = oldtype;
William M. Brack2f2a6632004-08-20 23:09:47 +000019220 return (0);
19221}
19222
19223/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019224 * xmlSchemaValidateElementByComplexType:
Daniel Veillard4255d502002-04-16 15:50:10 +000019225 * @ctxt: a schema validation context
19226 * @node: the top node.
19227 *
19228 * Validate the content of an element expected to be a complex type type
19229 * xmlschema-1.html#cvc-complex-type
19230 * Validation Rule: Element Locally Valid (Complex Type)
19231 *
19232 * Returns 0 if the element is schemas valid, a positive error code
Daniel Veillard01fa6152004-06-29 17:04:39 +000019233 * number otherwise and -1 in case of internal or API error.
19234 * Note on reported errors: Although it might be nice to report
19235 * the name of the simple/complex type, used to validate the content
19236 * of a node, it is quite unnecessary: for global defined types
19237 * the local name of the element is equal to the NCName of the type,
19238 * for local defined types it makes no sense to output the internal
19239 * computed name of the type. TODO: Instead, one should attach the
19240 * struct of the type involved to the error handler - this allows
19241 * the report of any additional information by the user.
Daniel Veillard4255d502002-04-16 15:50:10 +000019242 */
19243static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019244xmlSchemaValidateElementByComplexType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019245 xmlSchemaTypePtr type,
19246 int valSimpleContent)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019247{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019248 xmlSchemaTypePtr oldtype;
19249 xmlNodePtr elem, child;
Daniel Veillard01fa6152004-06-29 17:04:39 +000019250 int ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +000019251 const xmlChar *nsUri;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019252 xmlSchemaAttrStatePtr attrs = NULL, attrTop = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000019253
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019254 if ((ctxt == NULL) || (type->type != XML_SCHEMA_TYPE_COMPLEX))
19255 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000019256
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019257 oldtype = ctxt->type;
19258 ctxt->type = type;
19259 elem = ctxt->node;
19260
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019261 /*
19262 * Verify the attributes
19263 */
19264 /*
19265 * TODO: This "attrTop" thing is not needed any more.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019266 */
19267 /* NOTE: removed, since a check for abstract is
19268 * done in the cvc-type constraint.
19269 *
19270 *
19271 * if (type->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
19272 * xmlSchemaVComplexTypeErr(ctxt,
19273 * XML_SCHEMAV_CVC_COMPLEX_TYPE_1,
19274 * elem, type,
19275 * "The type definition is abstract");
19276 * return (XML_SCHEMAV_CVC_COMPLEX_TYPE_1);
19277 *}
19278 */
19279
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019280 attrs = ctxt->attr;
19281 attrTop = ctxt->attrTop;
19282 /*
19283 * STREAM: Attribute nodes are processed.
19284 */
19285 xmlSchemaRegisterAttributes(ctxt, elem->properties);
19286 xmlSchemaValidateAttributes(ctxt, elem, type);
19287 if (ctxt->attr != NULL)
19288 xmlSchemaFreeAttributeStates(ctxt->attr);
19289 ctxt->attr = attrs;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019290 ctxt->attrTop = attrTop;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019291
19292 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019293 * TODO: This one creates a regexp even if no content
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019294 * model was defined. Somehow ->contModel is always not NULL
19295 * for complex types, even if they are empty.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019296 * TODO: Check if the obove still occurs.
19297 */
Daniel Veillard4255d502002-04-16 15:50:10 +000019298 switch (type->contentType) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000019299 case XML_SCHEMA_CONTENT_EMPTY: {
19300 /*
19301 * 1 If the {content type} is empty, then the element information
19302 * item has no character or element information item [children].
Daniel Veillard3646d642004-06-02 19:19:14 +000019303 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000019304 /*
19305 * TODO: Is the entity stuff correct?
19306 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019307 if (xmlSchemaHasElemOrCharContent(elem) == 1) {
William M. Brack2f2a6632004-08-20 23:09:47 +000019308 xmlSchemaVComplexTypeErr(ctxt,
19309 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019310 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000019311 "Character or element content is not allowed, "
19312 "because the content type is empty");
Daniel Veillard01fa6152004-06-29 17:04:39 +000019313 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019314 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000019315 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019316 case XML_SCHEMA_CONTENT_MIXED:
19317 if ((type->subtypes == NULL) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019318 (type->baseType->builtInType == XML_SCHEMAS_ANYTYPE)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019319 /*
19320 * The type has 'anyType' as its base and no content model
19321 * is defined -> use 'anyType' as the type to validate
19322 * against.
19323 */
19324 ret = xmlSchemaValidateElementByAnyType(ctxt, type->baseType);
19325 /* TODO: Handle -1. */
19326 break;
19327 }
19328 /* No break on purpose. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000019329 case XML_SCHEMA_CONTENT_ELEMENTS:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019330 {
19331 xmlRegExecCtxtPtr oldregexp = NULL;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019332 xmlChar *values[10];
19333 int terminal, nbval = 10, nbneg;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019334
19335 /*
19336 * Content model check initialization.
19337 */
19338 if (type->contModel != NULL) {
19339 oldregexp = ctxt->regexp;
19340 ctxt->regexp = xmlRegNewExecCtxt(type->contModel,
19341 (xmlRegExecCallbacks)
19342 xmlSchemaValidateCallback, ctxt);
19343#ifdef DEBUG_AUTOMATA
19344 xmlGenericError(xmlGenericErrorContext, "====> %s\n", elem->name);
19345#endif
19346 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019347 /*
19348 * STREAM: Children are processed.
19349 */
19350 child = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000019351 while (child != NULL) {
19352 if (child->type == XML_ELEMENT_NODE) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000019353 if (child->ns != NULL)
19354 nsUri = child->ns->href;
19355 else
19356 nsUri = NULL;
19357 ret = xmlRegExecPushString2(ctxt->regexp,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019358 child->name, nsUri, child);
19359 if (ctxt->err == XML_SCHEMAV_INTERNAL)
19360 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019361 /*
19362 * URGENT TODO: Could we anchor an error report
19363 * here to notify of invalid elements?
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019364 * TODO: Perhaps it would be better to report
19365 * only the first erroneous element and then break.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019366 */
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019367#ifdef DEBUG_AUTOMATA
Daniel Veillard01fa6152004-06-29 17:04:39 +000019368 if (ret < 0)
19369 xmlGenericError(xmlGenericErrorContext,
19370 " --> %s Error\n", child->name);
William M. Bracke7091952004-05-11 15:09:58 +000019371 else
19372 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard01fa6152004-06-29 17:04:39 +000019373 " --> %s\n", child->name);
19374#endif
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019375 if (ret < 0) {
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019376 xmlRegExecErrInfo(ctxt->regexp, NULL, &nbval, &nbneg,
19377 &values[0], &terminal);
19378 xmlSchemaVComplexTypeElemErr(ctxt,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019379 XML_SCHEMAV_ELEMENT_CONTENT,
19380 child, NULL/* type */,
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019381 "This element is not expected",
19382 nbval, nbneg, values);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019383 ret = 1;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019384 /*
19385 * Note that this will skip further validation of the
19386 * content.
19387 */
19388 break;
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019389 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000019390 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) &&
19391 /*
19392 * TODO: Ask Daniel if this are all character nodes.
19393 */
19394 (((child->type == XML_TEXT_NODE) && (!IS_BLANK_NODE(child))) ||
19395 (child->type == XML_ENTITY_NODE) ||
19396 (child->type == XML_ENTITY_REF_NODE) ||
19397 (child->type == XML_CDATA_SECTION_NODE))) {
19398 /*
19399 * 2.3 If the {content type} is element-only, then the
19400 * element information item has no character information
19401 * item [children] other than those whose [character
19402 * code] is defined as a white space in [XML 1.0 (Second
19403 * Edition)].
19404 */
William M. Brack2f2a6632004-08-20 23:09:47 +000019405 xmlSchemaVComplexTypeErr(ctxt,
19406 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019407 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000019408 "Character content is not allowed, "
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019409 "because the content type is element-only");
19410 ret = 1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000019411 break;
19412 }
19413 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019414 }
19415 /*
19416 * Content model check finalization.
19417 */
19418 if (type->contModel != NULL) {
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019419 if (ret == 0) {
19420 xmlRegExecNextValues(ctxt->regexp, &nbval, &nbneg,
19421 &values[0], &terminal);
19422 if (nbval + nbneg != 0) {
19423 /*
19424 * If a next value still exists, I does not have to
19425 * mean that there's an element missing, since it
19426 * might be an optional element. So double check it.
19427 */
19428 ret = xmlRegExecPushString(ctxt->regexp,
19429 NULL, NULL);
19430 if (ret <= 0) {
19431 ret = 1;
19432 xmlSchemaVComplexTypeElemErr(ctxt,
19433 XML_SCHEMAV_ELEMENT_CONTENT,
19434 elem, type, "Missing child element(s)",
19435 nbval, nbneg, values);
19436 } else
19437 ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019438#ifdef DEBUG_AUTOMATA
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019439 xmlGenericError(xmlGenericErrorContext,
19440 "====> %s : %d\n", elem->name, ret);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019441#endif
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019442 }
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019443#ifdef DEBUG_CONTENT
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019444 if (ret == 0)
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019445 xmlGenericError(xmlGenericErrorContext,
19446 "Element %s content check succeeded\n",
19447 elem->name);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019448#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019449 }
19450 xmlRegFreeExecCtxt(ctxt->regexp);
19451 ctxt->regexp = oldregexp;
19452 }
19453 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000019454 break;
19455 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019456 case XML_SCHEMA_CONTENT_BASIC:
19457 /*
19458 * If the simple content was already validated
19459 * (e.g. a default value), the content need not
19460 * to be validated again.
19461 */
19462 if (valSimpleContent == 1) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000019463 xmlChar *value = NULL;
19464 /*
19465 * We hit a complexType with a simpleContent resolving
19466 * to a user derived or built-in simple type.
William M. Brack2f2a6632004-08-20 23:09:47 +000019467 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000019468 /*
19469 * 2.2 If the {content type} is a simple type definition,
19470 * then the element information item has no element
19471 * information item [children], and the ·normalized value·
19472 * of the element information item is ·valid· with respect
19473 * to that simple type definition as defined by String
19474 * Valid (§3.14.4).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019475 */
19476 /*
19477 * STREAM: Children are processed.
19478 */
19479 child = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000019480 while (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019481 /*
19482 * TODO: Could the entity stuff produce elements
19483 * as well?
19484 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000019485 if (child->type == XML_ELEMENT_NODE) {
William M. Brack2f2a6632004-08-20 23:09:47 +000019486 xmlSchemaVComplexTypeErr(ctxt,
19487 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019488 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000019489 "Element content is not allowed, because "
19490 "the content type is a simple type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000019491 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
19492 break;
19493 }
19494 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019495 }
19496 ctxt->node = elem;
19497 ctxt->cur = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000019498 if (ret == 0) {
19499 /*
19500 * Validate the character content against a simple type.
Daniel Veillard3646d642004-06-02 19:19:14 +000019501 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019502 /*
19503 * STREAM: Children are processed.
19504 */
19505 if (elem->children == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000019506 value = NULL;
19507 else
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019508 value = xmlNodeGetContent(elem);
19509 /*
19510 * URGENT TODO: Should facets for the simple type validation be
19511 * disabled, if the derivation of facets for complex types
19512 * is implemented?
19513 */
19514 /*
19515 * NOTE: This call won't check the correct types of the
19516 * content nodes, since this should be done here.
19517 */
19518 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type, value, 1, 1, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000019519 if (ret > 0) {
19520 /*
19521 * NOTE: Although an error will be reported by
19522 * xmlSchemaValidateSimpleTypeValue, the spec wants
19523 * a specific complex type error to be reported
19524 * additionally.
19525 */
19526 xmlSchemaVComplexTypeErr(ctxt,
19527 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019528 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000019529 "The character content is not valid");
Daniel Veillard01fa6152004-06-29 17:04:39 +000019530 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
19531 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019532 xmlSchemaVErr(ctxt, elem, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000019533 "Internal error: xmlSchemaValidateComplexType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000019534 "Element '%s': Error while validating character "
19535 "content against complex type '%s'.\n",
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019536 elem->name, type->name);
19537 if (value != NULL)
19538 xmlFree(value);
19539 ctxt->type = oldtype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000019540 return (-1);
19541 }
William M. Brack2f2a6632004-08-20 23:09:47 +000019542 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000019543 if (ret == 0) {
19544 /*
19545 * Apply facets of the complexType. Be sure to pass the
19546 * built-in type to xmlSchemaValidateFacetsInternal.
19547 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019548 /* URGENT TODO: I don't know yet if the facets of the simple type
Daniel Veillard01fa6152004-06-29 17:04:39 +000019549 * are used, or if the facets, defined by this complex type,
19550 * are to be used only. This here applies both facet sets.
19551 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000019552
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019553 ret = xmlSchemaValidateFacetsInternal(ctxt,
19554 type, value, 0, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000019555 if (ret > 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +000019556 xmlSchemaVComplexTypeErr(ctxt,
19557 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019558 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000019559 "The character content is not valid");
Daniel Veillard01fa6152004-06-29 17:04:39 +000019560 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
19561 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019562 xmlSchemaVErr(ctxt, elem, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000019563 "Internal error: xmlSchemaValidateComplexType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000019564 "Element '%s': Error while validating character "
19565 "content against complex type '%s'; failed to "
Daniel Veillard01fa6152004-06-29 17:04:39 +000019566 "apply facets.\n",
19567 type->name, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019568 if (value != NULL)
19569 xmlFree(value);
19570 ctxt->type = oldtype;
19571 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000019572 }
19573 }
19574 if (value != NULL)
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019575 xmlFree(value);
19576
Daniel Veillard01fa6152004-06-29 17:04:39 +000019577 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019578 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019579 default:
19580 TODO xmlGenericError(xmlGenericErrorContext,
19581 "unimplemented content type %d\n",
19582 type->contentType);
Daniel Veillard4255d502002-04-16 15:50:10 +000019583 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019584 ctxt->type = oldtype;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019585 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000019586}
19587
19588/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019589 * xmlSchemaValidateElementByType:
Daniel Veillard4255d502002-04-16 15:50:10 +000019590 * @ctxt: a schema validation context
19591 * @elem: an element
19592 * @type: the list of type declarations
19593 *
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019594 * Validation Rule: Element Locally Valid (Type).
Daniel Veillard4255d502002-04-16 15:50:10 +000019595 *
19596 * Returns 0 if the element is schemas valid, a positive error code
19597 * number otherwise and -1 in case of internal or API error.
19598 */
19599static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019600xmlSchemaValidateElementByType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019601 xmlSchemaTypePtr type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019602 int isNil,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019603 int valSimpleContent)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019604{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019605 int ret;
Daniel Veillard4255d502002-04-16 15:50:10 +000019606
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019607
19608 if ((ctxt == NULL) || (type == NULL)) {
19609 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_INTERNAL, NULL, NULL,
19610 "Internal error: xmlSchemaValidateElementByType, "
19611 "bad arguments", NULL);
19612 return (-1);
19613 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019614 /*
19615 * This one is called by "xmlSchemaValidateElementByDeclaration".
19616 * It will forward to the proper validation
19617 * procedures for the given type.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019618 */
19619 if (type == NULL) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019620 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019621 XML_SCHEMAV_CVC_TYPE_1,
19622 ctxt->node, NULL,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019623 "The type definition is absent", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019624 return (XML_SCHEMAV_CVC_TYPE_1);
19625 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019626
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019627 if (type->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019628 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019629 XML_SCHEMAV_CVC_TYPE_2,
19630 ctxt->node, type,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019631 "The type definition is abstract", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019632 return (XML_SCHEMAV_CVC_TYPE_2);
19633 }
19634
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019635 switch (type->type) {
19636 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019637 ret = xmlSchemaValidateElementByComplexType(ctxt, type,
19638 valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019639 break;
19640 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019641 ret = xmlSchemaValidateElementBySimpleType(ctxt, type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019642 isNil, valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019643 break;
19644 case XML_SCHEMA_TYPE_BASIC:
19645 if (type->builtInType == XML_SCHEMAS_ANYTYPE)
19646 ret = xmlSchemaValidateElementByAnyType(ctxt, type);
19647 else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019648 ret = xmlSchemaValidateElementBySimpleType(ctxt, type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019649 isNil, valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019650 break;
19651 default:
19652 ret = -1;
19653 break;
19654 }
19655 if (ret == -1)
19656 return (-1);
19657 else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019658 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000019659}
19660
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019661static int
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019662xmlSchemaPostCreateVal(xmlSchemaValidCtxtPtr vctxt,
19663 const xmlChar *value,
19664 xmlSchemaValPtr *val)
19665{
19666 xmlSchemaTypePtr prim;
19667
19668 if (val == NULL) {
19669 xmlSchemaVErr(vctxt, vctxt->nodeInfo->node,
19670 XML_SCHEMAV_INTERNAL,
19671 "Internal error: xmlSchemaPostCreateVal, "
19672 "bad arguments", NULL, NULL);
19673 return (-1);
19674 }
19675 /*
19676 * Only string or anySimpleType values are expected to be post-created.
19677 */
19678 prim = xmlSchemaGetPrimitiveType(vctxt->nodeInfo->typeDef);
19679 if ((prim->builtInType == XML_SCHEMAS_STRING) ||
19680 (prim->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
19681 {
19682#if 0
19683 builtIn = xmlSchemaGetBuiltInTypeAncestor(vctxt->nodeInfo->typeDef);
19684#endif
19685 if (value == NULL)
19686 /* TODO: Can this happen at all? */
19687 *val = xmlSchemaNewStringValue(XML_SCHEMAS_STRING,
19688 xmlStrdup(BAD_CAST ""));
19689 else
19690 *val = xmlSchemaNewStringValue(XML_SCHEMAS_STRING, value);
19691 if ((*val) == NULL) {
19692 xmlSchemaVErr(vctxt, vctxt->nodeInfo->node,
19693 XML_SCHEMAV_INTERNAL,
19694 "Internal error: xmlSchemaPostCreateVal, "
19695 "failed to create the value", NULL, NULL);
19696 return (-1);
19697 }
19698 return (0);
19699 }
19700 xmlSchemaVErr(vctxt, vctxt->nodeInfo->node,
19701 XML_SCHEMAV_INTERNAL,
19702 "Internal error: xmlSchemaPostCreateVal, "
19703 "the given type is not supported", NULL, NULL);
19704 return (-1);
19705}
19706
19707static int
19708xmlSchemaCheckAttrLocallyValid(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019709 xmlSchemaAttrStatePtr state)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019710{
19711 xmlChar *value;
19712 const xmlChar *defValue;
19713 xmlSchemaValPtr defVal;
19714 int fixed;
19715 int ret;
19716
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019717 if (vctxt->attrInfo->typeDef == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019718 state->state = XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED;
19719 return (XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED);
19720 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019721 vctxt->node = vctxt->attrInfo->node;
19722 vctxt->cur = vctxt->node->children;
19723 /* STREAM */
19724 value = xmlNodeListGetString(vctxt->node->doc, vctxt->cur, 1);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019725
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019726 /*
19727 * NOTE: This call also checks the content nodes for correct type.
19728 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019729 ret = xmlSchemaValidateSimpleTypeValue(vctxt, vctxt->attrInfo->typeDef,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019730 value, 1, 1, 1, 1);
19731
19732 /*
19733 * Handle 'fixed' attributes.
19734 */
19735 if (ret > 0) {
19736 state->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
19737 /*
19738 * NOTE: Fixed value constraints will be not
19739 * applied if the value was invalid, because:
19740 * 1. The validation process does not return a precomputed
19741 * value.
19742 * 2. An invalid value implies a violation of a fixed
19743 * value constraint.
19744 */
19745 } else if (ret == 0) {
19746 state->state = XML_SCHEMAS_ATTR_CHECKED;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019747 if (xmlSchemaGetEffectiveValueConstraint(
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019748 (xmlSchemaAttributePtr) vctxt->attrInfo->decl,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019749 &fixed, &defValue, &defVal) && (fixed == 1)) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000019750
19751 int ws = xmlSchemaGetWhiteSpaceFacetValue(
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019752 vctxt->nodeInfo->typeDef);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019753 /*
19754 * cvc-au : Attribute Locally Valid (Use)
19755 * For an attribute information item to be·valid·
19756 * with respect to an attribute use its ·normalized
19757 * value· must match the canonical lexical representation
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019758 * of the attribute use's {value constraint} value, if it
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019759 * is present and fixed.
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019760 *
19761 * TODO: Use somehow the *normalized* value and the *canonical*
19762 * fixed value. This here compares the canonical values of both.
19763 * The normalized value of, for example, a float type can differ
19764 * from its canonical representation. This all means that a fixed
19765 * value can only be OK, if it's present in the canonical form in
19766 * the instance.
19767 * NOTE: Since the value for string and anySimpleType is not always
19768 * precomputed during validation, we need to do it now.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019769 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019770 if (vctxt->value == NULL) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000019771 /*
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019772 * Post-create the value.
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000019773 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019774 if (xmlSchemaPostCreateVal(vctxt, value, &(vctxt->value)) == -1) {
19775 ret = -1;
19776 goto exit;
19777 }
19778 value = NULL;
19779 }
19780 if (defVal == NULL) {
19781 xmlChar *str;
19782
19783 /*
19784 * Post-create the default/fixed value.
19785 */
19786 if (defValue == NULL)
19787 str = xmlStrdup(BAD_CAST "");
19788 else
19789 str = xmlStrdup(defValue);
19790 if (xmlSchemaPostCreateVal(vctxt, str, &defVal) == -1) {
19791 ret = -1;
19792 FREE_AND_NULL(str)
19793 goto exit;
19794 }
19795 ((xmlSchemaAttributePtr) vctxt->attrInfo->decl)->defVal = defVal;
19796 }
19797 if (xmlSchemaCompareValuesWhtsp(vctxt->value,
19798 (xmlSchemaWhitespaceValueType) ws,
19799 defVal,
19800 (xmlSchemaWhitespaceValueType) ws) != 0)
19801 {
19802 state->state = XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019803 }
19804 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019805 }
19806exit:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019807 if (value != NULL) {
19808 xmlFree(value);
19809 }
19810 return (ret);
19811}
19812
Daniel Veillard4255d502002-04-16 15:50:10 +000019813/**
19814 * xmlSchemaValidateAttributes:
19815 * @ctxt: a schema validation context
19816 * @elem: an element
Daniel Veillard3646d642004-06-02 19:19:14 +000019817 * @type: the complexType holding the attribute uses
Daniel Veillard4255d502002-04-16 15:50:10 +000019818 *
19819 * Validate the attributes of an element.
19820 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000019821 * 1. Existent, invalid attributes are reported in the form
19822 * "prefix:localName".
19823 * Reason: readability - it is easier to find the actual XML
19824 * representation of the attributes QName.
19825 * 2. Missing attributes are reported in the form
19826 * {"URI", "localName"}.
19827 * This is necessary, since the the prefix need not to be declared
19828 * at all, and thus is not computable.
19829 *
Daniel Veillard4255d502002-04-16 15:50:10 +000019830 * Returns 0 if the element is schemas valid, a positive error code
19831 * number otherwise and -1 in case of internal or API error.
19832 */
19833static int
Daniel Veillard3646d642004-06-02 19:19:14 +000019834xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem, xmlSchemaTypePtr type)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019835{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019836 const xmlChar *nsURI;
Daniel Veillard3646d642004-06-02 19:19:14 +000019837 int ret;
19838 xmlAttrPtr attr; /* An attribute on the element. */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019839 const xmlChar *defValue;
19840 xmlSchemaValPtr defVal;
19841 int fixed;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019842 xmlSchemaAttributeLinkPtr attrUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000019843 xmlSchemaAttributePtr attrDecl;
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000019844 int found;
William M. Brack803812b2004-06-03 02:11:24 +000019845 xmlSchemaAttrStatePtr curState, reqAttrStates = NULL, reqAttrStatesTop = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019846 xmlSchemaAttrStatePtr defAttrStates = NULL, defAttrStatesTop = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019847 xmlNodePtr oldnode;
Daniel Veillard3646d642004-06-02 19:19:14 +000019848#ifdef DEBUG_ATTR_VALIDATION
19849 int redundant = 0;
19850#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000019851
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019852
Daniel Veillardc0826a72004-08-10 14:17:33 +000019853 /*
19854 * Allow all attributes if the type is anyType.
19855 */
19856 if (type == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE))
19857 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019858
19859 oldnode = ctxt->node;
19860 if (type != NULL)
19861 attrUse = type->attributeUses;
Daniel Veillard3646d642004-06-02 19:19:14 +000019862 while (attrUse != NULL) {
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000019863 found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000019864 attrDecl = attrUse->attr;
19865#ifdef DEBUG_ATTR_VALIDATION
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019866 printf("attr use - name: %s\n", xmlSchemaGetAttrName(attrDecl));
Daniel Veillard3646d642004-06-02 19:19:14 +000019867 printf("attr use - use: %d\n", attrDecl->occurs);
19868#endif
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019869 for (curState = ctxt->attr; curState != NULL; curState = curState->next) {
Daniel Veillard3646d642004-06-02 19:19:14 +000019870
19871 if (curState->decl == attrUse->attr) {
19872#ifdef DEBUG_ATTR_VALIDATION
19873 redundant = 1;
19874#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019875 }
Daniel Veillard3646d642004-06-02 19:19:14 +000019876 attr = curState->attr;
19877#ifdef DEBUG_ATTR_VALIDATION
19878 printf("attr - name: %s\n", attr->name);
19879 if (attr->ns != NULL)
19880 printf("attr - ns: %s\n", attr->ns->href);
19881 else
19882 printf("attr - ns: none\n");
19883#endif
19884 /* TODO: Can this ever happen? */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019885 if (attr == NULL)
19886 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000019887 if (attrDecl->ref != NULL) {
19888 if (!xmlStrEqual(attr->name, attrDecl->ref))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019889 continue;
19890 if (attr->ns != NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000019891 if ((attrDecl->refNs == NULL) ||
19892 (!xmlStrEqual(attr->ns->href, attrDecl->refNs)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019893 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000019894 } else if (attrDecl->refNs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019895 continue;
19896 }
19897 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000019898 if (!xmlStrEqual(attr->name, attrDecl->name))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019899 continue;
19900 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +000019901 * handle the namespaces checks here
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019902 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000019903 if (attr->ns == NULL) {
19904 /*
William M. Bracke7091952004-05-11 15:09:58 +000019905 * accept an unqualified attribute only if the target
19906 * namespace of the declaration is absent.
Daniel Veillardbe9c6322003-11-22 20:37:51 +000019907 */
Daniel Veillard3646d642004-06-02 19:19:14 +000019908 if (attrDecl->targetNamespace != NULL)
William M. Bracke7091952004-05-11 15:09:58 +000019909 /*
19910 * This check was removed, since the target namespace
19911 * was evaluated during parsing and already took
19912 * "attributeFormDefault" into account.
19913 */
19914 /* ((attributes->flags & XML_SCHEMAS_ATTR_NSDEFAULT) == 0)) */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000019915 continue;
19916 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000019917 if (attrDecl->targetNamespace == NULL)
Daniel Veillardbe9c6322003-11-22 20:37:51 +000019918 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000019919 if (!xmlStrEqual(attrDecl->targetNamespace,
Daniel Veillardbe9c6322003-11-22 20:37:51 +000019920 attr->ns->href))
19921 continue;
19922 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019923 }
Daniel Veillard3646d642004-06-02 19:19:14 +000019924#ifdef DEBUG_ATTR_VALIDATION
19925 printf("found\n");
19926#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019927 found = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +000019928 curState->decl = attrDecl;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019929 curState->state = XML_SCHEMAS_ATTR_VALIDATE_VALUE;
19930 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019931 ret = xmlSchemaCheckAttrLocallyValid(ctxt, attrDecl, curState, attr);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019932 */
Daniel Veillard3646d642004-06-02 19:19:14 +000019933 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019934 if (!found) {
19935 if (attrDecl->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
19936 xmlSchemaAttrStatePtr tmp;
19937
Daniel Veillard3646d642004-06-02 19:19:14 +000019938#ifdef DEBUG_ATTR_VALIDATION
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019939 printf("required attr not found\n");
Daniel Veillard3646d642004-06-02 19:19:14 +000019940#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019941 /*
19942 * Add a new dummy attribute state.
19943 */
19944 tmp = (xmlSchemaAttrStatePtr) xmlMalloc(sizeof(xmlSchemaAttrState));
19945 if (tmp == NULL) {
19946 xmlSchemaVErrMemory(ctxt, "registering required attributes", NULL);
19947 ctxt->node = oldnode;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019948 goto fatal_exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019949 }
19950 tmp->attr = NULL;
19951 tmp->state = XML_SCHEMAS_ATTR_MISSING;
19952 tmp->decl = attrDecl;
19953 tmp->next = NULL;
19954
19955 if (reqAttrStates == NULL) {
19956 reqAttrStates = tmp;
19957 reqAttrStatesTop = tmp;
19958 } else {
19959 reqAttrStatesTop->next = tmp;
19960 reqAttrStatesTop = tmp;
19961 }
19962 } else if ((attrDecl->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
19963 (xmlSchemaGetEffectiveValueConstraint(attrDecl,
19964 &fixed, &defValue, &defVal))) {
19965 xmlSchemaAttrStatePtr tmp;
19966 /*
19967 * Handle non existent default/fixed attributes.
19968 */
19969 tmp = (xmlSchemaAttrStatePtr)
19970 xmlMalloc(sizeof(xmlSchemaAttrState));
19971 if (tmp == NULL) {
19972 xmlSchemaVErrMemory(ctxt,
19973 "registering schema specified attributes", NULL);
19974 ctxt->node = oldnode;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019975 goto fatal_exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019976 }
19977 tmp->attr = NULL;
19978 tmp->state = XML_SCHEMAS_ATTR_DEFAULT;
19979 tmp->decl = attrDecl;
19980 tmp->value = defValue;
19981 tmp->next = NULL;
19982
19983 if (defAttrStates == NULL) {
19984 defAttrStates = tmp;
19985 defAttrStates = tmp;
19986 } else {
19987 defAttrStates->next = tmp;
19988 defAttrStatesTop = tmp;
19989 }
19990 }
Daniel Veillard3646d642004-06-02 19:19:14 +000019991 }
19992 attrUse = attrUse->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000019993 }
Daniel Veillard3646d642004-06-02 19:19:14 +000019994 /*
19995 * Add required attributes to the attribute states of the context.
19996 */
19997 if (reqAttrStates != NULL) {
19998 if (ctxt->attr == NULL) {
19999 ctxt->attr = reqAttrStates;
20000 } else {
20001 ctxt->attrTop->next = reqAttrStates;
20002 }
20003 ctxt->attrTop = reqAttrStatesTop;
Daniel Veillardc0826a72004-08-10 14:17:33 +000020004 }
Daniel Veillard3646d642004-06-02 19:19:14 +000020005 /*
20006 * Process wildcards.
20007 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020008
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020009 if ((type != NULL) && (type->attributeWildcard != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000020010#ifdef DEBUG_ATTR_VALIDATION
20011 xmlSchemaWildcardNsPtr ns;
20012 printf("matching wildcard: [%d] of complexType: %s\n", type->attributeWildcard, type->name);
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000020013 if (type->attributeWildcard->processContents ==
20014 XML_SCHEMAS_ANY_LAX)
20015 printf("processContents: lax\n");
20016 else if (type->attributeWildcard->processContents ==
20017 XML_SCHEMAS_ANY_STRICT)
20018 printf("processContents: strict\n");
20019 else
20020 printf("processContents: skip\n");
Daniel Veillard3646d642004-06-02 19:19:14 +000020021 if (type->attributeWildcard->any)
20022 printf("type: any\n");
20023 else if (type->attributeWildcard->negNsSet != NULL) {
20024 printf("type: negated\n");
20025 if (type->attributeWildcard->negNsSet->value == NULL)
20026 printf("ns: (absent)\n");
20027 else
20028 printf("ns: %s\n", type->attributeWildcard->negNsSet->value);
20029 } else if (type->attributeWildcard->nsSet != NULL) {
20030 printf("type: set\n");
20031 ns = type->attributeWildcard->nsSet;
20032 while (ns != NULL) {
20033 if (ns->value == NULL)
20034 printf("ns: (absent)\n");
20035 else
20036 printf("ns: %s\n", ns->value);
20037 ns = ns->next;
20038 }
20039 } else
20040 printf("empty\n");
20041
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000020042
20043#endif
Daniel Veillard3646d642004-06-02 19:19:14 +000020044 curState = ctxt->attr;
20045 while (curState != NULL) {
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000020046 if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
20047 if (curState->attr->ns != NULL)
20048 nsURI = curState->attr->ns->href;
20049 else
20050 nsURI = NULL;
20051 if (xmlSchemaMatchesWildcardNs(type->attributeWildcard,
20052 nsURI)) {
20053 /*
20054 * Handle processContents.
20055 */
20056 if ((type->attributeWildcard->processContents ==
20057 XML_SCHEMAS_ANY_LAX) ||
20058 (type->attributeWildcard->processContents ==
20059 XML_SCHEMAS_ANY_STRICT)) {
20060
20061 attr = curState->attr;
20062 attrDecl = xmlSchemaGetAttribute(ctxt->schema,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020063 attr->name, nsURI);
20064 curState->decl = attrDecl;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000020065 if (attrDecl != NULL) {
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000020066 curState->decl = attrDecl;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020067 curState->state = XML_SCHEMAS_ATTR_VALIDATE_VALUE;
20068 /* TODO
20069 ret = xmlSchemaCheckAttrLocallyValid(ctxt, attrDecl, curState, attr);
20070 */
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000020071 } else if (type->attributeWildcard->processContents ==
20072 XML_SCHEMAS_ANY_LAX) {
20073 curState->state = XML_SCHEMAS_ATTR_CHECKED;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020074 } else
20075 curState->state = XML_SCHEMAS_ATTR_WILD_NO_DECL;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000020076 } else
Daniel Veillard3646d642004-06-02 19:19:14 +000020077 curState->state = XML_SCHEMAS_ATTR_CHECKED;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020078 }
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000020079 }
Daniel Veillard3646d642004-06-02 19:19:14 +000020080 curState = curState->next;
20081 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020082 }
20083
Daniel Veillardc0826a72004-08-10 14:17:33 +000020084 if (ctxt->attr != NULL) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020085 int valueNeeded;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020086
20087 /*
20088 * Validate the value of the attribute.
20089 */
20090 if (ctxt->value != NULL) {
20091 xmlSchemaFreeValue(ctxt->value);
20092 ctxt->value = NULL;
20093 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000020094 curState = ctxt->attr;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020095 while ((curState != NULL) && (curState != ctxt->attrTop->next)) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020096 valueNeeded = 0;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020097 switch (curState->state) {
20098 case XML_SCHEMAS_ATTR_VALIDATE_VALUE:
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020099
20100 /*
20101 * Create an attribute info if needed.
20102 */
20103 if (ctxt->attrInfo == NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020104 ctxt->attrInfo = (xmlSchemaNodeInfoPtr)
20105 xmlMalloc(sizeof(xmlSchemaNodeInfo));
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020106 if (ctxt->attrInfo == NULL) {
20107 xmlSchemaVErrMemory(ctxt,
20108 "allocating an attribute info", NULL);
20109 goto fatal_exit;
20110 }
20111 }
20112 /*
20113 * Init the attribute info.
20114 */
20115 ctxt->attrInfo->flags = 0;
20116 ctxt->attrInfo->node = (xmlNodePtr) curState->attr;
20117 ctxt->attrInfo->decl = (xmlSchemaTypePtr) curState->decl;
20118 ctxt->attrInfo->value = NULL;
20119 if (curState->decl != NULL)
20120 ctxt->attrInfo->typeDef = curState->decl->subtypes;
20121 else
20122 ctxt->attrInfo->typeDef = NULL;
20123 if (curState->attr->ns != NULL)
20124 ctxt->attrInfo->namespaceName =
20125 curState->attr->ns->href;
20126 else
20127 ctxt->attrInfo->namespaceName = NULL;
20128 ctxt->attrInfo->localName = curState->attr->name;
20129
20130 ctxt->nodeInfo = ctxt->attrInfo;
20131
20132#ifdef IDC_ENABLED
20133 /*
20134 * Evaluate IDCs.
20135 */
20136 if (ctxt->xpathStates != NULL) {
20137 ret = xmlSchemaXPathEvaluate(ctxt,
20138 XML_ATTRIBUTE_NODE);
20139 if (ret == -1)
20140 goto fatal_exit;
20141 }
20142
20143#endif
20144 ret = xmlSchemaCheckAttrLocallyValid(ctxt, curState);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020145 if (ret == -1)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020146 goto fatal_exit;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020147 if ((ret != 0) && (ctxt->value != NULL)) {
20148 xmlSchemaFreeValue(ctxt->value);
20149 ctxt->value = NULL;
20150 }
20151 /* No break on purpose. */
20152 case XML_SCHEMAS_ATTR_CHECKED:
20153#ifdef IDC_ENABLED
20154 if (ctxt->xpathStates != NULL) {
20155 /*
20156 * Evaluate IDCs.
20157 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020158 if (ctxt->value != NULL) {
20159 ctxt->attrInfo->value = ctxt->value;
20160 ctxt->value = NULL;
20161 }
20162 if (xmlSchemaXPathProcessHistory(ctxt, ctxt->depth +1) == -1)
20163 goto fatal_exit;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020164 }
20165 break;
20166#endif
20167 default:
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020168 break;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020169 }
20170 curState = curState->next;
20171 }
20172
20173 /*
20174 * Report missing and illegal attributes.
20175 */
20176 curState = ctxt->attr;
20177 while ((curState != NULL) && (curState != ctxt->attrTop->next)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000020178 if (curState->state != XML_SCHEMAS_ATTR_CHECKED) {
20179 attr = curState->attr;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020180 if (curState->decl != NULL) {
20181 if (curState->decl->ref != NULL)
20182 attrDecl = curState->decl->refDecl;
20183 else
20184 attrDecl = curState->decl;
20185 } else
20186 attrDecl = NULL;
20187 if (curState->state == XML_SCHEMAS_ATTR_MISSING) {
20188 xmlSchemaVMissingAttrErr(ctxt, elem, attrDecl);
20189 } else if (curState->state ==
20190 XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED) {
20191 xmlSchemaVCustomErr(ctxt,
20192 XML_SCHEMAV_CVC_ATTRIBUTE_2,
20193 (xmlNodePtr) attr,
20194 (xmlSchemaTypePtr) attrDecl,
20195 "The type definition is absent",
20196 NULL);
20197 } else if (curState->state ==
20198 XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE) {
20199 xmlSchemaVCustomErr(ctxt,
20200 XML_SCHEMAV_CVC_AU,
20201 (xmlNodePtr) attr, (xmlSchemaTypePtr) attrDecl,
20202 "The value does not match the fixed value "
20203 "constraint", NULL);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020204 } else if (curState->state == XML_SCHEMAS_ATTR_WILD_NO_DECL) {
20205 xmlSchemaVWildcardErr(ctxt,
20206 XML_SCHEMAV_CVC_WILDCARD,
20207 (xmlNodePtr) attr,
20208 type->attributeWildcard,
20209 "No global attribute declaration found, but "
20210 "stipulated by the strict processContents of "
20211 "the wildcard");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020212 } else if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000020213 /* TODO: "prohibited" won't ever be touched here!.
20214 (curState->state == XML_SCHEMAS_ATTR_PROHIBITED))
20215 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020216 /*
20217 * TODO: One might report different error messages
20218 * for the following errors.
20219 */
20220 if ((type == NULL) || (type->attributeWildcard == NULL)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000020221 xmlSchemaVIllegalAttrErr(ctxt,
20222 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, attr);
20223 } else {
20224 xmlSchemaVIllegalAttrErr(ctxt,
20225 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, attr);
20226 }
20227 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000020228 }
20229 curState = curState->next;
20230 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020231 }
20232
20233 /*
20234 * Add missing default/fixed attributes.
20235 */
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000020236 if (defAttrStates != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020237 curState = defAttrStates;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000020238
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020239 while (curState != NULL) {
20240 attrDecl = curState->decl;
20241 if (attrDecl->ref != NULL)
20242 attrDecl = attrDecl->refDecl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020243
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000020244#ifdef IDC_ENABLED
20245 /*
20246 * Evaluate IDCs on default attributes.
20247 */
20248 if (ctxt->xpathStates != NULL) {
20249 /*
20250 * Create an attribute info if needed.
20251 */
20252 if (ctxt->attrInfo == NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020253 ctxt->attrInfo = (xmlSchemaNodeInfoPtr)
20254 xmlMalloc(sizeof(xmlSchemaNodeInfo));
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000020255 if (ctxt->attrInfo == NULL) {
20256 xmlSchemaVErrMemory(ctxt,
20257 "allocating an attribute info", NULL);
20258 goto fatal_exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020259 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020260 ctxt->attrInfo->value = NULL;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000020261 }
20262 /*
20263 * Init the attribute info.
Kasimier T. Buchcik285ebab2005-03-04 18:04:59 +000020264 * TODO: Hmm, maby a bit oversized this all.
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000020265 */
20266 ctxt->attrInfo->flags = 0;
20267 ctxt->attrInfo->decl = (xmlSchemaTypePtr) attrDecl;
20268 ctxt->attrInfo->node = NULL;
20269 ctxt->attrInfo->typeDef = attrDecl->subtypes;
20270 ctxt->attrInfo->namespaceName = attrDecl->targetNamespace;
20271 ctxt->attrInfo->localName = attrDecl->name;
20272
20273 ctxt->nodeInfo = ctxt->attrInfo;
20274
20275 ret = xmlSchemaXPathEvaluate(ctxt,
20276 XML_ATTRIBUTE_NODE);
20277 if (ret == -1)
20278 goto fatal_exit;
20279 if (ctxt->attrInfo->value != NULL) {
20280 xmlSchemaFreeValue(ctxt->attrInfo->value);
20281 ctxt->attrInfo->value = NULL;
20282 }
20283 if (ret > 0) {
Kasimier T. Buchcik285ebab2005-03-04 18:04:59 +000020284 /*
20285 * IDCs will consume the precomputed default value,
20286 * so we need to clone it somehow.
20287 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020288 /*
20289 * string or anySimpleType does not create a precomputed value
20290 * by default, so it will be created here on demand.
20291 * TODO: default/fixed attributes are a bit unoptimized:
20292 * the string value will be hold by ->defValue and inside
20293 * the precomputed value.
20294 */
20295 if (attrDecl->defVal == NULL) {
20296 xmlChar *str = xmlStrdup(attrDecl->defValue);
20297
20298 if (xmlSchemaPostCreateVal(ctxt,
20299 str,
20300 &(attrDecl->defVal)) == -1) {
20301 FREE_AND_NULL(str)
20302 goto fatal_exit;
20303 }
20304 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000020305 ctxt->attrInfo->value = xmlSchemaCopyValue(attrDecl->defVal);
20306 /* TODO: error on NULL return. */
20307 }
Kasimier T. Buchcik285ebab2005-03-04 18:04:59 +000020308
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000020309 if (xmlSchemaXPathProcessHistory(ctxt, ctxt->depth +1) == -1)
20310 goto fatal_exit;
20311 }
20312#endif
20313
20314 if (ctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
20315 /*
20316 * PSVI: Add a new attribute node to the current element.
20317 */
20318 if (attrDecl->targetNamespace == NULL) {
20319 xmlNewProp(elem, attrDecl->name, curState->value);
20320 } else {
20321 xmlNsPtr ns;
20322
20323 ns = xmlSearchNsByHref(elem->doc, elem,
20324 attrDecl->targetNamespace);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020325 if (ns == NULL) {
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000020326 xmlChar prefix[12];
20327 int counter = 1;
20328
20329 attr = curState->attr;
20330 /*
20331 * Create a namespace declaration on the validation
20332 * root node if no namespace declaration is in scope.
20333 */
20334 snprintf((char *) prefix, sizeof(prefix), "p");
20335 /*
20336 * This is somehow not performant, since the ancestor
20337 * axis beyond @elem will be searched as well.
20338 */
20339 ns = xmlSearchNs(elem->doc, elem, BAD_CAST prefix);
20340 while (ns != NULL) {
20341 if (counter > 1000) {
20342 xmlSchemaVErr(ctxt, (xmlNodePtr) attr,
20343 XML_SCHEMAV_INTERNAL,
20344 "Internal error: xmlSchemaValidateAttributes, "
20345 "could not compute a ns prefix for "
20346 "default/fixed attribute '%s'.\n",
20347 attrDecl->name, NULL);
20348
20349 break;
20350 }
20351 snprintf((char *) prefix,
20352 sizeof(prefix), "p%d", counter++);
20353 ns = xmlSearchNs(elem->doc, elem,
20354 BAD_CAST prefix);
20355 }
20356 if (ns == NULL) {
20357 ns = xmlNewNs(ctxt->validationRoot,
20358 attrDecl->targetNamespace, BAD_CAST prefix);
20359 xmlNewNsProp(elem, ns, attrDecl->name,
20360 curState->value);
20361 }
20362 } else {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020363 xmlNewNsProp(elem, ns, attrDecl->name,
20364 curState->value);
20365 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020366 }
20367 }
20368 curState = curState->next;
20369 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000020370 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020371 ret = ctxt->err;
20372 goto exit;
20373
20374fatal_exit:
20375 ret = -1;
20376
20377exit:
20378
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020379 if (defAttrStates != NULL)
20380 xmlSchemaFreeAttributeStates(defAttrStates);
20381
Daniel Veillard3646d642004-06-02 19:19:14 +000020382#ifdef DEBUG_ATTR_VALIDATION
20383 if (redundant)
20384 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020385 "xmlSchemaValidateAttributes: redundant call by "
20386 "type: %s\n", type->name);
Daniel Veillard3646d642004-06-02 19:19:14 +000020387#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020388 ctxt->nodeInfo = ctxt->elemInfos[ctxt->depth];
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020389 ctxt->node = oldnode;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020390 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000020391}
20392
20393/**
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020394 * xmlSchemaStartValidation:
Daniel Veillard4255d502002-04-16 15:50:10 +000020395 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000020396 *
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020397 * The starting point of the validation, called by
20398 * xmlSchemaValidateDocument and xmlSchemaValidateOneElement.
Daniel Veillard4255d502002-04-16 15:50:10 +000020399 *
20400 * Returns 0 if the element is schemas valid, a positive error code
20401 * number otherwise and -1 in case of internal or API error.
20402 */
20403static int
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020404xmlSchemaStartValidation(xmlSchemaValidCtxtPtr ctxt)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020405{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020406 xmlSchemaElementPtr elemDecl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020407 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000020408
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020409 ctxt->err = 0;
20410 ctxt->nberrors = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020411 if (ctxt->schema == NULL) {
20412 /*
20413 * No schema was specified at time of creation of the validation
20414 * context. Use xsi:schemaLocation and xsi:noNamespaceSchemaLocation
20415 * of the instance to build a schema.
20416 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020417 if (ctxt->pctxt == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020418 if (xmlSchemaCreatePCtxtOnVCtxt(ctxt) == -1)
20419 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020420 ctxt->schema = xmlSchemaNewSchema(ctxt->pctxt);
20421 if (ctxt->schema == NULL)
20422 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020423 ctxt->xsiAssemble = 1;
20424 } else
20425 ctxt->xsiAssemble = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020426 /*
20427 * Assemble new schemata using xsi.
Daniel Veillardc0826a72004-08-10 14:17:33 +000020428 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020429 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020430 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
20431 if (ret == -1) {
20432 xmlSchemaVCustomErr(ctxt,
20433 XML_SCHEMAV_INTERNAL,
20434 ctxt->node, NULL,
20435 "Internal error: xmlSchemaValidateElement, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020436 "assembling schema by xsi", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020437 }
20438 /*
20439 * NOTE: We won't react on schema parser errors here.
20440 * TODO: But a warning would be nice.
20441 */
20442 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020443 if (ret != -1) {
20444 if (ctxt->node->ns != NULL)
20445 elemDecl = xmlSchemaGetElem(ctxt->schema, ctxt->node->name,
20446 ctxt->node->ns->href);
20447 else
20448 elemDecl = xmlSchemaGetElem(ctxt->schema, ctxt->node->name, NULL);
20449
20450 if (elemDecl == NULL) {
20451 xmlSchemaVCustomErr(ctxt,
20452 XML_SCHEMAV_CVC_ELT_1,
20453 ctxt->node, NULL,
20454 "No matching global declaration available", NULL);
20455 ret = XML_SCHEMAV_CVC_ELT_1;
20456 } else {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020457 /*
20458 * Augment the IDC definitions.
20459 */
20460 if (ctxt->schema->idcDef != NULL) {
20461 xmlHashScan(ctxt->schema->idcDef,
20462 (xmlHashScanner) xmlSchemaAugmentIDC, ctxt);
20463 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020464 ctxt->depth = -1;
20465 xmlSchemaBeginElement(ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020466 ret = xmlSchemaValidateElementByDeclaration(ctxt, elemDecl);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020467 xmlSchemaEndElement(ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020468 if (ret < 0) {
20469 xmlSchemaVCustomErr(ctxt,
20470 XML_SCHEMAV_INTERNAL, ctxt->node, NULL,
20471 "Internal error: xmlSchemaValidateElement, "
20472 "calling validation by declaration", NULL);
20473 }
20474 }
20475 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020476
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020477 if (ctxt->xsiAssemble) {
20478 if (ctxt->schema != NULL) {
20479 xmlSchemaFree(ctxt->schema);
20480 ctxt->schema = NULL;
20481 }
Daniel Veillard4255d502002-04-16 15:50:10 +000020482 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020483 xmlSchemaClearValidCtxt(ctxt);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020484 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000020485}
20486
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020487
Daniel Veillard4255d502002-04-16 15:50:10 +000020488/**
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000020489 * xmlSchemaValidateOneElement:
20490 * @ctxt: a schema validation context
20491 * @elem: an element node
20492 *
20493 * Validate a branch of a tree, starting with the given @elem.
20494 *
20495 * Returns 0 if the element and its subtree is valid, a positive error
20496 * code number otherwise and -1 in case of an internal or API error.
20497 */
20498int
20499xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
20500{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020501 if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000020502 return (-1);
20503
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020504 if (ctxt->schema == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020505 xmlSchemaVErr(ctxt, NULL,
20506 XML_SCHEMAV_INTERNAL,
20507 "API error: xmlSchemaValidateOneElement, "
20508 "no schema specified.\n", NULL, NULL);
20509 return (-1);
20510 }
20511
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000020512 ctxt->doc = elem->doc;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020513 ctxt->node = elem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020514 ctxt->validationRoot = elem;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020515 return (xmlSchemaStartValidation(ctxt));
Daniel Veillard4255d502002-04-16 15:50:10 +000020516}
20517
20518/************************************************************************
20519 * *
20520 * SAX Validation code *
20521 * *
20522 ************************************************************************/
20523
20524/************************************************************************
20525 * *
20526 * Validation interfaces *
20527 * *
20528 ************************************************************************/
20529
20530/**
20531 * xmlSchemaNewValidCtxt:
20532 * @schema: a precompiled XML Schemas
20533 *
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020534 * Create an XML Schemas validation context based on the given schema.
Daniel Veillard4255d502002-04-16 15:50:10 +000020535 *
20536 * Returns the validation context or NULL in case of error
20537 */
20538xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020539xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
20540{
Daniel Veillard4255d502002-04-16 15:50:10 +000020541 xmlSchemaValidCtxtPtr ret;
20542
20543 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
20544 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020545 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000020546 return (NULL);
20547 }
20548 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
Daniel Veillardc0826a72004-08-10 14:17:33 +000020549 ret->schema = schema;
Daniel Veillard4255d502002-04-16 15:50:10 +000020550 return (ret);
20551}
20552
20553/**
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020554 * xmlSchemaClearValidCtxt:
20555 * @ctxt: the schema validation context
20556 *
20557 * Free the resources associated to the schema validation context;
20558 * leaves some fields alive intended for reuse of the context.
20559 */
20560static void
20561xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
20562{
20563 if (vctxt == NULL)
20564 return;
20565
20566 vctxt->validationRoot = NULL;
20567 if (vctxt->attr != NULL) {
20568 xmlSchemaFreeAttributeStates(vctxt->attr);
20569 vctxt->attr = NULL;
20570 }
20571 if (vctxt->value != NULL) {
20572 xmlSchemaFreeValue(vctxt->value);
20573 vctxt->value = NULL;
20574 }
20575 /*
20576 * Augmented IDC information.
20577 */
20578 if (vctxt->aidcs != NULL) {
20579 xmlSchemaIDCAugPtr cur = vctxt->aidcs, next;
20580 do {
20581 next = cur->next;
20582 xmlFree(cur);
20583 cur = next;
20584 } while (cur != NULL);
20585 vctxt->aidcs = NULL;
20586 }
20587 if (vctxt->idcNodes != NULL) {
20588 int i;
20589 xmlSchemaPSVIIDCNodePtr item;
20590
20591 for (i = 0; i < vctxt->nbIdcNodes; i++) {
20592 item = vctxt->idcNodes[i];
20593 xmlFree(item->keys);
20594 xmlFree(item);
20595 }
20596 xmlFree(vctxt->idcNodes);
20597 vctxt->idcNodes = NULL;
20598 }
20599 /*
20600 * Note that we won't delete the XPath state pool here.
20601 */
20602 if (vctxt->xpathStates != NULL) {
20603 xmlSchemaFreeIDCStateObjList(vctxt->xpathStates);
20604 vctxt->xpathStates = NULL;
20605 }
20606 if (vctxt->attrInfo != NULL) {
20607 if (vctxt->attrInfo->value != NULL) {
20608 xmlSchemaFreeValue(vctxt->attrInfo->value);
20609 }
20610 memset(vctxt->attrInfo, 0, sizeof(xmlSchemaNodeInfo));
20611 }
20612 if (vctxt->elemInfos != NULL) {
20613 int i;
20614 xmlSchemaNodeInfoPtr info;
20615
20616 for (i = 0; i < vctxt->sizeElemInfos; i++) {
20617 info = vctxt->elemInfos[i];
20618 if (info == NULL)
20619 break;
20620 if (info->value != NULL) {
20621 xmlSchemaFreeValue(info->value);
20622 info->value = NULL;
20623 }
20624 if (info->idcMatchers != NULL) {
20625 xmlSchemaIDCFreeMatcherList(info->idcMatchers);
20626 info->idcMatchers = NULL;
20627 }
20628 if (info->idcTable != NULL) {
20629 xmlSchemaIDCFreeIDCTable(info->idcTable);
20630 info->idcTable = NULL;
20631 }
20632 }
20633 }
20634}
20635
20636/**
Daniel Veillard4255d502002-04-16 15:50:10 +000020637 * xmlSchemaFreeValidCtxt:
20638 * @ctxt: the schema validation context
20639 *
20640 * Free the resources associated to the schema validation context
20641 */
20642void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020643xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
20644{
Daniel Veillard4255d502002-04-16 15:50:10 +000020645 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020646 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000020647 if (ctxt->attr != NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000020648 xmlSchemaFreeAttributeStates(ctxt->attr);
Daniel Veillard88c58912002-04-23 07:12:20 +000020649 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020650 xmlSchemaFreeValue(ctxt->value);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020651 if (ctxt->pctxt != NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020652 xmlSchemaFreeParserCtxt(ctxt->pctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020653 if (ctxt->idcNodes != NULL) {
20654 int i;
20655 xmlSchemaPSVIIDCNodePtr item;
20656
20657 for (i = 0; i < ctxt->nbIdcNodes; i++) {
20658 item = ctxt->idcNodes[i];
20659 xmlFree(item->keys);
20660 xmlFree(item);
20661 }
20662 xmlFree(ctxt->idcNodes);
20663 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020664 if (ctxt->idcKeys != NULL) {
20665 int i;
20666 for (i = 0; i < ctxt->nbIdcKeys; i++)
20667 xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
20668 xmlFree(ctxt->idcKeys);
20669 }
20670
20671 if (ctxt->xpathStates != NULL)
20672 xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
20673 if (ctxt->xpathStatePool != NULL)
20674 xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
20675
20676 /*
20677 * Augmented IDC information.
20678 */
20679 if (ctxt->aidcs != NULL) {
20680 xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
20681 do {
20682 next = cur->next;
20683 xmlFree(cur);
20684 cur = next;
20685 } while (cur != NULL);
20686 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020687 if (ctxt->attrInfo != NULL) {
20688 if (ctxt->attrInfo->value != NULL)
20689 xmlSchemaFreeValue(ctxt->attrInfo->value);
20690 xmlFree(ctxt->attrInfo);
20691 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020692 if (ctxt->elemInfos != NULL) {
20693 int i;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020694 xmlSchemaNodeInfoPtr info;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020695
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020696 for (i = 0; i < ctxt->sizeElemInfos; i++) {
20697 info = ctxt->elemInfos[i];
20698 if (info == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020699 break;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020700 if (info->value != NULL)
20701 xmlSchemaFreeValue(info->value);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020702 if (info->idcMatchers != NULL)
20703 xmlSchemaIDCFreeMatcherList(info->idcMatchers);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020704 if (info->idcTable != NULL)
20705 xmlSchemaIDCFreeIDCTable(info->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020706 /*
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020707 * TODO: Don't know if those will have to be freed if in streaming
20708 * mode.
20709 *
20710 * xmlFree(info->localName);
20711 * if (info->namespaceName != NULL)
20712 * xmlFree(info->namespaceName);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020713 */
20714 xmlFree(info);
20715 }
20716 xmlFree(ctxt->elemInfos);
20717 }
Daniel Veillard4255d502002-04-16 15:50:10 +000020718 xmlFree(ctxt);
20719}
20720
20721/**
20722 * xmlSchemaSetValidErrors:
20723 * @ctxt: a schema validation context
20724 * @err: the error function
20725 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +000020726 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +000020727 *
William M. Brack2f2a6632004-08-20 23:09:47 +000020728 * Set the error and warning callback informations
Daniel Veillard4255d502002-04-16 15:50:10 +000020729 */
20730void
20731xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020732 xmlSchemaValidityErrorFunc err,
20733 xmlSchemaValidityWarningFunc warn, void *ctx)
20734{
Daniel Veillard4255d502002-04-16 15:50:10 +000020735 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020736 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000020737 ctxt->error = err;
20738 ctxt->warning = warn;
20739 ctxt->userData = ctx;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020740 if (ctxt->pctxt != NULL)
20741 xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
Daniel Veillard4255d502002-04-16 15:50:10 +000020742}
20743
20744/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000020745 * xmlSchemaGetValidErrors:
20746 * @ctxt: a XML-Schema validation context
20747 * @err: the error function result
20748 * @warn: the warning function result
20749 * @ctx: the functions context result
20750 *
20751 * Get the error and warning callback informations
20752 *
20753 * Returns -1 in case of error and 0 otherwise
20754 */
20755int
20756xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
20757 xmlSchemaValidityErrorFunc * err,
20758 xmlSchemaValidityWarningFunc * warn, void **ctx)
20759{
20760 if (ctxt == NULL)
20761 return (-1);
20762 if (err != NULL)
20763 *err = ctxt->error;
20764 if (warn != NULL)
20765 *warn = ctxt->warning;
20766 if (ctx != NULL)
20767 *ctx = ctxt->userData;
20768 return (0);
20769}
20770
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020771
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020772/**
Daniel Veillard6927b102004-10-27 17:29:04 +000020773 * xmlSchemaSetValidOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020774 * @ctxt: a schema validation context
20775 * @options: a combination of xmlSchemaValidOption
20776 *
20777 * Sets the options to be used during the validation.
20778 *
20779 * Returns 0 in case of success, -1 in case of an
20780 * API error.
20781 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020782int
20783xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
20784 int options)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020785
20786{
20787 int i;
20788
20789 if (ctxt == NULL)
20790 return (-1);
20791 /*
20792 * WARNING: Change the start value if adding to the
20793 * xmlSchemaValidOption.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020794 * TODO: Is there an other, more easy to maintain,
20795 * way?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020796 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020797 for (i = 1; i < (int) sizeof(int) * 8; i++) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020798 if (options & 1<<i) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020799 xmlSchemaVErr(ctxt, NULL,
20800 XML_SCHEMAV_INTERNAL,
20801 "Internal error: xmlSchemaSetValidOptions, "
20802 "invalid option argument.\n", NULL, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020803 return (-1);
20804 }
20805 }
20806 ctxt->options = options;
20807 return (0);
20808}
20809
20810/**
Daniel Veillard6927b102004-10-27 17:29:04 +000020811 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020812 * @ctxt: a schema validation context
20813 *
William M. Brack21e4ef22005-01-02 09:53:13 +000020814 * Get the validation context options.
20815 *
20816 * Returns the option combination or -1 on error.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020817 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020818int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020819xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
20820
20821{
20822 if (ctxt == NULL)
20823 return (-1);
20824 else
20825 return (ctxt->options);
20826}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020827
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020828
Daniel Veillard259f0df2004-08-18 09:13:18 +000020829/**
Daniel Veillard4255d502002-04-16 15:50:10 +000020830 * xmlSchemaValidateDoc:
20831 * @ctxt: a schema validation context
20832 * @doc: a parsed document tree
20833 *
20834 * Validate a document tree in memory.
20835 *
20836 * Returns 0 if the document is schemas valid, a positive error code
20837 * number otherwise and -1 in case of internal or API error.
20838 */
20839int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020840xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
20841{
Daniel Veillard4255d502002-04-16 15:50:10 +000020842 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020843 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000020844
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020845 ctxt->doc = doc;
20846 ctxt->node = xmlDocGetRootElement(doc);
20847 if (ctxt->node == NULL) {
20848 xmlSchemaVCustomErr(ctxt,
20849 XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
20850 (xmlNodePtr) doc, NULL,
20851 "The document has no document element", NULL);
20852 return (ctxt->err);
20853 }
20854 ctxt->validationRoot = ctxt->node;
20855 xmlSchemaStartValidation(ctxt);
20856
20857 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000020858}
20859
20860/**
20861 * xmlSchemaValidateStream:
20862 * @ctxt: a schema validation context
20863 * @input: the input to use for reading the data
20864 * @enc: an optional encoding information
20865 * @sax: a SAX handler for the resulting events
20866 * @user_data: the context to provide to the SAX handler.
20867 *
20868 * Validate a document tree in memory.
20869 *
20870 * Returns 0 if the document is schemas valid, a positive error code
20871 * number otherwise and -1 in case of internal or API error.
20872 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020873int
Daniel Veillard4255d502002-04-16 15:50:10 +000020874xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020875 xmlParserInputBufferPtr input, xmlCharEncoding enc,
20876 xmlSAXHandlerPtr sax, void *user_data)
20877{
Daniel Veillard4255d502002-04-16 15:50:10 +000020878 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020879 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000020880 ctxt->input = input;
20881 ctxt->enc = enc;
20882 ctxt->sax = sax;
20883 ctxt->user_data = user_data;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020884 TODO return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000020885}
20886
20887#endif /* LIBXML_SCHEMAS_ENABLED */