blob: c7527bd968ecbc956f47acc85681e6dd00f859c3 [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);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +0000565static int
566xmlSchemaPostCreateVal(xmlSchemaValidCtxtPtr vctxt,
567 xmlSchemaTypePtr type,
568 const xmlChar *value,
569 xmlSchemaValPtr *val);
570static xmlSchemaTypePtr
571xmlSchemaGetSimpleContentType(xmlSchemaTypePtr complexType);
572static int
573xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type);
William M. Brack87640d52004-04-17 14:58:15 +0000574
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000575/************************************************************************
576 * *
577 * Datatype error handlers *
578 * *
579 ************************************************************************/
580
581/**
582 * xmlSchemaPErrMemory:
583 * @node: a context node
584 * @extra: extra informations
585 *
586 * Handle an out of memory condition
587 */
588static void
589xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
590 const char *extra, xmlNodePtr node)
591{
592 if (ctxt != NULL)
593 ctxt->nberrors++;
594 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
595 extra);
596}
597
598/**
599 * xmlSchemaPErr:
600 * @ctxt: the parsing context
601 * @node: the context node
602 * @error: the error code
603 * @msg: the error message
604 * @str1: extra data
605 * @str2: extra data
606 *
607 * Handle a parser error
608 */
609static void
610xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
611 const char *msg, const xmlChar * str1, const xmlChar * str2)
612{
613 xmlGenericErrorFunc channel = NULL;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000614 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000615 void *data = NULL;
616
617 if (ctxt != NULL) {
618 ctxt->nberrors++;
619 channel = ctxt->error;
620 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000621 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000622 }
Daniel Veillard659e71e2003-10-10 14:10:40 +0000623 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000624 error, XML_ERR_ERROR, NULL, 0,
625 (const char *) str1, (const char *) str2, NULL, 0, 0,
626 msg, str1, str2);
627}
628
629/**
630 * xmlSchemaPErr2:
631 * @ctxt: the parsing context
632 * @node: the context node
633 * @node: the current child
634 * @error: the error code
635 * @msg: the error message
636 * @str1: extra data
637 * @str2: extra data
638 *
639 * Handle a parser error
640 */
641static void
642xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
643 xmlNodePtr child, int error,
644 const char *msg, const xmlChar * str1, const xmlChar * str2)
645{
646 if (child != NULL)
647 xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
648 else
649 xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
650}
651
Daniel Veillard01fa6152004-06-29 17:04:39 +0000652
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000653/**
Daniel Veillard3646d642004-06-02 19:19:14 +0000654 * xmlSchemaPErrExt:
655 * @ctxt: the parsing context
656 * @node: the context node
657 * @error: the error code
658 * @strData1: extra data
659 * @strData2: extra data
660 * @strData3: extra data
661 * @msg: the message
662 * @str1: extra parameter for the message display
663 * @str2: extra parameter for the message display
664 * @str3: extra parameter for the message display
665 * @str4: extra parameter for the message display
666 * @str5: extra parameter for the message display
667 *
668 * Handle a parser error
669 */
670static void
671xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
672 const xmlChar * strData1, const xmlChar * strData2,
673 const xmlChar * strData3, const char *msg, const xmlChar * str1,
674 const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
675 const xmlChar * str5)
676{
677
678 xmlGenericErrorFunc channel = NULL;
679 xmlStructuredErrorFunc schannel = NULL;
680 void *data = NULL;
681
682 if (ctxt != NULL) {
683 ctxt->nberrors++;
684 channel = ctxt->error;
685 data = ctxt->userData;
686 schannel = ctxt->serror;
687 }
688 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
689 error, XML_ERR_ERROR, NULL, 0,
690 (const char *) strData1, (const char *) strData2,
William M. Brack803812b2004-06-03 02:11:24 +0000691 (const char *) strData3, 0, 0, msg, str1, str2,
692 str3, str4, str5);
Daniel Veillard3646d642004-06-02 19:19:14 +0000693}
Daniel Veillard01fa6152004-06-29 17:04:39 +0000694
Daniel Veillard3646d642004-06-02 19:19:14 +0000695
696/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000697 * xmlSchemaVTypeErrMemory:
698 * @node: a context node
699 * @extra: extra informations
700 *
701 * Handle an out of memory condition
702 */
703static void
704xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
705 const char *extra, xmlNodePtr node)
706{
707 if (ctxt != NULL) {
708 ctxt->nberrors++;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000709 ctxt->err = XML_SCHEMAV_INTERNAL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000710 }
711 __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
712 extra);
713}
714
715/**
716 * xmlSchemaVErr3:
717 * @ctxt: the validation context
718 * @node: the context node
719 * @error: the error code
720 * @msg: the error message
721 * @str1: extra data
722 * @str2: extra data
723 * @str3: extra data
724 *
725 * Handle a validation error
726 */
727static void
728xmlSchemaVErr3(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
729 const char *msg, const xmlChar *str1, const xmlChar *str2,
730 const xmlChar *str3)
731{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000732 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000733 xmlGenericErrorFunc channel = NULL;
734 void *data = NULL;
735
736 if (ctxt != NULL) {
737 ctxt->nberrors++;
738 ctxt->err = error;
739 channel = ctxt->error;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000740 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000741 data = ctxt->userData;
742 }
743 /* reajust to global error numbers */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000744 /* Removed, since the old schema error codes have been
745 * substituted for the global error codes.
746 *
747 * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
748 */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000749 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000750 error, XML_ERR_ERROR, NULL, 0,
751 (const char *) str1, (const char *) str2,
752 (const char *) str3, 0, 0,
753 msg, str1, str2, str3);
754}
Daniel Veillardc0826a72004-08-10 14:17:33 +0000755
756/**
757 * xmlSchemaVErrExt:
758 * @ctxt: the validation context
759 * @node: the context node
760 * @error: the error code
761 * @msg: the message
762 * @str1: extra parameter for the message display
763 * @str2: extra parameter for the message display
764 * @str3: extra parameter for the message display
765 * @str4: extra parameter for the message display
766 * @str5: extra parameter for the message display
767 *
768 * Handle a validation error
769 */
770static void
771xmlSchemaVErrExt(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
772 const char *msg, const xmlChar * str1,
773 const xmlChar * str2, const xmlChar * str3,
774 const xmlChar * str4, const xmlChar * str5)
775{
776 xmlStructuredErrorFunc schannel = NULL;
777 xmlGenericErrorFunc channel = NULL;
778 void *data = NULL;
779
780 if (ctxt != NULL) {
781 ctxt->nberrors++;
782 ctxt->err = error;
783 channel = ctxt->error;
784 schannel = ctxt->serror;
785 data = ctxt->userData;
786 }
787 /* reajust to global error numbers */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000788 /* Removed, since the old schema error codes have been
789 * substituted for the global error codes.
790 *
791 * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
792 */
Daniel Veillardc0826a72004-08-10 14:17:33 +0000793 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
794 error, XML_ERR_ERROR, NULL, 0, NULL, NULL, NULL, 0, 0,
795 msg, str1, str2, str3, str4, str5);
796}
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000797/**
798 * xmlSchemaVErr:
799 * @ctxt: the validation context
800 * @node: the context node
801 * @error: the error code
802 * @msg: the error message
803 * @str1: extra data
804 * @str2: extra data
805 *
806 * Handle a validation error
807 */
808static void
809xmlSchemaVErr(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
810 const char *msg, const xmlChar * str1, const xmlChar * str2)
811{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000812 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000813 xmlGenericErrorFunc channel = NULL;
814 void *data = NULL;
815
816 if (ctxt != NULL) {
817 ctxt->nberrors++;
818 ctxt->err = error;
819 channel = ctxt->error;
820 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000821 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000822 }
823 /* reajust to global error numbers */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000824 /* Removed, since the old schema error codes have been
825 * substituted for the global error codes.
826 *
827 * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
828 */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000829 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000830 error, XML_ERR_ERROR, NULL, 0,
831 (const char *) str1, (const char *) str2, NULL, 0, 0,
832 msg, str1, str2);
833}
Daniel Veillard4255d502002-04-16 15:50:10 +0000834
Daniel Veillardc0826a72004-08-10 14:17:33 +0000835/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000836 * xmlSchemaGetAttrName:
Daniel Veillardc0826a72004-08-10 14:17:33 +0000837 * @attr: the attribute declaration/use
838 *
839 * Returns the name of the attribute; if the attribute
840 * is a reference, the name of the referenced global type will be returned.
841 */
842static const xmlChar *
843xmlSchemaGetAttrName(xmlSchemaAttributePtr attr)
844{
845 if (attr->ref != NULL)
846 return(attr->ref);
847 else
848 return(attr->name);
849}
850
851/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000852 * xmlSchemaGetAttrTargetNsURI:
Daniel Veillardc0826a72004-08-10 14:17:33 +0000853 * @type: the type (element or attribute)
854 *
855 * Returns the target namespace URI of the type; if the type is a reference,
856 * the target namespace of the referenced type will be returned.
857 */
858static const xmlChar *
859xmlSchemaGetAttrTargetNsURI(xmlSchemaAttributePtr attr)
860{
861 if (attr->ref != NULL)
862 return (attr->refNs);
863 else
864 return(attr->targetNamespace);
865}
866
867/**
868 * xmlSchemaFormatNsUriLocal:
869 * @buf: the string buffer
870 * @uri: the namespace URI
871 * @local: the local name
872 *
873 * Returns a representation of the given URI used
874 * for error reports.
875 *
876 * Returns an empty string, if @ns is NULL, a formatted
877 * string otherwise.
878 */
879static const xmlChar*
880xmlSchemaFormatNsUriLocal(xmlChar **buf,
881 const xmlChar *uri, const xmlChar *local)
882{
883 if (*buf != NULL)
884 xmlFree(*buf);
885 if (uri == NULL) {
886 *buf = xmlStrdup(BAD_CAST "{'");
887 *buf = xmlStrcat(*buf, local);
888 } else {
889 *buf = xmlStrdup(BAD_CAST "{'");
890 *buf = xmlStrcat(*buf, uri);
891 *buf = xmlStrcat(*buf, BAD_CAST "', '");
892 *buf = xmlStrcat(*buf, local);
893 }
894 *buf = xmlStrcat(*buf, BAD_CAST "'}");
895 return ((const xmlChar *) *buf);
896}
897
898/**
899 * xmlSchemaFormatNsPrefixLocal:
900 * @buf: the string buffer
901 * @ns: the namespace
902 * @local: the local name
903 *
904 * Returns a representation of the given URI used
905 * for error reports.
906 *
907 * Returns an empty string, if @ns is NULL, a formatted
908 * string otherwise.
909 */
910static const xmlChar*
911xmlSchemaFormatNsPrefixLocal(xmlChar **buf,
912 xmlNsPtr ns, const xmlChar *local)
913{
914 if (*buf != NULL) {
915 xmlFree(*buf);
916 *buf = NULL;
917 }
918 if ((ns == NULL) || (ns->prefix == NULL))
919 return(local);
920 else {
921 *buf = xmlStrdup(ns->prefix);
922 *buf = xmlStrcat(*buf, BAD_CAST ":");
923 *buf = xmlStrcat(*buf, local);
924 }
925 return ((const xmlChar *) *buf);
926}
927
928/**
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000929 * xmlSchemaFormatQName:
930 * @buf: the string buffer
931 * @namespaceName: the namespace name
932 * @localName: the local name
933 *
934 * Returns the given QName in the format "{namespaceName}localName" or
935 * just "localName" if @namespaceName is NULL.
936 *
937 * Returns the localName if @namespaceName is NULL, a formatted
938 * string otherwise.
939 */
940static const xmlChar*
941xmlSchemaFormatQName(xmlChar **buf,
942 const xmlChar *namespaceName,
943 const xmlChar *localName)
944{
945 FREE_AND_NULL(*buf)
946 if (namespaceName == NULL)
947 return(localName);
948
949 *buf = xmlStrdup(BAD_CAST "{");
950 *buf = xmlStrcat(*buf, namespaceName);
951 *buf = xmlStrcat(*buf, BAD_CAST "}");
952 *buf = xmlStrcat(*buf, localName);
953
954 return ((const xmlChar *) *buf);
955}
956
957/**
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +0000958 * xmlSchemaWildcardPCToString:
959 * @pc: the type of processContents
960 *
961 * Returns a string representation of the type of
962 * processContents.
963 */
964static const xmlChar *
965xmlSchemaWildcardPCToString(int pc)
966{
967 switch (pc) {
968 case XML_SCHEMAS_ANY_SKIP:
969 return (BAD_CAST "skip");
970 case XML_SCHEMAS_ANY_LAX:
971 return (BAD_CAST "lax");
972 case XML_SCHEMAS_ANY_STRICT:
973 return (BAD_CAST "strict");
974 default:
975 return (BAD_CAST "invalid process contents");
976 }
977}
978
979/**
Daniel Veillardc0826a72004-08-10 14:17:33 +0000980 * xmlSchemaFormatItemForReport:
981 * @buf: the string buffer
982 * @itemDes: the designation of the item
983 * @itemName: the name of the item
984 * @item: the item as an object
985 * @itemNode: the node of the item
986 * @local: the local name
987 * @parsing: if the function is used during the parse
988 *
989 * Returns a representation of the given item used
990 * for error reports.
991 *
992 * The following order is used to build the resulting
993 * designation if the arguments are not NULL:
994 * 1a. If itemDes not NULL -> itemDes
995 * 1b. If (itemDes not NULL) and (itemName not NULL)
996 * -> itemDes + itemName
997 * 2. If the preceding was NULL and (item not NULL) -> item
998 * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
999 *
1000 * If the itemNode is an attribute node, the name of the attribute
1001 * will be appended to the result.
1002 *
1003 * Returns the formatted string and sets @buf to the resulting value.
1004 */
1005static xmlChar*
1006xmlSchemaFormatItemForReport(xmlChar **buf,
1007 const xmlChar *itemDes,
1008 xmlSchemaTypePtr item,
1009 xmlNodePtr itemNode,
1010 int parsing)
1011{
1012 xmlChar *str = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00001013 int named = 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001014
1015 if (*buf != NULL) {
1016 xmlFree(*buf);
1017 *buf = NULL;
1018 }
1019
William M. Brack2f2a6632004-08-20 23:09:47 +00001020 if (itemDes != NULL) {
1021 *buf = xmlStrdup(itemDes);
1022 } else if (item != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001023 switch (item->type) {
1024 case XML_SCHEMA_TYPE_BASIC:
Daniel Veillardc0826a72004-08-10 14:17:33 +00001025 if (item->builtInType == XML_SCHEMAS_ANYTYPE)
1026 *buf = xmlStrdup(BAD_CAST "'anyType'");
1027 else if (item->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)
1028 *buf = xmlStrdup(BAD_CAST "'anySimpleType'");
1029 else {
1030 /* *buf = xmlStrdup(BAD_CAST "bi "); */
1031 /* *buf = xmlStrcat(*buf, xmlSchemaElemDesST); */
1032 *buf = xmlStrdup(BAD_CAST "'");
1033 *buf = xmlStrcat(*buf, item->name);
1034 *buf = xmlStrcat(*buf, BAD_CAST "'");
1035 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001036 break;
1037 case XML_SCHEMA_TYPE_SIMPLE:
Daniel Veillardc0826a72004-08-10 14:17:33 +00001038 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1039 *buf = xmlStrdup(xmlSchemaElemDesST);
1040 *buf = xmlStrcat(*buf, BAD_CAST " '");
1041 *buf = xmlStrcat(*buf, item->name);
1042 *buf = xmlStrcat(*buf, BAD_CAST "'");
1043 } else {
1044 *buf = xmlStrdup(xmlSchemaElemDesST);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001045 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001046 break;
1047 case XML_SCHEMA_TYPE_COMPLEX:
Daniel Veillardc0826a72004-08-10 14:17:33 +00001048 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1049 *buf = xmlStrdup(xmlSchemaElemDesCT);
1050 *buf = xmlStrcat(*buf, BAD_CAST " '");
1051 *buf = xmlStrcat(*buf, item->name);
1052 *buf = xmlStrcat(*buf, BAD_CAST "'");
1053 } else {
1054 *buf = xmlStrdup(xmlSchemaElemDesCT);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001055 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001056 break;
1057 case XML_SCHEMA_TYPE_ATTRIBUTE: {
1058 xmlSchemaAttributePtr attr;
1059
1060 attr = (xmlSchemaAttributePtr) item;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001061 if ((attr->flags & XML_SCHEMAS_ATTR_GLOBAL) ||
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001062 (attr->ref == NULL)) {
1063 *buf = xmlStrdup(xmlSchemaElemDesAttrDecl);
1064 *buf = xmlStrcat(*buf, BAD_CAST " '");
1065 *buf = xmlStrcat(*buf, attr->name);
1066 *buf = xmlStrcat(*buf, BAD_CAST "'");
1067 } else {
1068 *buf = xmlStrdup(xmlSchemaElemDesAttrRef);
1069 *buf = xmlStrcat(*buf, BAD_CAST " '");
1070 *buf = xmlStrcat(*buf, attr->refPrefix);
1071 *buf = xmlStrcat(*buf, BAD_CAST ":");
1072 *buf = xmlStrcat(*buf, attr->ref);
1073 *buf = xmlStrcat(*buf, BAD_CAST "'");
1074 }
1075 }
1076 break;
1077 case XML_SCHEMA_TYPE_ELEMENT: {
1078 xmlSchemaElementPtr elem;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001079
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001080 elem = (xmlSchemaElementPtr) item;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001081 if ((elem->flags & XML_SCHEMAS_ELEM_GLOBAL) ||
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001082 (elem->ref == NULL)) {
1083 *buf = xmlStrdup(xmlSchemaElemDesElemDecl);
1084 *buf = xmlStrcat(*buf, BAD_CAST " '");
1085 *buf = xmlStrcat(*buf, elem->name);
1086 *buf = xmlStrcat(*buf, BAD_CAST "'");
1087 } else {
1088 *buf = xmlStrdup(xmlSchemaElemDesElemRef);
1089 *buf = xmlStrcat(*buf, BAD_CAST " '");
1090 *buf = xmlStrcat(*buf, elem->refPrefix);
1091 *buf = xmlStrcat(*buf, BAD_CAST ":");
1092 *buf = xmlStrcat(*buf, elem->ref);
1093 *buf = xmlStrcat(*buf, BAD_CAST "'");
1094 }
1095 }
1096 break;
1097 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1098 case XML_SCHEMA_TYPE_IDC_KEY:
1099 case XML_SCHEMA_TYPE_IDC_KEYREF:
1100 if (item->type == XML_SCHEMA_TYPE_IDC_UNIQUE)
1101 *buf = xmlStrdup(BAD_CAST "unique '");
1102 else if (item->type == XML_SCHEMA_TYPE_IDC_KEY)
1103 *buf = xmlStrdup(BAD_CAST "key '");
1104 else
1105 *buf = xmlStrdup(BAD_CAST "keyRef '");
1106 *buf = xmlStrcat(*buf, ((xmlSchemaIDCPtr) item)->name);
1107 *buf = xmlStrcat(*buf, BAD_CAST "'");
1108 break;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00001109 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001110 *buf = xmlStrdup(xmlSchemaWildcardPCToString(
1111 ((xmlSchemaWildcardPtr) item)->processContents));
1112 *buf = xmlStrcat(*buf, BAD_CAST " wildcard");
1113 break;
1114 case XML_SCHEMA_FACET_MININCLUSIVE:
1115 case XML_SCHEMA_FACET_MINEXCLUSIVE:
1116 case XML_SCHEMA_FACET_MAXINCLUSIVE:
1117 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
1118 case XML_SCHEMA_FACET_TOTALDIGITS:
1119 case XML_SCHEMA_FACET_FRACTIONDIGITS:
1120 case XML_SCHEMA_FACET_PATTERN:
1121 case XML_SCHEMA_FACET_ENUMERATION:
1122 case XML_SCHEMA_FACET_WHITESPACE:
1123 case XML_SCHEMA_FACET_LENGTH:
1124 case XML_SCHEMA_FACET_MAXLENGTH:
1125 case XML_SCHEMA_FACET_MINLENGTH:
1126 *buf = xmlStrdup(BAD_CAST "facet '");
1127 *buf = xmlStrcat(*buf, xmlSchemaFacetTypeToString(item->type));
1128 *buf = xmlStrcat(*buf, BAD_CAST "'");
1129 break;
1130 case XML_SCHEMA_TYPE_NOTATION:
1131 *buf = xmlStrdup(BAD_CAST "notation");
1132 break;
1133 case XML_SCHEMA_TYPE_GROUP:
1134 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1135 *buf = xmlStrdup(xmlSchemaElemModelGrDef);
1136 *buf = xmlStrcat(*buf, BAD_CAST " '");
1137 *buf = xmlStrcat(*buf, item->name);
1138 *buf = xmlStrcat(*buf, BAD_CAST "'");
1139 } else {
1140 *buf = xmlStrdup(xmlSchemaElemModelGrRef);
1141 *buf = xmlStrcat(*buf, BAD_CAST " '");
1142 *buf = xmlStrcat(*buf, item->ref);
1143 *buf = xmlStrcat(*buf, BAD_CAST "'");
1144 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00001145 break;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001146 default:
William M. Brack2f2a6632004-08-20 23:09:47 +00001147 named = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001148 }
William M. Brack2f2a6632004-08-20 23:09:47 +00001149 } else
1150 named = 0;
1151
1152 if ((named == 0) && (itemNode != NULL)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00001153 xmlNodePtr elem;
1154
1155 if (itemNode->type == XML_ATTRIBUTE_NODE)
1156 elem = itemNode->parent;
1157 else
1158 elem = itemNode;
1159 *buf = xmlStrdup(BAD_CAST "Element '");
1160 if (parsing)
1161 *buf = xmlStrcat(*buf, elem->name);
1162 else
1163 *buf = xmlStrcat(*buf,
1164 xmlSchemaFormatNsPrefixLocal(&str, elem->ns, elem->name));
1165 *buf = xmlStrcat(*buf, BAD_CAST "'");
1166 }
1167 if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
1168 *buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
1169 *buf = xmlStrcat(*buf, xmlSchemaFormatNsPrefixLocal(&str,
1170 itemNode->ns, itemNode->name));
1171 *buf = xmlStrcat(*buf, BAD_CAST "'");
1172 }
1173 FREE_AND_NULL(str);
1174
1175 return (*buf);
1176}
1177
1178/**
1179 * xmlSchemaPFormatItemDes:
1180 * @buf: the string buffer
1181 * @item: the item as a schema object
1182 * @itemNode: the item as a node
1183 *
1184 * If the pointer to @buf is not NULL and @but holds no value,
1185 * the value is set to a item designation using
1186 * xmlSchemaFormatItemForReport. This one avoids adding
1187 * an attribute designation postfix.
1188 *
1189 * Returns a string of all enumeration elements.
1190 */
1191static void
1192xmlSchemaPRequestItemDes(xmlChar **buf,
1193 xmlSchemaTypePtr item,
1194 xmlNodePtr itemNode)
1195{
1196 if ((buf == 0) || (*buf != NULL))
1197 return;
1198 if (itemNode->type == XML_ATTRIBUTE_NODE)
1199 itemNode = itemNode->parent;
1200 xmlSchemaFormatItemForReport(buf, NULL, item, itemNode, 1);
1201}
1202
1203/**
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001204 * xmlSchemaGetCanonValueWhtsp:
1205 * @val: the precomputed value
1206 * @retValue: the returned value
1207 * @ws: the whitespace type of the value
1208 *
1209 * Get a the cononical representation of the value.
1210 * The caller has to free the returned retValue.
1211 *
1212 * Returns 0 if the value could be built and -1 in case of
1213 * API errors or if the value type is not supported yet.
1214 */
1215static int
1216xmlSchemaGetCanonValueWhtsp(const xmlChar *value,
1217 xmlSchemaValPtr val,
1218 xmlSchemaWhitespaceValueType ws,
1219 const xmlChar **retValue)
1220{
1221 xmlSchemaValType valType;
1222
1223 if ((retValue == NULL) || (value == NULL) || (val == NULL))
1224 return (-1);
1225 *retValue = NULL;
1226 valType = xmlSchemaGetValType(val);
1227 switch (valType) {
1228 case XML_SCHEMAS_STRING:
1229 if (value == NULL)
1230 *retValue = BAD_CAST xmlStrdup(BAD_CAST "");
1231 else
1232 *retValue =
1233 BAD_CAST xmlStrdup(value);
1234 break;
1235 case XML_SCHEMAS_NORMSTRING:
1236 if (value == NULL)
1237 *retValue = BAD_CAST xmlStrdup(BAD_CAST "");
1238 else {
1239 if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
1240 *retValue = xmlSchemaCollapseString(value);
1241 else
1242 *retValue = xmlSchemaWhiteSpaceReplace(value);
1243 if ((*retValue) == NULL)
1244 *retValue = BAD_CAST xmlStrdup(value);
1245 }
1246 break;
1247 default:
1248 return (xmlSchemaGetCanonValue(val, retValue));
1249 }
1250 return (0);
1251}
1252
1253/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00001254 * xmlSchemaFormatFacetEnumSet:
1255 * @buf: the string buffer
1256 * @type: the type holding the enumeration facets
1257 *
1258 * Builds a string consisting of all enumeration elements.
1259 *
1260 * Returns a string of all enumeration elements.
1261 */
1262static const xmlChar *
1263xmlSchemaFormatFacetEnumSet(xmlChar **buf, xmlSchemaTypePtr type)
1264{
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001265 xmlSchemaFacetPtr facet;
1266 xmlSchemaWhitespaceValueType ws;
1267 const xmlChar *value;
1268 int res;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001269
1270 if (*buf != NULL)
1271 xmlFree(*buf);
1272 *buf = NULL;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001273
1274 do {
1275 /*
1276 * Use the whitespace type of the base type.
1277 */
1278 if (type->type == XML_SCHEMA_TYPE_COMPLEX)
1279 /* TODO: Get rid of this case. */
1280 ws = (xmlSchemaWhitespaceValueType)
1281 xmlSchemaGetWhiteSpaceFacetValue(
1282 xmlSchemaGetSimpleContentType(type));
1283 else
1284 ws = (xmlSchemaWhitespaceValueType)
1285 xmlSchemaGetWhiteSpaceFacetValue(type->baseType);
1286 for (facet = type->facets; facet != NULL; facet = facet->next) {
1287 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
1288 continue;
1289 res = xmlSchemaGetCanonValueWhtsp(facet->value, facet->val,
1290 ws, &value);
1291 if (res == -1) {
1292 xmlSchemaVErr(NULL, NULL,
1293 XML_SCHEMAV_INTERNAL,
1294 "Internal error: xmlSchemaFormatFacetEnumSet, failed to "
1295 "compute the canonical lexical representation.\n",
1296 NULL, NULL);
1297 if (*buf != NULL)
1298 xmlFree(*buf);
1299 *buf = NULL;
1300 return (NULL);
1301 }
1302 if (*buf == NULL) {
1303 *buf = xmlStrdup(BAD_CAST "'");
1304 *buf = xmlStrcat(*buf, value);
1305 *buf = xmlStrcat(*buf, BAD_CAST "'");
1306 } else {
1307 *buf = xmlStrcat(*buf, BAD_CAST ", '");
1308 *buf = xmlStrcat(*buf, value);
1309 *buf = xmlStrcat(*buf, BAD_CAST "'");
1310 }
1311 }
1312 if (type->type == XML_SCHEMA_TYPE_COMPLEX)
1313 /* TODO: Get rid of this case. */
1314 type = xmlSchemaGetSimpleContentType(type);
1315 else
1316 type = type->baseType;
1317 } while ((type != NULL) && (type->type != XML_SCHEMA_TYPE_BASIC));
1318
1319#if 0
Daniel Veillardc0826a72004-08-10 14:17:33 +00001320 for (link = type->facetSet; link != NULL; link = link->next) {
1321 if (link->facet->type == XML_SCHEMA_FACET_ENUMERATION) {
1322 if (*buf == NULL) {
1323 *buf = xmlStrdup(BAD_CAST "'");
1324 *buf = xmlStrcat(*buf, link->facet->value);
1325 *buf = xmlStrcat(*buf, BAD_CAST "'");
1326 } else {
1327 *buf = xmlStrcat(*buf, BAD_CAST ", '");
1328 *buf = xmlStrcat(*buf, link->facet->value);
1329 *buf = xmlStrcat(*buf, BAD_CAST "'");
1330 }
1331 }
1332 }
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001333#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +00001334 return ((const xmlChar *) *buf);
1335}
1336
1337/**
1338 * xmlSchemaVFacetErr:
1339 * @ctxt: the schema validation context
1340 * @error: the error code
1341 * @node: the node to be validated
1342 * @value: the value of the node
1343 * @type: the type holding the facet
1344 * @facet: the facet
1345 * @message: the error message of NULL
1346 * @str1: extra data
1347 * @str2: extra data
1348 * @str3: extra data
1349 *
1350 * Reports a facet validation error.
1351 * TODO: Should this report the value of an element as well?
1352 */
1353static void
1354xmlSchemaVFacetErr(xmlSchemaValidCtxtPtr ctxt,
1355 xmlParserErrors error,
1356 xmlNodePtr node,
1357 const xmlChar *value,
1358 unsigned long length,
1359 xmlSchemaTypePtr type,
1360 xmlSchemaFacetPtr facet,
1361 const char *message,
1362 const xmlChar *str1,
1363 const xmlChar *str2,
1364 const xmlChar *str3)
1365{
1366 xmlChar *str = NULL, *msg = NULL;
1367 xmlSchemaTypeType facetType;
1368
1369 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
1370 msg = xmlStrcat(msg, BAD_CAST " [");
1371 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1372 msg = xmlStrcat(msg, BAD_CAST ", facet '");
1373 if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
1374 facetType = XML_SCHEMA_FACET_ENUMERATION;
1375 /*
1376 * If enumerations are validated, one must not expect the
1377 * facet to be given.
1378 */
1379 } else
1380 facetType = facet->type;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001381 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facetType));
Daniel Veillardc0826a72004-08-10 14:17:33 +00001382 msg = xmlStrcat(msg, BAD_CAST "']: ");
1383 if (message == NULL) {
1384 /*
1385 * Use a default message.
1386 */
1387 if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
1388 (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
1389 (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
1390
1391 char len[25], actLen[25];
1392
1393 /* FIXME, TODO: What is the max expected string length of the
1394 * this value?
1395 */
1396 if (node->type == XML_ATTRIBUTE_NODE)
1397 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
1398 else
1399 msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
1400
1401 snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
1402 snprintf(actLen, 24, "%lu", length);
1403
1404 if (facetType == XML_SCHEMA_FACET_LENGTH)
1405 msg = xmlStrcat(msg,
1406 BAD_CAST "this differs from the allowed length of '%s'.\n");
1407 else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
1408 msg = xmlStrcat(msg,
1409 BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
1410 else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
1411 msg = xmlStrcat(msg,
1412 BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
1413
1414 if (node->type == XML_ATTRIBUTE_NODE)
1415 xmlSchemaVErrExt(ctxt, node, error,
1416 (const char *) msg,
1417 value, (const xmlChar *) actLen, (const xmlChar *) len,
1418 NULL, NULL);
1419 else
1420 xmlSchemaVErr(ctxt, node, error,
1421 (const char *) msg,
1422 (const xmlChar *) actLen, (const xmlChar *) len);
1423
1424 } else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
1425 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
1426 "of the set {%s}.\n");
1427 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
1428 xmlSchemaFormatFacetEnumSet(&str, type));
1429 } else if (facetType == XML_SCHEMA_FACET_PATTERN) {
1430 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
1431 "by the pattern '%s'.\n");
1432 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
1433 facet->value);
Daniel Veillardcc5e2332005-03-16 21:55:35 +00001434 } else if (facetType == XML_SCHEMA_FACET_MININCLUSIVE) {
1435 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is less than the "
1436 "minimum value allowed ('%s').\n");
1437 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
1438 facet->value);
1439 } else if (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) {
1440 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is greater than the "
1441 "maximum value allowed ('%s').\n");
1442 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
1443 facet->value);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001444 } else if (node->type == XML_ATTRIBUTE_NODE) {
1445 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
1446 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value, NULL);
1447 } else {
1448 msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
1449 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
1450 }
1451 } else {
1452 msg = xmlStrcat(msg, (const xmlChar *) message);
1453 msg = xmlStrcat(msg, BAD_CAST ".\n");
1454 xmlSchemaVErr3(ctxt, node, error, (const char *) msg, str1, str2, str3);
1455 }
1456 FREE_AND_NULL(str)
1457 xmlFree(msg);
1458}
1459
1460/**
1461 * xmlSchemaVSimpleTypeErr:
1462 * @ctxt: the schema validation context
1463 * @error: the error code
1464 * @type: the type used for validation
1465 * @node: the node containing the validated value
1466 * @value: the validated value
1467 *
1468 * Reports a simple type validation error.
1469 * TODO: Should this report the value of an element as well?
1470 */
1471static void
1472xmlSchemaVSimpleTypeErr(xmlSchemaValidCtxtPtr ctxt,
1473 xmlParserErrors error,
1474 xmlNodePtr node,
1475 const xmlChar *value,
1476 xmlSchemaTypePtr type)
1477{
1478 xmlChar *str = NULL, *msg = NULL;
1479
1480 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
1481 msg = xmlStrcat(msg, BAD_CAST " [");
1482 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1483 if (node->type == XML_ATTRIBUTE_NODE) {
1484 msg = xmlStrcat(msg, BAD_CAST "]: The value '%s' is not valid.\n");
1485 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value, NULL);
1486 } else {
1487 msg = xmlStrcat(msg, BAD_CAST "]: The character content is not valid.\n");
1488 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
1489 }
1490 FREE_AND_NULL(str)
1491 xmlFree(msg);
1492}
1493
1494/**
William M. Brack2f2a6632004-08-20 23:09:47 +00001495 * xmlSchemaVComplexTypeErr:
1496 * @ctxt: the schema validation context
1497 * @error: the error code
1498 * @node: the node containing the validated value
1499 * @type: the complex type used for validation
1500 * @message: the error message
1501 *
1502 * Reports a complex type validation error.
1503 */
1504static void
1505xmlSchemaVComplexTypeErr(xmlSchemaValidCtxtPtr ctxt,
1506 xmlParserErrors error,
1507 xmlNodePtr node,
1508 xmlSchemaTypePtr type,
1509 const char *message)
1510{
1511 xmlChar *str = NULL, *msg = NULL;
1512
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00001513 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00001514 /* Specify the complex type only if it is global. */
1515 if ((type != NULL) && (type->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00001516 msg = xmlStrcat(msg, BAD_CAST " [");
1517 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1518 msg = xmlStrcat(msg, BAD_CAST "]");
1519 }
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001520 msg = xmlStrcat(msg, BAD_CAST ": %s.\n");
1521 xmlSchemaVErr(ctxt, node, error, (const char *) msg,
William M. Brack2f2a6632004-08-20 23:09:47 +00001522 (const xmlChar *) message, NULL);
1523 FREE_AND_NULL(str)
1524 xmlFree(msg);
1525}
1526
1527/**
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001528 * xmlSchemaVComplexTypeElemErr:
1529 * @ctxt: the schema validation context
1530 * @error: the error code
1531 * @node: the node containing the validated value
1532 * @type: the complex type used for validation
1533 * @message: the error message
1534 *
1535 * Reports a complex type validation error.
1536 */
1537static void
1538xmlSchemaVComplexTypeElemErr(xmlSchemaValidCtxtPtr ctxt,
1539 xmlParserErrors error,
1540 xmlNodePtr node,
1541 xmlSchemaTypePtr type,
1542 const char *message,
1543 int nbval,
1544 int nbneg,
1545 xmlChar **values)
1546{
1547 xmlChar *str = NULL, *msg = NULL;
1548 xmlChar *localName, *nsName;
1549 const xmlChar *cur, *end;
1550 int i;
1551
1552 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
1553 /* Specify the complex type only if it is global. */
1554 if ((type != NULL) && (type->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
1555 msg = xmlStrcat(msg, BAD_CAST " [");
1556 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1557 msg = xmlStrcat(msg, BAD_CAST "]");
1558 FREE_AND_NULL(str)
1559 }
1560 msg = xmlStrcat(msg, BAD_CAST ": ");
1561 msg = xmlStrcat(msg, (const xmlChar *) message);
1562 /*
1563 * Note that is does not make sense to report that we have a
1564 * wildcard here, since the wildcard might be unfolded into
1565 * multiple transitions.
1566 */
1567 if (nbval + nbneg > 0) {
1568 if (nbval + nbneg > 1) {
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00001569 str = xmlStrdup(BAD_CAST ". Expected is one of ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001570 } else
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00001571 str = xmlStrdup(BAD_CAST ". Expected is ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001572 nsName = NULL;
1573
1574 for (i = 0; i < nbval + nbneg; i++) {
1575 cur = values[i];
1576 /*
1577 * Get the local name.
1578 */
1579 localName = NULL;
1580
1581 end = cur;
1582 if (*end == '*') {
1583 localName = xmlStrdup(BAD_CAST "*");
1584 *end++;
1585 } else {
1586 while ((*end != 0) && (*end != '|'))
1587 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001588 localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001589 }
1590 if (*end != 0) {
1591 *end++;
1592 /*
1593 * Skip "*|*" if they come with negated expressions, since
1594 * they represent the same negated wildcard.
1595 */
1596 if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
1597 /*
1598 * Get the namespace name.
1599 */
1600 cur = end;
1601 if (*end == '*') {
1602 nsName = xmlStrdup(BAD_CAST "{*}");
1603 } else {
1604 while (*end != 0)
1605 end++;
1606
1607 if (i >= nbval)
1608 nsName = xmlStrdup(BAD_CAST "{##other:");
1609 else
1610 nsName = xmlStrdup(BAD_CAST "{");
1611
1612 nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
1613 nsName = xmlStrcat(nsName, BAD_CAST "}");
1614 }
1615 str = xmlStrcat(str, BAD_CAST nsName);
1616 FREE_AND_NULL(nsName)
1617 } else {
1618 FREE_AND_NULL(localName);
1619 continue;
1620 }
1621 }
1622 str = xmlStrcat(str, BAD_CAST localName);
1623 FREE_AND_NULL(localName);
1624
1625 if (i < nbval + nbneg -1)
1626 str = xmlStrcat(str, BAD_CAST ", ");
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00001627 }
1628 str = xmlStrcat(str, BAD_CAST " )");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001629 msg = xmlStrcat(msg, BAD_CAST str);
1630 FREE_AND_NULL(str)
1631 }
1632 msg = xmlStrcat(msg, BAD_CAST ".\n");
1633 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
1634 xmlFree(msg);
1635}
1636
1637/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00001638 * xmlSchemaPMissingAttrErr:
1639 * @ctxt: the schema validation context
1640 * @ownerDes: the designation of the owner
1641 * @ownerName: the name of the owner
1642 * @ownerItem: the owner as a schema object
1643 * @ownerElem: the owner as an element node
1644 * @node: the parent element node of the missing attribute node
1645 * @type: the corresponding type of the attribute node
1646 *
1647 * Reports an illegal attribute.
1648 */
1649static void
1650xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
1651 xmlParserErrors error,
1652 xmlChar **ownerDes,
1653 xmlSchemaTypePtr ownerItem,
1654 xmlNodePtr ownerElem,
1655 const char *name,
1656 const char *message)
1657{
1658 xmlChar *des = NULL;
1659
1660 if (ownerDes == NULL)
1661 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
1662 else if (*ownerDes == NULL) {
1663 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
1664 des = *ownerDes;
1665 } else
1666 des = *ownerDes;
1667 if (message != NULL)
1668 xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
1669 else
1670 xmlSchemaPErr(ctxt, ownerElem, error,
1671 "%s: The attribute '%s' is required but missing.\n",
1672 BAD_CAST des, BAD_CAST name);
1673 if (ownerDes == NULL)
1674 FREE_AND_NULL(des);
1675}
1676
William M. Brack2f2a6632004-08-20 23:09:47 +00001677/**
1678 * xmlSchemaCompTypeToString:
1679 * @type: the type of the schema item
1680 *
1681 * Returns the component name of a schema item.
1682 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001683static const char *
1684xmlSchemaCompTypeToString(xmlSchemaTypeType type)
1685{
1686 switch (type) {
1687 case XML_SCHEMA_TYPE_SIMPLE:
1688 return("simple type definition");
1689 case XML_SCHEMA_TYPE_COMPLEX:
1690 return("complex type definition");
1691 case XML_SCHEMA_TYPE_ELEMENT:
1692 return("element declaration");
1693 case XML_SCHEMA_TYPE_ATTRIBUTE:
1694 return("attribute declaration");
1695 case XML_SCHEMA_TYPE_GROUP:
1696 return("model group definition");
1697 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1698 return("attribute group definition");
1699 case XML_SCHEMA_TYPE_NOTATION:
1700 return("notation declaration");
1701 default:
1702 return("Not a schema component");
1703 }
1704}
1705/**
1706 * xmlSchemaPResCompAttrErr:
1707 * @ctxt: the schema validation context
1708 * @error: the error code
1709 * @ownerDes: the designation of the owner
1710 * @ownerItem: the owner as a schema object
1711 * @ownerElem: the owner as an element node
1712 * @name: the name of the attribute holding the QName
1713 * @refName: the referenced local name
1714 * @refURI: the referenced namespace URI
1715 * @message: optional message
1716 *
1717 * Used to report QName attribute values that failed to resolve
1718 * to schema components.
1719 */
1720static void
1721xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
1722 xmlParserErrors error,
1723 xmlChar **ownerDes,
1724 xmlSchemaTypePtr ownerItem,
1725 xmlNodePtr ownerElem,
1726 const char *name,
1727 const xmlChar *refName,
1728 const xmlChar *refURI,
1729 xmlSchemaTypeType refType,
1730 const char *refTypeStr)
1731{
1732 xmlChar *des = NULL, *strA = NULL;
1733
1734 if (ownerDes == NULL)
1735 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
1736 else if (*ownerDes == NULL) {
1737 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
1738 des = *ownerDes;
1739 } else
1740 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001741 if (refTypeStr == NULL)
1742 refTypeStr = xmlSchemaCompTypeToString(refType);
1743 xmlSchemaPErrExt(ctxt, ownerElem, error,
1744 NULL, NULL, NULL,
1745 "%s, attribute '%s': The QName value %s does not resolve to a(n) "
1746 "%s.\n", BAD_CAST des, BAD_CAST name,
1747 xmlSchemaFormatNsUriLocal(&strA, refURI, refName),
1748 BAD_CAST refTypeStr, NULL);
1749 if (ownerDes == NULL)
1750 FREE_AND_NULL(des)
1751 FREE_AND_NULL(strA)
1752}
1753
William M. Brack2f2a6632004-08-20 23:09:47 +00001754/**
1755 * xmlSchemaPCustomAttrErr:
1756 * @ctxt: the schema parser context
1757 * @error: the error code
1758 * @ownerDes: the designation of the owner
1759 * @ownerItem: the owner as a schema object
1760 * @attr: the illegal attribute node
1761 *
1762 * Reports an illegal attribute during the parse.
1763 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001764static void
1765xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00001766 xmlParserErrors error,
1767 xmlChar **ownerDes,
1768 xmlSchemaTypePtr ownerItem,
1769 xmlAttrPtr attr,
1770 const char *msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001771{
1772 xmlChar *des = NULL;
1773
1774 if (ownerDes == NULL)
1775 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
1776 else if (*ownerDes == NULL) {
1777 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
1778 des = *ownerDes;
1779 } else
1780 des = *ownerDes;
1781 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
1782 "%s, attribute '%s': %s.\n",
1783 BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
1784 if (ownerDes == NULL)
1785 FREE_AND_NULL(des);
1786}
1787
1788/**
1789 * xmlSchemaPIllegalAttrErr:
William M. Brack2f2a6632004-08-20 23:09:47 +00001790 * @ctxt: the schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00001791 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00001792 * @ownerDes: the designation of the attribute's owner
1793 * @ownerItem: the attribute's owner item
Daniel Veillardc0826a72004-08-10 14:17:33 +00001794 * @attr: the illegal attribute node
1795 *
William M. Brack2f2a6632004-08-20 23:09:47 +00001796 * Reports an illegal attribute during the parse.
Daniel Veillardc0826a72004-08-10 14:17:33 +00001797 */
1798static void
1799xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
1800 xmlParserErrors error,
1801 xmlChar **ownerDes,
1802 xmlSchemaTypePtr ownerItem,
1803 xmlAttrPtr attr)
1804{
1805 xmlChar *des = NULL, *strA = NULL;
1806
1807 if (ownerDes == NULL)
1808 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
1809 else if (*ownerDes == NULL) {
1810 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
1811 des = *ownerDes;
1812 } else
1813 des = *ownerDes;
1814 xmlSchemaPErr(ctxt, (xmlNodePtr) attr, error,
1815 "%s: The attribute '%s' is not allowed.\n", BAD_CAST des,
1816 xmlSchemaFormatNsPrefixLocal(&strA, attr->ns, attr->name));
1817 if (ownerDes == NULL)
1818 FREE_AND_NULL(des);
1819 FREE_AND_NULL(strA);
1820}
1821
William M. Brack2f2a6632004-08-20 23:09:47 +00001822/**
1823 * xmlSchemaPAquireDes:
1824 * @des: the first designation
1825 * @itemDes: the second designation
1826 * @item: the schema item
1827 * @itemElem: the node of the schema item
1828 *
1829 * Creates a designation for an item.
1830 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001831static void
1832xmlSchemaPAquireDes(xmlChar **des,
1833 xmlChar **itemDes,
1834 xmlSchemaTypePtr item,
1835 xmlNodePtr itemElem)
1836{
1837 if (itemDes == NULL)
1838 xmlSchemaFormatItemForReport(des, NULL, item, itemElem, 1);
1839 else if (*itemDes == NULL) {
1840 xmlSchemaFormatItemForReport(itemDes, NULL, item, itemElem, 1);
1841 *des = *itemDes;
1842 } else
1843 *des = *itemDes;
1844}
1845
William M. Brack2f2a6632004-08-20 23:09:47 +00001846/**
1847 * xmlSchemaPCustomErr:
1848 * @ctxt: the schema parser context
1849 * @error: the error code
1850 * @itemDes: the designation of the schema item
1851 * @item: the schema item
1852 * @itemElem: the node of the schema item
1853 * @message: the error message
1854 * @str1: an optional param for the error message
1855 * @str2: an optional param for the error message
1856 * @str3: an optional param for the error message
1857 *
1858 * Reports an error during parsing.
1859 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001860static void
1861xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
1862 xmlParserErrors error,
1863 xmlChar **itemDes,
1864 xmlSchemaTypePtr item,
1865 xmlNodePtr itemElem,
1866 const char *message,
1867 const xmlChar *str1,
1868 const xmlChar *str2,
1869 const xmlChar *str3)
1870{
1871 xmlChar *des = NULL, *msg = NULL;
1872
1873 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
1874 msg = xmlStrdup(BAD_CAST "%s: ");
1875 msg = xmlStrcat(msg, (const xmlChar *) message);
1876 msg = xmlStrcat(msg, BAD_CAST ".\n");
1877 if ((itemElem == NULL) && (item != NULL))
1878 itemElem = item->node;
1879 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
1880 (const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
1881 if (itemDes == NULL)
1882 FREE_AND_NULL(des);
1883 FREE_AND_NULL(msg);
1884}
1885
William M. Brack2f2a6632004-08-20 23:09:47 +00001886/**
1887 * xmlSchemaPCustomErr:
1888 * @ctxt: the schema parser context
1889 * @error: the error code
1890 * @itemDes: the designation of the schema item
1891 * @item: the schema item
1892 * @itemElem: the node of the schema item
1893 * @message: the error message
1894 * @str1: the optional param for the error message
1895 *
1896 * Reports an error during parsing.
1897 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001898static void
1899xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
1900 xmlParserErrors error,
1901 xmlChar **itemDes,
1902 xmlSchemaTypePtr item,
1903 xmlNodePtr itemElem,
1904 const char *message,
1905 const xmlChar *str1)
1906{
1907 xmlSchemaPCustomErrExt(ctxt, error, itemDes, item, itemElem, message,
1908 str1, NULL, NULL);
1909}
1910
William M. Brack2f2a6632004-08-20 23:09:47 +00001911/**
1912 * xmlSchemaPAttrUseErr:
1913 * @ctxt: the schema parser context
1914 * @error: the error code
1915 * @itemDes: the designation of the schema type
1916 * @item: the schema type
1917 * @itemElem: the node of the schema type
1918 * @attr: the invalid schema attribute
1919 * @message: the error message
1920 * @str1: the optional param for the error message
1921 *
1922 * Reports an attribute use error during parsing.
1923 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001924static void
1925xmlSchemaPAttrUseErr(xmlSchemaParserCtxtPtr ctxt,
1926 xmlParserErrors error,
1927 xmlChar **itemDes,
1928 xmlSchemaTypePtr item,
1929 xmlNodePtr itemElem,
1930 const xmlSchemaAttributePtr attr,
1931 const char *message,
1932 const xmlChar *str1)
1933{
1934 xmlChar *des = NULL, *strA = NULL, *msg = NULL;
1935
1936 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
1937 xmlSchemaFormatNsUriLocal(&strA, xmlSchemaGetAttrTargetNsURI(attr),
1938 xmlSchemaGetAttrName(attr));
1939 msg = xmlStrdup(BAD_CAST "%s, attr. use %s: ");
1940 msg = xmlStrcat(msg, (const xmlChar *) message);
1941 msg = xmlStrcat(msg, BAD_CAST ".\n");
1942 if ((itemElem == NULL) && (item != NULL))
1943 itemElem = item->node;
1944 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
1945 (const char *) msg, BAD_CAST des, BAD_CAST strA, str1, NULL, NULL);
1946 if (itemDes == NULL)
1947 FREE_AND_NULL(des);
1948 FREE_AND_NULL(strA);
1949 xmlFree(msg);
1950}
1951
William M. Brack2f2a6632004-08-20 23:09:47 +00001952/**
1953 * xmlSchemaPIllegalFacetAtomicErr:
1954 * @ctxt: the schema parser context
1955 * @error: the error code
1956 * @itemDes: the designation of the type
1957 * @item: the schema type
1958 * @baseItem: the base type of type
1959 * @facet: the illegal facet
1960 *
1961 * Reports an illegal facet for atomic simple types.
1962 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001963static void
1964xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
1965 xmlParserErrors error,
1966 xmlChar **itemDes,
1967 xmlSchemaTypePtr item,
1968 xmlSchemaTypePtr baseItem,
1969 xmlSchemaFacetPtr facet)
1970{
1971 xmlChar *des = NULL, *strT = NULL;
1972
1973 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
1974 xmlSchemaPErrExt(ctxt, item->node, error, NULL, NULL, NULL,
1975 "%s: The facet '%s' is not allowed on types derived from the "
1976 "type %s.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001977 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type),
Daniel Veillardc0826a72004-08-10 14:17:33 +00001978 xmlSchemaFormatItemForReport(&strT, NULL, baseItem, NULL, 1),
1979 NULL, NULL);
1980 if (itemDes == NULL)
1981 FREE_AND_NULL(des);
1982 FREE_AND_NULL(strT);
1983}
1984
William M. Brack2f2a6632004-08-20 23:09:47 +00001985/**
1986 * xmlSchemaPIllegalFacetListUnionErr:
1987 * @ctxt: the schema parser context
1988 * @error: the error code
1989 * @itemDes: the designation of the schema item involved
1990 * @item: the schema item involved
1991 * @facet: the illegal facet
1992 *
1993 * Reports an illegal facet for <list> and <union>.
1994 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001995static void
1996xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
1997 xmlParserErrors error,
1998 xmlChar **itemDes,
1999 xmlSchemaTypePtr item,
2000 xmlSchemaFacetPtr facet)
2001{
2002 xmlChar *des = NULL, *strT = NULL;
2003
2004 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
2005 xmlSchemaPErr(ctxt, item->node, error,
2006 "%s: The facet '%s' is not allowed.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00002007 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +00002008 if (itemDes == NULL)
2009 FREE_AND_NULL(des);
2010 FREE_AND_NULL(strT);
2011}
2012
2013/**
2014 * xmlSchemaPMutualExclAttrErr:
2015 * @ctxt: the schema validation context
2016 * @error: the error code
2017 * @elemDes: the designation of the parent element node
2018 * @attr: the bad attribute node
2019 * @type: the corresponding type of the attribute node
2020 *
2021 * Reports an illegal attribute.
2022 */
2023static void
2024xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
2025 xmlParserErrors error,
2026 xmlChar **ownerDes,
2027 xmlSchemaTypePtr ownerItem,
2028 xmlAttrPtr attr,
2029 const char *name1,
2030 const char *name2)
2031{
2032 xmlChar *des = NULL;
2033
2034 if (ownerDes == NULL)
2035 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
2036 else if (*ownerDes == NULL) {
2037 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
2038 des = *ownerDes;
2039 } else
2040 des = *ownerDes;
2041 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
2042 "%s: The attributes '%s' and '%s' are mutually exclusive.\n",
2043 BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
2044 if (ownerDes == NULL)
2045 FREE_AND_NULL(des)
2046}
2047
2048/**
2049 * xmlSchemaPSimpleTypeErr:
2050 * @ctxt: the schema validation context
2051 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00002052 * @type: the type specifier
Daniel Veillardc0826a72004-08-10 14:17:33 +00002053 * @ownerDes: the designation of the owner
2054 * @ownerItem: the schema object if existent
2055 * @node: the validated node
2056 * @value: the validated value
2057 *
2058 * Reports a simple type validation error.
2059 * TODO: Should this report the value of an element as well?
2060 */
2061static void
2062xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
2063 xmlParserErrors error,
2064 xmlChar **ownerDes,
2065 xmlSchemaTypePtr ownerItem,
2066 xmlNodePtr node,
William M. Brack2f2a6632004-08-20 23:09:47 +00002067 xmlSchemaTypePtr type,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002068 const char *typeDes,
2069 const xmlChar *value,
2070 const char *message,
2071 const xmlChar *str1,
2072 const xmlChar *str2)
2073{
William M. Brack2f2a6632004-08-20 23:09:47 +00002074 xmlChar *des = NULL, *strA = NULL, *strT = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002075
2076 if (ownerDes == NULL)
2077 xmlSchemaPRequestItemDes(&des, ownerItem, node);
2078 else if (*ownerDes == NULL) {
2079 xmlSchemaPRequestItemDes(ownerDes, ownerItem, node);
2080 des = *ownerDes;
2081 } else
2082 des = *ownerDes;
William M. Brack2f2a6632004-08-20 23:09:47 +00002083 if (type != NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002084 typeDes = (const char *) xmlSchemaFormatItemForReport(&strT, NULL, type, NULL, 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002085 if (message == NULL) {
2086 /*
2087 * Use default messages.
2088 */
2089 if (node->type == XML_ATTRIBUTE_NODE) {
2090 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
2091 "%s, attribute '%s' [%s]: The value '%s' is not "
2092 "valid.\n",
2093 BAD_CAST des, xmlSchemaFormatNsPrefixLocal(&strA, node->ns,
2094 node->name), BAD_CAST typeDes, value, NULL);
2095 } else {
2096 xmlSchemaPErr(ctxt, node, error,
2097 "%s [%s]: The character content is not valid.\n",
2098 BAD_CAST des, BAD_CAST typeDes);
2099 }
2100 } else {
2101 xmlChar *msg;
2102
2103 msg = xmlStrdup(BAD_CAST "%s");
2104 if (node->type == XML_ATTRIBUTE_NODE)
2105 msg = xmlStrcat(msg, BAD_CAST ", attribute '%s'");
2106 msg = xmlStrcat(msg, BAD_CAST " [%s]: ");
2107 msg = xmlStrcat(msg, (const xmlChar *) message);
2108 msg = xmlStrcat(msg, BAD_CAST ".\n");
2109 if (node->type == XML_ATTRIBUTE_NODE) {
2110 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
2111 (const char *) msg,
2112 BAD_CAST des, xmlSchemaFormatNsPrefixLocal(&strA,
2113 node->ns, node->name), BAD_CAST typeDes, str1, str2);
2114 } else {
2115 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
2116 (const char *) msg,
2117 BAD_CAST des, BAD_CAST typeDes, str1, str2, NULL);
2118 }
2119 xmlFree(msg);
2120 }
2121 /* Cleanup. */
2122 FREE_AND_NULL(strA)
2123 FREE_AND_NULL(strT)
2124 if (ownerDes == NULL)
2125 FREE_AND_NULL(des)
2126}
2127
William M. Brack2f2a6632004-08-20 23:09:47 +00002128/**
2129 * xmlSchemaPContentErr:
2130 * @ctxt: the schema parser context
2131 * @error: the error code
2132 * @onwerDes: the designation of the holder of the content
2133 * @ownerItem: the owner item of the holder of the content
2134 * @ownerElem: the node of the holder of the content
2135 * @child: the invalid child node
2136 * @message: the optional error message
2137 * @content: the optional string describing the correct content
2138 *
2139 * Reports an error concerning the content of a schema element.
2140 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002141static void
2142xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
2143 xmlParserErrors error,
2144 xmlChar **ownerDes,
2145 xmlSchemaTypePtr ownerItem,
2146 xmlNodePtr ownerElem,
2147 xmlNodePtr child,
2148 const char *message,
2149 const char *content)
2150{
2151 xmlChar *des = NULL;
2152
2153 if (ownerDes == NULL)
2154 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
2155 else if (*ownerDes == NULL) {
2156 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
2157 des = *ownerDes;
2158 } else
2159 des = *ownerDes;
2160 if (message != NULL)
2161 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2162 "%s: %s.\n",
2163 BAD_CAST des, BAD_CAST message);
2164 else {
2165 if (content != NULL) {
2166 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2167 "%s: The content is not valid. Expected is %s.\n",
2168 BAD_CAST des, BAD_CAST content);
2169 } else {
2170 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2171 "%s: The content is not valid.\n",
2172 BAD_CAST des, NULL);
2173 }
2174 }
2175 if (ownerDes == NULL)
2176 FREE_AND_NULL(des)
2177}
2178
2179/**
2180 * xmlSchemaVIllegalAttrErr:
2181 * @ctxt: the schema validation context
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002182 * @error: the error code
Daniel Veillardc0826a72004-08-10 14:17:33 +00002183 * @attr: the illegal attribute node
2184 *
2185 * Reports an illegal attribute.
2186 */
2187static void
2188xmlSchemaVIllegalAttrErr(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002189 xmlParserErrors error,
William M. Brack2f2a6632004-08-20 23:09:47 +00002190 xmlAttrPtr attr)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002191{
2192 xmlChar *strE = NULL, *strA = NULL;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002193
2194 xmlSchemaVErr(ctxt, (xmlNodePtr) attr,
2195 error,
2196 /* XML_SCHEMAS_ERR_ATTRUNKNOWN, */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002197 "%s: The attribute '%s' is not allowed.\n",
2198 xmlSchemaFormatItemForReport(&strE, NULL, NULL, attr->parent, 0),
2199 xmlSchemaFormatNsPrefixLocal(&strA, attr->ns, attr->name));
2200 FREE_AND_NULL(strE)
2201 FREE_AND_NULL(strA)
2202}
2203
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002204
2205static int
2206xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
2207{
2208 switch (item->type) {
2209 case XML_SCHEMA_TYPE_COMPLEX:
2210 case XML_SCHEMA_TYPE_SIMPLE:
2211 case XML_SCHEMA_TYPE_GROUP:
2212 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
2213 return(1);
2214 break;
2215 case XML_SCHEMA_TYPE_ELEMENT:
2216 if ( ((xmlSchemaElementPtr) item)->flags &
2217 XML_SCHEMAS_ELEM_GLOBAL)
2218 return(1);
2219 break;
2220 case XML_SCHEMA_TYPE_ATTRIBUTE:
2221 if ( ((xmlSchemaAttributePtr) item)->flags &
2222 XML_SCHEMAS_ATTR_GLOBAL)
2223 return(1);
2224 break;
2225 /* Note that attribute groups are always global. */
2226 default:
2227 return(1);
2228 }
2229 return (0);
2230}
2231
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002232
2233static void
2234xmlSchemaStreamVCustomErr(xmlSchemaValidCtxtPtr vctxt,
2235 xmlParserErrors error,
2236 xmlSchemaNodeInfoPtr nodeInfo,
2237 xmlSchemaTypePtr type,
2238 const char *message,
2239 const xmlChar *str1,
2240 const xmlChar *str2)
2241{
2242 xmlChar *msg = NULL, *str = NULL;
2243
2244 msg = xmlStrdup(BAD_CAST "Element '");
2245
2246 if (vctxt->elemInfos[vctxt->depth] != nodeInfo) {
2247 xmlSchemaNodeInfoPtr elemInfo;
2248 /*
2249 * The node info is an attribute info.
2250 */
2251 elemInfo = vctxt->elemInfos[vctxt->depth];
2252 msg = xmlStrcat(msg, xmlSchemaFormatQName(&str,
2253 elemInfo->namespaceName, elemInfo->localName));
2254 msg = xmlStrcat(msg, BAD_CAST "', ");
2255 msg = xmlStrcat(msg, BAD_CAST "attribute '");
2256 }
2257 msg = xmlStrcat(msg, xmlSchemaFormatQName(&str,
2258 nodeInfo->namespaceName, nodeInfo->localName));
2259 msg = xmlStrcat(msg, BAD_CAST "'");
2260
2261 if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
2262 msg = xmlStrcat(msg, BAD_CAST " [");
2263 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str,
2264 NULL, type, NULL, 0));
2265 msg = xmlStrcat(msg, BAD_CAST "]");
2266 }
2267 msg = xmlStrcat(msg, BAD_CAST ": ");
2268
2269 msg = xmlStrcat(msg, (const xmlChar *) message);
2270 msg = xmlStrcat(msg, BAD_CAST ".\n");
2271 xmlSchemaVErr(vctxt, nodeInfo->node, error, (const char *) msg,
2272 str1, str2);
2273 FREE_AND_NULL(msg)
2274 FREE_AND_NULL(str)
2275}
2276
William M. Brack2f2a6632004-08-20 23:09:47 +00002277/**
2278 * xmlSchemaVCustomErr:
2279 * @ctxt: the schema validation context
2280 * @error: the error code
2281 * @node: the validated node
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002282 * @type: the schema type of the validated node
William M. Brack2f2a6632004-08-20 23:09:47 +00002283 * @message: the error message
2284 * @str1: the optional param for the message
2285 *
2286 * Reports a validation error.
2287 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002288static void
2289xmlSchemaVCustomErr(xmlSchemaValidCtxtPtr ctxt,
2290 xmlParserErrors error,
2291 xmlNodePtr node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002292 xmlSchemaTypePtr type,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002293 const char *message,
2294 const xmlChar *str1)
2295{
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002296 xmlChar *msg = NULL, *str = NULL;
2297
2298 if (node == NULL) {
2299 xmlSchemaVErr(ctxt, NULL,
2300 XML_SCHEMAV_INTERNAL,
2301 "Internal error: xmlSchemaVCustomErr, no node "
2302 "given.\n", NULL, NULL);
2303 return;
2304 }
2305 /* TODO: Are the HTML and DOCB doc nodes expected here? */
2306 if (node->type != XML_DOCUMENT_NODE) {
2307 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002308 if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002309 msg = xmlStrcat(msg, BAD_CAST " [");
2310 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
2311 msg = xmlStrcat(msg, BAD_CAST "]");
2312 }
2313 msg = xmlStrcat(msg, BAD_CAST ": ");
2314 } else
2315 msg = xmlStrdup((const xmlChar *) "");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002316 msg = xmlStrcat(msg, (const xmlChar *) message);
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002317 msg = xmlStrcat(msg, BAD_CAST ".\n");
2318 xmlSchemaVErr(ctxt, node, error, (const char *) msg, str1, NULL);
2319 FREE_AND_NULL(msg)
2320 FREE_AND_NULL(str)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002321}
2322
William M. Brack2f2a6632004-08-20 23:09:47 +00002323/**
William M. Brack2f2a6632004-08-20 23:09:47 +00002324 * xmlSchemaVWildcardErr:
2325 * @ctxt: the schema validation context
2326 * @error: the error code
2327 * @node: the validated node
2328 * @wild: the wildcard used
2329 * @message: the error message
2330 *
2331 * Reports an validation-by-wildcard error.
2332 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002333static void
2334xmlSchemaVWildcardErr(xmlSchemaValidCtxtPtr ctxt,
2335 xmlParserErrors error,
2336 xmlNodePtr node,
2337 xmlSchemaWildcardPtr wild,
2338 const char *message)
2339{
2340 xmlChar *des = NULL, *msg = NULL;
2341
2342 xmlSchemaFormatItemForReport(&des, NULL, NULL, node, 0);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00002343 msg = xmlStrdup(BAD_CAST "%s [");
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00002344 msg = xmlStrcat(msg, xmlSchemaWildcardPCToString(wild->processContents));
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002345 msg = xmlStrcat(msg, BAD_CAST " wildcard]: ");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002346 msg = xmlStrcat(msg, (const xmlChar *) message);
2347 msg = xmlStrcat(msg, BAD_CAST ".\n");
2348 xmlSchemaVErr(ctxt, node, error, (const char *) msg, BAD_CAST des, NULL);
2349 FREE_AND_NULL(des);
2350 FREE_AND_NULL(msg);
2351}
2352
2353/**
2354 * xmlSchemaVMissingAttrErr:
2355 * @ctxt: the schema validation context
2356 * @node: the parent element node of the missing attribute node
2357 * @type: the corresponding type of the attribute node
2358 *
2359 * Reports an illegal attribute.
2360 */
2361static void
2362xmlSchemaVMissingAttrErr(xmlSchemaValidCtxtPtr ctxt,
2363 xmlNodePtr elem,
2364 xmlSchemaAttributePtr type)
2365{
2366 const xmlChar *name, *uri;
2367 xmlChar *strE = NULL, *strA = NULL;
2368
2369 if (type->ref != NULL) {
2370 name = type->ref;
2371 uri = type->refNs;
2372 } else {
2373 name = type->name;
2374 uri = type->targetNamespace;
2375 }
2376 xmlSchemaVErr(ctxt, elem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002377 XML_SCHEMAV_CVC_COMPLEX_TYPE_4,
2378 /* XML_SCHEMAS_ERR_MISSING, */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002379 "%s: The attribute %s is required but missing.\n",
2380 xmlSchemaFormatItemForReport(&strE, NULL, NULL, elem, 0),
2381 xmlSchemaFormatNsUriLocal(&strA, uri, name));
2382 FREE_AND_NULL(strE)
2383 FREE_AND_NULL(strA)
2384}
2385
Daniel Veillard4255d502002-04-16 15:50:10 +00002386/************************************************************************
2387 * *
2388 * Allocation functions *
2389 * *
2390 ************************************************************************/
2391
2392/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002393 * xmlSchemaNewSchemaForParserCtxt:
William M. Brack08171912003-12-29 02:52:11 +00002394 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00002395 *
2396 * Allocate a new Schema structure.
2397 *
2398 * Returns the newly allocated structure or NULL in case or error
2399 */
2400static xmlSchemaPtr
2401xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
2402{
2403 xmlSchemaPtr ret;
2404
2405 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
2406 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002407 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002408 return (NULL);
2409 }
2410 memset(ret, 0, sizeof(xmlSchema));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002411 ret->dict = ctxt->dict;
Daniel Veillard500a1de2004-03-22 15:22:58 +00002412 xmlDictReference(ret->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00002413
2414 return (ret);
2415}
2416
2417/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002418 * xmlSchemaNewSchema:
2419 * @ctxt: a schema validation context
2420 *
2421 * Allocate a new Schema structure.
2422 *
2423 * Returns the newly allocated structure or NULL in case or error
2424 */
2425static xmlSchemaAssemblePtr
2426xmlSchemaNewAssemble(void)
2427{
2428 xmlSchemaAssemblePtr ret;
2429
2430 ret = (xmlSchemaAssemblePtr) xmlMalloc(sizeof(xmlSchemaAssemble));
2431 if (ret == NULL) {
2432 /* xmlSchemaPErrMemory(ctxt, "allocating assemble info", NULL); */
2433 return (NULL);
2434 }
2435 memset(ret, 0, sizeof(xmlSchemaAssemble));
2436 ret->items = NULL;
2437 return (ret);
2438}
2439
2440/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002441 * xmlSchemaNewFacet:
Daniel Veillard4255d502002-04-16 15:50:10 +00002442 *
2443 * Allocate a new Facet structure.
2444 *
2445 * Returns the newly allocated structure or NULL in case or error
2446 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00002447xmlSchemaFacetPtr
2448xmlSchemaNewFacet(void)
Daniel Veillard4255d502002-04-16 15:50:10 +00002449{
2450 xmlSchemaFacetPtr ret;
2451
2452 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
2453 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002454 return (NULL);
2455 }
2456 memset(ret, 0, sizeof(xmlSchemaFacet));
2457
2458 return (ret);
2459}
2460
2461/**
2462 * xmlSchemaNewAnnot:
William M. Brack08171912003-12-29 02:52:11 +00002463 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00002464 * @node: a node
2465 *
2466 * Allocate a new annotation structure.
2467 *
2468 * Returns the newly allocated structure or NULL in case or error
2469 */
2470static xmlSchemaAnnotPtr
2471xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
2472{
2473 xmlSchemaAnnotPtr ret;
2474
2475 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
2476 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002477 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
Daniel Veillard4255d502002-04-16 15:50:10 +00002478 return (NULL);
2479 }
2480 memset(ret, 0, sizeof(xmlSchemaAnnot));
2481 ret->content = node;
2482 return (ret);
2483}
2484
2485/**
Daniel Veillardfdc91562002-07-01 21:52:03 +00002486 * xmlSchemaFreeAnnot:
2487 * @annot: a schema type structure
2488 *
2489 * Deallocate a annotation structure
2490 */
2491static void
2492xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
2493{
2494 if (annot == NULL)
2495 return;
2496 xmlFree(annot);
2497}
2498
2499/**
Daniel Veillard1d913862003-11-21 00:28:39 +00002500 * xmlSchemaFreeImport:
2501 * @import: a schema import structure
2502 *
2503 * Deallocate an import structure
2504 */
2505static void
2506xmlSchemaFreeImport(xmlSchemaImportPtr import)
2507{
2508 if (import == NULL)
2509 return;
2510
2511 xmlSchemaFree(import->schema);
William M. Brack2f2a6632004-08-20 23:09:47 +00002512 xmlFreeDoc(import->doc);
Daniel Veillard1d913862003-11-21 00:28:39 +00002513 xmlFree(import);
2514}
2515
2516/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002517 * xmlSchemaFreeInclude:
2518 * @include: a schema include structure
2519 *
2520 * Deallocate an include structure
2521 */
2522static void
2523xmlSchemaFreeInclude(xmlSchemaIncludePtr include)
2524{
2525 if (include == NULL)
2526 return;
2527
2528 xmlFreeDoc(include->doc);
2529 xmlFree(include);
2530}
2531
2532/**
2533 * xmlSchemaFreeIncludeList:
2534 * @includes: a schema include list
2535 *
2536 * Deallocate an include structure
2537 */
2538static void
2539xmlSchemaFreeIncludeList(xmlSchemaIncludePtr includes)
2540{
2541 xmlSchemaIncludePtr next;
2542
2543 while (includes != NULL) {
2544 next = includes->next;
2545 xmlSchemaFreeInclude(includes);
2546 includes = next;
2547 }
2548}
2549
2550/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002551 * xmlSchemaFreeNotation:
2552 * @schema: a schema notation structure
2553 *
2554 * Deallocate a Schema Notation structure.
2555 */
2556static void
2557xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
2558{
2559 if (nota == NULL)
2560 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002561 xmlFree(nota);
2562}
2563
2564/**
2565 * xmlSchemaFreeAttribute:
2566 * @schema: a schema attribute structure
2567 *
2568 * Deallocate a Schema Attribute structure.
2569 */
2570static void
2571xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
2572{
2573 if (attr == NULL)
2574 return;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002575 if (attr->annot != NULL)
2576 xmlSchemaFreeAnnot(attr->annot);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002577 if (attr->defVal != NULL)
2578 xmlSchemaFreeValue(attr->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00002579 xmlFree(attr);
2580}
2581
2582/**
Daniel Veillard3646d642004-06-02 19:19:14 +00002583 * xmlSchemaFreeWildcardNsSet:
2584 * set: a schema wildcard namespace
2585 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00002586 * Deallocates a list of wildcard constraint structures.
Daniel Veillard3646d642004-06-02 19:19:14 +00002587 */
2588static void
2589xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
2590{
2591 xmlSchemaWildcardNsPtr next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002592
Daniel Veillard3646d642004-06-02 19:19:14 +00002593 while (set != NULL) {
2594 next = set->next;
2595 xmlFree(set);
2596 set = next;
2597 }
2598}
2599
2600/**
2601 * xmlSchemaFreeWildcard:
Daniel Veillard01fa6152004-06-29 17:04:39 +00002602 * @wildcard: a wildcard structure
Daniel Veillard3646d642004-06-02 19:19:14 +00002603 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00002604 * Deallocates a wildcard structure.
Daniel Veillard3646d642004-06-02 19:19:14 +00002605 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00002606void
Daniel Veillard3646d642004-06-02 19:19:14 +00002607xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
2608{
2609 if (wildcard == NULL)
2610 return;
2611 if (wildcard->annot != NULL)
2612 xmlSchemaFreeAnnot(wildcard->annot);
2613 if (wildcard->nsSet != NULL)
2614 xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
2615 if (wildcard->negNsSet != NULL)
2616 xmlFree(wildcard->negNsSet);
2617 xmlFree(wildcard);
2618}
2619
2620/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002621 * xmlSchemaFreeAttributeGroup:
2622 * @schema: a schema attribute group structure
2623 *
2624 * Deallocate a Schema Attribute Group structure.
2625 */
2626static void
2627xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attr)
2628{
2629 if (attr == NULL)
2630 return;
Daniel Veillard3646d642004-06-02 19:19:14 +00002631 if (attr->annot != NULL)
2632 xmlSchemaFreeAnnot(attr->annot);
2633 if ((attr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) &&
2634 (attr->attributeWildcard != NULL))
2635 xmlSchemaFreeWildcard(attr->attributeWildcard);
2636
Daniel Veillard4255d502002-04-16 15:50:10 +00002637 xmlFree(attr);
2638}
2639
2640/**
Daniel Veillard3646d642004-06-02 19:19:14 +00002641 * xmlSchemaFreeAttributeUseList:
Daniel Veillard01fa6152004-06-29 17:04:39 +00002642 * @attrUse: an attribute link
Daniel Veillard3646d642004-06-02 19:19:14 +00002643 *
2644 * Deallocate a list of schema attribute uses.
2645 */
2646static void
2647xmlSchemaFreeAttributeUseList(xmlSchemaAttributeLinkPtr attrUse)
2648{
2649 xmlSchemaAttributeLinkPtr next;
2650
2651 while (attrUse != NULL) {
2652 next = attrUse->next;
2653 xmlFree(attrUse);
2654 attrUse = next;
2655 }
2656}
2657
2658/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00002659 * xmlSchemaFreeTypeLinkList:
2660 * @alink: a type link
2661 *
2662 * Deallocate a list of types.
2663 */
2664static void
2665xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
2666{
2667 xmlSchemaTypeLinkPtr next;
2668
2669 while (link != NULL) {
2670 next = link->next;
2671 xmlFree(link);
2672 link = next;
2673 }
2674}
2675
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00002676#ifdef IDC_ENABLED
2677static void
2678xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
2679{
2680 xmlSchemaIDCStateObjPtr next;
2681 while (sto != NULL) {
2682 next = sto->next;
2683 if (sto->history != NULL)
2684 xmlFree(sto->history);
2685 if (sto->xpathCtxt != NULL)
2686 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
2687 xmlFree(sto);
2688 sto = next;
2689 }
2690}
2691
2692/**
2693 * xmlSchemaFreeIDC:
2694 * @idc: a identity-constraint definition
2695 *
2696 * Deallocates an identity-constraint definition.
2697 */
2698static void
2699xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)
2700{
2701 xmlSchemaIDCSelectPtr cur, prev;
2702
2703 if (idcDef == NULL)
2704 return;
2705 if (idcDef->annot != NULL)
2706 xmlSchemaFreeAnnot(idcDef->annot);
2707 if (idcDef->ref != NULL)
2708 xmlFree(idcDef->ref);
2709 /* Selector */
2710 if (idcDef->selector != NULL) {
2711 if (idcDef->selector->xpathComp != NULL)
2712 xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp);
2713 xmlFree(idcDef->selector);
2714 }
2715 /* Fields */
2716 if (idcDef->fields != NULL) {
2717 cur = idcDef->fields;
2718 do {
2719 prev = cur;
2720 cur = cur->next;
2721 if (prev->xpathComp != NULL)
2722 xmlFreePattern((xmlPatternPtr) prev->xpathComp);
2723 xmlFree(prev);
2724 } while (cur != NULL);
2725 }
2726 xmlFree(idcDef);
2727}
2728#endif /* IDC_ENABLED */
2729
Daniel Veillard01fa6152004-06-29 17:04:39 +00002730/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002731 * xmlSchemaFreeElement:
2732 * @schema: a schema element structure
2733 *
2734 * Deallocate a Schema Element structure.
2735 */
2736static void
2737xmlSchemaFreeElement(xmlSchemaElementPtr elem)
2738{
2739 if (elem == NULL)
2740 return;
Daniel Veillard32370232002-10-16 14:08:14 +00002741 if (elem->annot != NULL)
2742 xmlSchemaFreeAnnot(elem->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00002743 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002744 xmlRegFreeRegexp(elem->contModel);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002745 if (elem->defVal != NULL)
2746 xmlSchemaFreeValue(elem->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00002747 xmlFree(elem);
2748}
2749
2750/**
2751 * xmlSchemaFreeFacet:
2752 * @facet: a schema facet structure
2753 *
2754 * Deallocate a Schema Facet structure.
2755 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00002756void
Daniel Veillard4255d502002-04-16 15:50:10 +00002757xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
2758{
2759 if (facet == NULL)
2760 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002761 if (facet->val != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002762 xmlSchemaFreeValue(facet->val);
Daniel Veillard4255d502002-04-16 15:50:10 +00002763 if (facet->regexp != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002764 xmlRegFreeRegexp(facet->regexp);
Daniel Veillardfdc91562002-07-01 21:52:03 +00002765 if (facet->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002766 xmlSchemaFreeAnnot(facet->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00002767 xmlFree(facet);
2768}
2769
2770/**
2771 * xmlSchemaFreeType:
2772 * @type: a schema type structure
2773 *
2774 * Deallocate a Schema Type structure.
2775 */
2776void
2777xmlSchemaFreeType(xmlSchemaTypePtr type)
2778{
2779 if (type == NULL)
2780 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002781 if (type->annot != NULL)
Daniel Veillard32370232002-10-16 14:08:14 +00002782 xmlSchemaFreeAnnot(type->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00002783 if (type->facets != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002784 xmlSchemaFacetPtr facet, next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002785
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002786 facet = type->facets;
2787 while (facet != NULL) {
2788 next = facet->next;
2789 xmlSchemaFreeFacet(facet);
2790 facet = next;
2791 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002792 }
Daniel Veillard3646d642004-06-02 19:19:14 +00002793 if (type->type != XML_SCHEMA_TYPE_BASIC) {
2794 if (type->attributeUses != NULL)
2795 xmlSchemaFreeAttributeUseList(type->attributeUses);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002796 if ((type->attributeWildcard != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +00002797 ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002798 (type->flags & XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD))) {
2799 /*
2800 * NOTE: The only case where an attribute wildcard
2801 * is not owned, is if a complex type inherits it
2802 * from a base type.
2803 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002804 xmlSchemaFreeWildcard(type->attributeWildcard);
2805 }
2806 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00002807 if (type->memberTypes != NULL)
2808 xmlSchemaFreeTypeLinkList(type->memberTypes);
2809 if (type->facetSet != NULL) {
2810 xmlSchemaFacetLinkPtr next, link;
2811
2812 link = type->facetSet;
2813 do {
2814 next = link->next;
2815 xmlFree(link);
2816 link = next;
2817 } while (link != NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002818 }
2819 if (type->contModel != NULL)
2820 xmlRegFreeRegexp(type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00002821 xmlFree(type);
2822}
2823
2824/**
Daniel Veillardb0f397e2003-12-23 23:30:53 +00002825 * xmlSchemaFreeTypeList:
2826 * @type: a schema type structure
2827 *
2828 * Deallocate a Schema Type structure.
2829 */
2830static void
2831xmlSchemaFreeTypeList(xmlSchemaTypePtr type)
2832{
2833 xmlSchemaTypePtr next;
2834
2835 while (type != NULL) {
2836 next = type->redef;
2837 xmlSchemaFreeType(type);
2838 type = next;
2839 }
2840}
2841
2842/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002843 * xmlSchemaFree:
2844 * @schema: a schema structure
2845 *
2846 * Deallocate a Schema structure.
2847 */
2848void
2849xmlSchemaFree(xmlSchemaPtr schema)
2850{
2851 if (schema == NULL)
2852 return;
2853
Daniel Veillard4255d502002-04-16 15:50:10 +00002854 if (schema->notaDecl != NULL)
2855 xmlHashFree(schema->notaDecl,
2856 (xmlHashDeallocator) xmlSchemaFreeNotation);
2857 if (schema->attrDecl != NULL)
2858 xmlHashFree(schema->attrDecl,
2859 (xmlHashDeallocator) xmlSchemaFreeAttribute);
2860 if (schema->attrgrpDecl != NULL)
2861 xmlHashFree(schema->attrgrpDecl,
2862 (xmlHashDeallocator) xmlSchemaFreeAttributeGroup);
2863 if (schema->elemDecl != NULL)
2864 xmlHashFree(schema->elemDecl,
2865 (xmlHashDeallocator) xmlSchemaFreeElement);
2866 if (schema->typeDecl != NULL)
2867 xmlHashFree(schema->typeDecl,
Daniel Veillardb0f397e2003-12-23 23:30:53 +00002868 (xmlHashDeallocator) xmlSchemaFreeTypeList);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00002869 if (schema->groupDecl != NULL)
2870 xmlHashFree(schema->groupDecl,
2871 (xmlHashDeallocator) xmlSchemaFreeType);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00002872#ifdef IDC_ENABLED
2873 if (schema->idcDef != NULL)
2874 xmlHashFree(schema->idcDef,
2875 (xmlHashDeallocator) xmlSchemaFreeIDC);
2876#endif
Daniel Veillard1d913862003-11-21 00:28:39 +00002877 if (schema->schemasImports != NULL)
2878 xmlHashFree(schema->schemasImports,
2879 (xmlHashDeallocator) xmlSchemaFreeImport);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002880 if (schema->includes != NULL) {
2881 xmlSchemaFreeIncludeList((xmlSchemaIncludePtr) schema->includes);
2882 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002883 if (schema->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002884 xmlSchemaFreeAnnot(schema->annot);
Daniel Veillarddda22c12004-01-24 08:31:30 +00002885 if (schema->doc != NULL && !schema->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002886 xmlFreeDoc(schema->doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002887 xmlDictFree(schema->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00002888 xmlFree(schema);
2889}
2890
2891/************************************************************************
2892 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00002893 * Debug functions *
2894 * *
2895 ************************************************************************/
2896
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002897#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002898
Daniel Veillard4255d502002-04-16 15:50:10 +00002899/**
2900 * xmlSchemaElementDump:
2901 * @elem: an element
2902 * @output: the file output
2903 *
2904 * Dump the element
2905 */
2906static void
2907xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002908 const xmlChar * name ATTRIBUTE_UNUSED,
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002909 const xmlChar * namespace ATTRIBUTE_UNUSED,
2910 const xmlChar * context ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00002911{
2912 if (elem == NULL)
2913 return;
2914
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002915 if (elem->flags & XML_SCHEMAS_ELEM_REF) {
2916 fprintf(output, "Particle: %s", name);
2917 fprintf(output, ", term element: %s", elem->ref);
2918 if (elem->refNs != NULL)
2919 fprintf(output, " ns %s", elem->refNs);
2920 } else {
2921 fprintf(output, "Element");
2922 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
2923 fprintf(output, " (global)");
2924 fprintf(output, ": %s ", elem->name);
2925 if (namespace != NULL)
2926 fprintf(output, "ns %s", namespace);
2927 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002928 fprintf(output, "\n");
2929 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002930 fprintf(output, " min %d ", elem->minOccurs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002931 if (elem->maxOccurs >= UNBOUNDED)
2932 fprintf(output, "max: unbounded\n");
2933 else if (elem->maxOccurs != 1)
2934 fprintf(output, "max: %d\n", elem->maxOccurs);
2935 else
2936 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002937 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002938 /*
2939 * Misc other properties.
2940 */
2941 if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
2942 (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
2943 (elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
2944 (elem->flags & XML_SCHEMAS_ELEM_DEFAULT) ||
2945 (elem->id != NULL)) {
2946 fprintf(output, " props: ");
2947 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
2948 fprintf(output, "[fixed] ");
2949 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
2950 fprintf(output, "[default] ");
2951 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
2952 fprintf(output, "[abstract] ");
2953 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
2954 fprintf(output, "[nillable] ");
2955 if (elem->id != NULL)
2956 fprintf(output, "[id: '%s'] ", elem->id);
2957 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002958 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002959 /*
2960 * Default/fixed value.
2961 */
Daniel Veillard4255d502002-04-16 15:50:10 +00002962 if (elem->value != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002963 fprintf(output, " value: '%s'\n", elem->value);
2964 /*
2965 * Type.
2966 */
2967 if (elem->namedType != NULL) {
2968 fprintf(output, " type: %s ", elem->namedType);
2969 if (elem->namedTypeNs != NULL)
2970 fprintf(output, "ns %s\n", elem->namedTypeNs);
2971 else
2972 fprintf(output, "\n");
2973 }
2974 /*
2975 * Substitution group.
2976 */
2977 if (elem->substGroup != NULL) {
2978 fprintf(output, " substitutionGroup: %s ", elem->substGroup);
2979 if (elem->substGroupNs != NULL)
2980 fprintf(output, "ns %s\n", elem->substGroupNs);
2981 else
2982 fprintf(output, "\n");
2983 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002984}
2985
2986/**
2987 * xmlSchemaAnnotDump:
2988 * @output: the file output
2989 * @annot: a annotation
2990 *
2991 * Dump the annotation
2992 */
2993static void
2994xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
2995{
2996 xmlChar *content;
2997
2998 if (annot == NULL)
2999 return;
3000
3001 content = xmlNodeGetContent(annot->content);
3002 if (content != NULL) {
3003 fprintf(output, " Annot: %s\n", content);
3004 xmlFree(content);
3005 } else
3006 fprintf(output, " Annot: empty\n");
3007}
3008
3009/**
3010 * xmlSchemaTypeDump:
3011 * @output: the file output
3012 * @type: a type structure
3013 *
3014 * Dump a SchemaType structure
3015 */
3016static void
3017xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
3018{
3019 if (type == NULL) {
3020 fprintf(output, "Type: NULL\n");
3021 return;
3022 }
3023 fprintf(output, "Type: ");
3024 if (type->name != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003025 fprintf(output, "%s ", type->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003026 else
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003027 fprintf(output, "no name ");
3028 if (type->targetNamespace != NULL)
3029 fprintf(output, "ns %s ", type->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003030 switch (type->type) {
3031 case XML_SCHEMA_TYPE_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003032 fprintf(output, "[basic] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003033 break;
3034 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003035 fprintf(output, "[simple] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003036 break;
3037 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003038 fprintf(output, "[complex] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003039 break;
3040 case XML_SCHEMA_TYPE_SEQUENCE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003041 fprintf(output, "[sequence] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003042 break;
3043 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003044 fprintf(output, "[choice] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003045 break;
3046 case XML_SCHEMA_TYPE_ALL:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003047 fprintf(output, "[all] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003048 break;
3049 case XML_SCHEMA_TYPE_UR:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003050 fprintf(output, "[ur] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003051 break;
3052 case XML_SCHEMA_TYPE_RESTRICTION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003053 fprintf(output, "[restriction] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003054 break;
3055 case XML_SCHEMA_TYPE_EXTENSION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003056 fprintf(output, "[extension] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003057 break;
3058 default:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003059 fprintf(output, "[unknown type %d] ", type->type);
Daniel Veillard4255d502002-04-16 15:50:10 +00003060 break;
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003061 }
3062 fprintf(output, "content: ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003063 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003064 case XML_SCHEMA_CONTENT_UNKNOWN:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003065 fprintf(output, "[unknown] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003066 break;
3067 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003068 fprintf(output, "[empty] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003069 break;
3070 case XML_SCHEMA_CONTENT_ELEMENTS:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003071 fprintf(output, "[element] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003072 break;
3073 case XML_SCHEMA_CONTENT_MIXED:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003074 fprintf(output, "[mixed] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003075 break;
3076 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003077 /* not used. */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003078 break;
3079 case XML_SCHEMA_CONTENT_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003080 fprintf(output, "[basic] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003081 break;
3082 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003083 fprintf(output, "[simple] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003084 break;
3085 case XML_SCHEMA_CONTENT_ANY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003086 fprintf(output, "[any] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003087 break;
Daniel Veillard4255d502002-04-16 15:50:10 +00003088 }
3089 fprintf(output, "\n");
3090 if ((type->minOccurs != 1) || (type->maxOccurs != 1)) {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003091 fprintf(output, " min: %d ", type->minOccurs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003092 if (type->maxOccurs >= UNBOUNDED)
3093 fprintf(output, "max: unbounded\n");
3094 else if (type->maxOccurs != 1)
3095 fprintf(output, "max: %d\n", type->maxOccurs);
3096 else
3097 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00003098 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003099 if (type->base != NULL) {
3100 fprintf(output, " base type: %s", type->base);
3101 if (type->baseNs != NULL)
3102 fprintf(output, " ns %s\n", type->baseNs);
3103 else
3104 fprintf(output, "\n");
3105 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003106 if (type->annot != NULL)
3107 xmlSchemaAnnotDump(output, type->annot);
3108 if (type->subtypes != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003109 xmlSchemaTypePtr sub = type->subtypes;
Daniel Veillard4255d502002-04-16 15:50:10 +00003110
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003111 fprintf(output, " subtypes: ");
3112 while (sub != NULL) {
3113 fprintf(output, "%s ", sub->name);
3114 sub = sub->next;
3115 }
3116 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00003117 }
3118
3119}
3120
3121/**
3122 * xmlSchemaDump:
3123 * @output: the file output
3124 * @schema: a schema structure
3125 *
3126 * Dump a Schema structure.
3127 */
3128void
3129xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
3130{
Daniel Veillardce682bc2004-11-05 17:22:25 +00003131 if (output == NULL)
3132 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003133 if (schema == NULL) {
3134 fprintf(output, "Schemas: NULL\n");
3135 return;
3136 }
3137 fprintf(output, "Schemas: ");
3138 if (schema->name != NULL)
3139 fprintf(output, "%s, ", schema->name);
3140 else
3141 fprintf(output, "no name, ");
3142 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00003143 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003144 else
3145 fprintf(output, "no target namespace");
3146 fprintf(output, "\n");
3147 if (schema->annot != NULL)
3148 xmlSchemaAnnotDump(output, schema->annot);
3149
3150 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
3151 output);
3152 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003153 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00003154}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003155
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003156#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00003157#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003158/**
3159 * xmlSchemaDebugDumpIDCTable:
3160 * @vctxt: the WXS validation context
3161 *
3162 * Displays the current IDC table for debug purposes.
3163 */
3164static void
3165xmlSchemaDebugDumpIDCTable(FILE * output,
3166 const xmlChar *namespaceName,
3167 const xmlChar *localName,
3168 xmlSchemaPSVIIDCBindingPtr bind)
3169{
3170 xmlChar *str = NULL, *value;
3171 xmlSchemaPSVIIDCNodePtr tab;
3172 xmlSchemaPSVIIDCKeyPtr key;
3173 int i, j, res;
3174
3175 fprintf(output, "IDC: TABLES on %s\n",
3176 xmlSchemaFormatNsUriLocal(&str, namespaceName, localName));
3177 FREE_AND_NULL(str)
3178
3179 if (bind == NULL)
3180 return;
3181 do {
3182 fprintf(output, "IDC: BINDING %s\n",
3183 xmlSchemaFormatNsUriLocal(&str, bind->definition->targetNamespace,
3184 bind->definition->name));
3185 FREE_AND_NULL(str)
3186 for (i = 0; i < bind->nbNodes; i++) {
3187 tab = bind->nodeTable[i];
3188 fprintf(output, " ( ");
3189 for (j = 0; j < bind->definition->nbFields; j++) {
3190 key = tab->keys[j];
3191 if ((key != NULL) && (key->compValue != NULL)) {
3192#ifdef IDC_VALUE_SUPPORT
3193 res = xmlSchemaGetCanonValue(key->compValue, &value);
3194#else
3195 value = xmlStrdup(BAD_CAST "dummy-value");
3196 res = 0;
3197#endif
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003198 if (res >= 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003199 fprintf(output, "\"%s\" ", value);
3200 else
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003201 fprintf(output, "CANON-VALUE-FAILED ");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003202 if (res == 0)
3203 FREE_AND_NULL(value)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003204 } else if (key != NULL)
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003205 fprintf(output, "(no val), ");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003206 else
3207 fprintf(output, "(key missing), ");
3208 }
3209 fprintf(output, ")\n");
3210 }
3211 bind = bind->next;
3212 } while (bind != NULL);
3213}
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00003214#endif /* DEBUG_IDC */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003215#endif /* IDC_ENABLED */
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00003216#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +00003217
3218/************************************************************************
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003219 * *
3220 * Utilities *
3221 * *
3222 ************************************************************************/
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003223
Daniel Veillardc0826a72004-08-10 14:17:33 +00003224/**
3225 * xmlSchemaGetPropNode:
3226 * @node: the element node
3227 * @name: the name of the attribute
3228 *
3229 * Seeks an attribute with a name of @name in
3230 * no namespace.
3231 *
3232 * Returns the attribute or NULL if not present.
3233 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003234static xmlAttrPtr
Daniel Veillardc0826a72004-08-10 14:17:33 +00003235xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
Daniel Veillard01fa6152004-06-29 17:04:39 +00003236{
3237 xmlAttrPtr prop;
3238
Daniel Veillardc0826a72004-08-10 14:17:33 +00003239 if ((node == NULL) || (name == NULL))
3240 return(NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003241 prop = node->properties;
3242 while (prop != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00003243 if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
3244 return(prop);
3245 prop = prop->next;
3246 }
3247 return (NULL);
3248}
3249
3250/**
3251 * xmlSchemaGetPropNodeNs:
3252 * @node: the element node
3253 * @uri: the uri
3254 * @name: the name of the attribute
3255 *
3256 * Seeks an attribute with a local name of @name and
3257 * a namespace URI of @uri.
3258 *
3259 * Returns the attribute or NULL if not present.
3260 */
3261static xmlAttrPtr
3262xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
3263{
3264 xmlAttrPtr prop;
3265
3266 if ((node == NULL) || (name == NULL))
3267 return(NULL);
3268 prop = node->properties;
3269 while (prop != NULL) {
3270 if ((prop->ns != NULL) &&
3271 xmlStrEqual(prop->name, BAD_CAST name) &&
3272 xmlStrEqual(prop->ns->href, BAD_CAST uri))
Daniel Veillard01fa6152004-06-29 17:04:39 +00003273 return(prop);
3274 prop = prop->next;
3275 }
3276 return (NULL);
3277}
3278
3279static const xmlChar *
3280xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3281{
3282 xmlChar *val;
3283 const xmlChar *ret;
3284
3285 val = xmlNodeGetContent(node);
3286 if (val == NULL)
3287 return(NULL);
3288 ret = xmlDictLookup(ctxt->dict, val, -1);
3289 xmlFree(val);
3290 return(ret);
3291}
3292
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003293/**
3294 * xmlSchemaGetProp:
3295 * @ctxt: the parser context
3296 * @node: the node
3297 * @name: the property name
3298 *
3299 * Read a attribute value and internalize the string
3300 *
3301 * Returns the string or NULL if not present.
3302 */
3303static const xmlChar *
3304xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
3305 const char *name)
3306{
3307 xmlChar *val;
3308 const xmlChar *ret;
3309
3310 val = xmlGetProp(node, BAD_CAST name);
3311 if (val == NULL)
3312 return(NULL);
3313 ret = xmlDictLookup(ctxt->dict, val, -1);
3314 xmlFree(val);
3315 return(ret);
3316}
3317
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003318/************************************************************************
Daniel Veillard4255d502002-04-16 15:50:10 +00003319 * *
3320 * Parsing functions *
3321 * *
3322 ************************************************************************/
3323
3324/**
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003325 * xmlSchemaGetElem:
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003326 * @schema: the schema context
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003327 * @name: the element name
3328 * @ns: the element namespace
3329 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003330 * Lookup a global element declaration in the schema.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003331 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003332 * Returns the element declaration or NULL if not found.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003333 */
3334static xmlSchemaElementPtr
3335xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003336 const xmlChar * namespace)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003337{
3338 xmlSchemaElementPtr ret;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003339
3340 if ((name == NULL) || (schema == NULL))
3341 return (NULL);
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003342
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003343 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003344 if ((ret != NULL) &&
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003345 (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003346 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00003347 } else
3348 ret = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00003349 /*
3350 * This one was removed, since top level element declarations have
3351 * the target namespace specified in targetNamespace of the <schema>
3352 * information element, even if elementFormDefault is "unqualified".
3353 */
3354
3355 /* else if ((schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003356 if (xmlStrEqual(namespace, schema->targetNamespace))
3357 ret = xmlHashLookup2(schema->elemDecl, name, NULL);
3358 else
3359 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003360 if ((ret != NULL) &&
3361 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003362 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003363 }
William M. Bracke7091952004-05-11 15:09:58 +00003364 */
Daniel Veillard3646d642004-06-02 19:19:14 +00003365
William M. Brack2f2a6632004-08-20 23:09:47 +00003366 /*
3367 * Removed since imported components will be hold by the main schema only.
3368 *
Daniel Veillard3646d642004-06-02 19:19:14 +00003369 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003370 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003371 else
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003372 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003373 if (import != NULL) {
Daniel Veillardf2a12832003-11-24 13:04:35 +00003374 ret = xmlSchemaGetElem(import->schema, name, namespace, level + 1);
Daniel Veillard3646d642004-06-02 19:19:14 +00003375 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
3376 return (ret);
3377 } else
3378 ret = NULL;
3379 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003380 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003381#ifdef DEBUG
3382 if (ret == NULL) {
3383 if (namespace == NULL)
3384 fprintf(stderr, "Unable to lookup type %s", name);
3385 else
3386 fprintf(stderr, "Unable to lookup type %s:%s", name,
3387 namespace);
3388 }
3389#endif
3390 return (ret);
3391}
3392
3393/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003394 * xmlSchemaGetType:
3395 * @schema: the schemas context
3396 * @name: the type name
3397 * @ns: the type namespace
3398 *
3399 * Lookup a type in the schemas or the predefined types
3400 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003401 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +00003402 */
3403static xmlSchemaTypePtr
3404xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003405 const xmlChar * namespace)
3406{
Daniel Veillard4255d502002-04-16 15:50:10 +00003407 xmlSchemaTypePtr ret;
3408
3409 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003410 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003411 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003412 ret = xmlHashLookup2(schema->typeDecl, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003413 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003414 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003415 }
3416 ret = xmlSchemaGetPredefinedType(name, namespace);
Daniel Veillard1d913862003-11-21 00:28:39 +00003417 if (ret != NULL)
3418 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00003419 /*
3420 * Removed, since the imported components will be grafted on the
3421 * main schema only.
Daniel Veillard3646d642004-06-02 19:19:14 +00003422 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003423 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003424 else
Daniel Veillard1d913862003-11-21 00:28:39 +00003425 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003426 if (import != NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00003427 ret = xmlSchemaGetType(import->schema, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003428 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
3429 return (ret);
3430 } else
3431 ret = NULL;
3432 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003433 */
Daniel Veillard4255d502002-04-16 15:50:10 +00003434#ifdef DEBUG
3435 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003436 if (namespace == NULL)
3437 fprintf(stderr, "Unable to lookup type %s", name);
3438 else
3439 fprintf(stderr, "Unable to lookup type %s:%s", name,
3440 namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003441 }
3442#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003443 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003444}
3445
Daniel Veillard3646d642004-06-02 19:19:14 +00003446/**
3447 * xmlSchemaGetAttribute:
3448 * @schema: the context of the schema
3449 * @name: the name of the attribute
3450 * @ns: the target namespace of the attribute
3451 *
3452 * Lookup a an attribute in the schema or imported schemas
3453 *
3454 * Returns the attribute declaration or NULL if not found.
3455 */
3456static xmlSchemaAttributePtr
3457xmlSchemaGetAttribute(xmlSchemaPtr schema, const xmlChar * name,
3458 const xmlChar * namespace)
3459{
3460 xmlSchemaAttributePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00003461
3462 if ((name == NULL) || (schema == NULL))
3463 return (NULL);
3464
3465
3466 ret = xmlHashLookup2(schema->attrDecl, name, namespace);
3467 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL))
3468 return (ret);
3469 else
3470 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00003471 /*
3472 * Removed, since imported components will be hold by the main schema only.
3473 *
Daniel Veillard3646d642004-06-02 19:19:14 +00003474 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003475 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003476 else
3477 import = xmlHashLookup(schema->schemasImports, namespace);
3478 if (import != NULL) {
3479 ret = xmlSchemaGetAttribute(import->schema, name, namespace);
3480 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL)) {
3481 return (ret);
3482 } else
3483 ret = NULL;
3484 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003485 */
Daniel Veillard3646d642004-06-02 19:19:14 +00003486#ifdef DEBUG
3487 if (ret == NULL) {
3488 if (namespace == NULL)
3489 fprintf(stderr, "Unable to lookup attribute %s", name);
3490 else
3491 fprintf(stderr, "Unable to lookup attribute %s:%s", name,
3492 namespace);
3493 }
3494#endif
3495 return (ret);
3496}
3497
3498/**
3499 * xmlSchemaGetAttributeGroup:
3500 * @schema: the context of the schema
3501 * @name: the name of the attribute group
3502 * @ns: the target namespace of the attribute group
3503 *
3504 * Lookup a an attribute group in the schema or imported schemas
3505 *
3506 * Returns the attribute group definition or NULL if not found.
3507 */
3508static xmlSchemaAttributeGroupPtr
3509xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
3510 const xmlChar * namespace)
3511{
3512 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00003513
3514 if ((name == NULL) || (schema == NULL))
3515 return (NULL);
3516
3517
3518 ret = xmlHashLookup2(schema->attrgrpDecl, name, namespace);
3519 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
3520 return (ret);
3521 else
3522 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00003523 /*
3524 * Removed since imported components will be hold by the main schema only.
3525 *
Daniel Veillard3646d642004-06-02 19:19:14 +00003526 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003527 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003528 else
3529 import = xmlHashLookup(schema->schemasImports, namespace);
3530 if (import != NULL) {
3531 ret = xmlSchemaGetAttributeGroup(import->schema, name, namespace);
3532 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
3533 return (ret);
3534 else
3535 ret = NULL;
3536 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003537 */
Daniel Veillard3646d642004-06-02 19:19:14 +00003538#ifdef DEBUG
3539 if (ret == NULL) {
3540 if (namespace == NULL)
3541 fprintf(stderr, "Unable to lookup attribute group %s", name);
3542 else
3543 fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
3544 namespace);
3545 }
3546#endif
3547 return (ret);
3548}
3549
3550/**
3551 * xmlSchemaGetGroup:
3552 * @schema: the context of the schema
3553 * @name: the name of the group
3554 * @ns: the target namespace of the group
3555 *
3556 * Lookup a group in the schema or imported schemas
3557 *
3558 * Returns the group definition or NULL if not found.
3559 */
3560static xmlSchemaTypePtr
3561xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
3562 const xmlChar * namespace)
3563{
3564 xmlSchemaTypePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00003565
3566 if ((name == NULL) || (schema == NULL))
3567 return (NULL);
3568
3569
3570 ret = xmlHashLookup2(schema->groupDecl, name, namespace);
3571 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
3572 return (ret);
3573 else
3574 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00003575 /*
3576 * Removed since imported components will be hold by the main schema only.
3577 *
Daniel Veillard3646d642004-06-02 19:19:14 +00003578 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003579 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003580 else
3581 import = xmlHashLookup(schema->schemasImports, namespace);
3582 if (import != NULL) {
3583 ret = xmlSchemaGetGroup(import->schema, name, namespace);
3584 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
3585 return (ret);
3586 else
3587 ret = NULL;
3588 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003589 */
Daniel Veillard3646d642004-06-02 19:19:14 +00003590#ifdef DEBUG
3591 if (ret == NULL) {
3592 if (namespace == NULL)
3593 fprintf(stderr, "Unable to lookup group %s", name);
3594 else
3595 fprintf(stderr, "Unable to lookup group %s:%s", name,
3596 namespace);
3597 }
3598#endif
3599 return (ret);
3600}
3601
Daniel Veillard4255d502002-04-16 15:50:10 +00003602/************************************************************************
3603 * *
3604 * Parsing functions *
3605 * *
3606 ************************************************************************/
3607
3608#define IS_BLANK_NODE(n) \
3609 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content)))
3610
3611/**
3612 * xmlSchemaIsBlank:
3613 * @str: a string
3614 *
3615 * Check if a string is ignorable
3616 *
3617 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
3618 */
3619static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003620xmlSchemaIsBlank(xmlChar * str)
3621{
Daniel Veillard4255d502002-04-16 15:50:10 +00003622 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003623 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003624 while (*str != 0) {
William M. Brack76e95df2003-10-18 16:20:14 +00003625 if (!(IS_BLANK_CH(*str)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003626 return (0);
3627 str++;
Daniel Veillard4255d502002-04-16 15:50:10 +00003628 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003629 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003630}
3631
3632/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003633 * xmlSchemaAddAssembledItem:
3634 * @ctxt: a schema parser context
3635 * @schema: the schema being built
3636 * @item: the item
3637 *
3638 * Add a item to the schema's list of current items.
3639 * This is used if the schema was already constructed and
3640 * new schemata need to be added to it.
3641 * *WARNING* this interface is highly subject to change.
3642 *
3643 * Returns 0 if suceeds and -1 if an internal error occurs.
3644 */
3645static int
3646xmlSchemaAddAssembledItem(xmlSchemaParserCtxtPtr ctxt,
3647 xmlSchemaTypePtr item)
3648{
3649 static int growSize = 100;
3650 xmlSchemaAssemblePtr ass;
3651
3652 ass = ctxt->assemble;
3653 if (ass->sizeItems < 0) {
3654 /* If disabled. */
3655 return (0);
3656 }
3657 if (ass->sizeItems <= 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003658 ass->items = (void **) xmlMalloc(growSize * sizeof(xmlSchemaTypePtr));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003659 if (ass->items == NULL) {
3660 xmlSchemaPErrMemory(ctxt,
3661 "allocating new item buffer", NULL);
3662 return (-1);
3663 }
3664 ass->sizeItems = growSize;
3665 } else if (ass->sizeItems <= ass->nbItems) {
3666 ass->sizeItems *= 2;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003667 ass->items = (void **) xmlRealloc(ass->items,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003668 ass->sizeItems * sizeof(xmlSchemaTypePtr));
3669 if (ass->items == NULL) {
3670 xmlSchemaPErrMemory(ctxt,
3671 "growing item buffer", NULL);
3672 ass->sizeItems = 0;
3673 return (-1);
3674 }
3675 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003676 /* ass->items[ass->nbItems++] = (void *) item; */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003677 ((xmlSchemaTypePtr *) ass->items)[ass->nbItems++] = (void *) item;
3678 return (0);
3679}
3680
3681/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003682 * xmlSchemaAddNotation:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003683 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003684 * @schema: the schema being built
3685 * @name: the item name
3686 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00003687 * Add an XML schema annotation declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00003688 * *WARNING* this interface is highly subject to change
3689 *
3690 * Returns the new struture or NULL in case of error
3691 */
3692static xmlSchemaNotationPtr
3693xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00003694 const xmlChar *name)
Daniel Veillard4255d502002-04-16 15:50:10 +00003695{
3696 xmlSchemaNotationPtr ret = NULL;
3697 int val;
3698
3699 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3700 return (NULL);
3701
3702 if (schema->notaDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003703 schema->notaDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003704 if (schema->notaDecl == NULL)
3705 return (NULL);
3706
3707 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
3708 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003709 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003710 return (NULL);
3711 }
3712 memset(ret, 0, sizeof(xmlSchemaNotation));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003713 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003714 val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
3715 ret);
3716 if (val != 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00003717 /*
3718 * TODO: This should never happen, since a unique name will be computed.
3719 * If it fails, then an other internal error must have occured.
3720 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003721 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
3722 XML_SCHEMAP_REDEFINED_NOTATION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003723 "Annotation declaration '%s' is already declared.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003724 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003725 xmlFree(ret);
3726 return (NULL);
3727 }
3728 return (ret);
3729}
3730
3731
3732/**
3733 * xmlSchemaAddAttribute:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003734 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003735 * @schema: the schema being built
3736 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003737 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00003738 *
3739 * Add an XML schema Attrribute declaration
3740 * *WARNING* this interface is highly subject to change
3741 *
3742 * Returns the new struture or NULL in case of error
3743 */
3744static xmlSchemaAttributePtr
3745xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003746 const xmlChar * name, const xmlChar * namespace,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003747 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00003748{
3749 xmlSchemaAttributePtr ret = NULL;
3750 int val;
3751
3752 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3753 return (NULL);
3754
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003755#ifdef DEBUG
3756 fprintf(stderr, "Adding attribute %s\n", name);
3757 if (namespace != NULL)
3758 fprintf(stderr, " target namespace %s\n", namespace);
3759#endif
3760
Daniel Veillard4255d502002-04-16 15:50:10 +00003761 if (schema->attrDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003762 schema->attrDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003763 if (schema->attrDecl == NULL)
3764 return (NULL);
3765
3766 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
3767 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003768 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003769 return (NULL);
3770 }
3771 memset(ret, 0, sizeof(xmlSchemaAttribute));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003772 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00003773 ret->targetNamespace = namespace;
Daniel Veillard4255d502002-04-16 15:50:10 +00003774 val = xmlHashAddEntry3(schema->attrDecl, name,
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00003775 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003776 if (val != 0) {
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003777 if (topLevel) {
3778 xmlSchemaPCustomErr(ctxt,
3779 XML_SCHEMAP_REDEFINED_ATTR,
3780 NULL, NULL, node,
3781 "A global attribute declaration with the name '%s' does "
3782 "already exist", name);
3783 xmlFree(ret);
3784 return (NULL);
3785 } else {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003786 char buf[30];
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003787 /*
3788 * Using the ctxt->container for xmlHashAddEntry3 is ambigious
3789 * in the scenario:
3790 * 1. multiple top-level complex types have different target
3791 * namespaces but have the SAME NAME; this can happen if
3792 * schemata are imported
3793 * 2. those complex types contain attributes with an equal name
3794 * 3. those attributes are in no namespace
3795 * We will compute a new context string.
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003796 */
3797 snprintf(buf, 29, "#aCont%d", ctxt->counter++ + 1);
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003798 val = xmlHashAddEntry3(schema->attrDecl, name,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00003799 namespace, xmlDictLookup(ctxt->dict, BAD_CAST buf, -1), ret);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003800
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003801 if (val != 0) {
3802 xmlSchemaPCustomErr(ctxt,
3803 XML_SCHEMAP_INTERNAL,
3804 NULL, NULL, node,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003805 "Internal error: xmlSchemaAddAttribute, "
3806 "a dublicate attribute declaration with the name '%s' "
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003807 "could not be added to the hash.", name);
3808 xmlFree(ret);
3809 return (NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003810 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003811 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003812 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003813 if (ctxt->assemble != NULL)
3814 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003815 return (ret);
3816}
3817
3818/**
3819 * xmlSchemaAddAttributeGroup:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003820 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003821 * @schema: the schema being built
3822 * @name: the item name
3823 *
3824 * Add an XML schema Attrribute Group declaration
3825 *
3826 * Returns the new struture or NULL in case of error
3827 */
3828static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003829xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00003830 xmlSchemaPtr schema, const xmlChar * name,
3831 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003832{
3833 xmlSchemaAttributeGroupPtr ret = NULL;
3834 int val;
3835
3836 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3837 return (NULL);
3838
3839 if (schema->attrgrpDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003840 schema->attrgrpDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003841 if (schema->attrgrpDecl == NULL)
3842 return (NULL);
3843
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003844 ret =
3845 (xmlSchemaAttributeGroupPtr)
3846 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00003847 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003848 xmlSchemaPErrMemory(ctxt, "allocating attribute group", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003849 return (NULL);
3850 }
3851 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003852 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003853 val = xmlHashAddEntry3(schema->attrgrpDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003854 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003855 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003856 xmlSchemaPCustomErr(ctxt,
3857 XML_SCHEMAP_REDEFINED_ATTRGROUP,
3858 NULL, NULL, node,
3859 "A global attribute group definition with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003860 xmlFree(ret);
3861 return (NULL);
3862 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003863 if (ctxt->assemble != NULL)
3864 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003865 return (ret);
3866}
3867
3868/**
3869 * xmlSchemaAddElement:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003870 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003871 * @schema: the schema being built
3872 * @name: the type name
3873 * @namespace: the type namespace
3874 *
3875 * Add an XML schema Element declaration
3876 * *WARNING* this interface is highly subject to change
3877 *
3878 * Returns the new struture or NULL in case of error
3879 */
3880static xmlSchemaElementPtr
3881xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003882 const xmlChar * name, const xmlChar * namespace,
3883 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00003884{
3885 xmlSchemaElementPtr ret = NULL;
3886 int val;
3887
3888 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3889 return (NULL);
3890
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003891#ifdef DEBUG
3892 fprintf(stderr, "Adding element %s\n", name);
3893 if (namespace != NULL)
3894 fprintf(stderr, " target namespace %s\n", namespace);
3895#endif
3896
Daniel Veillard4255d502002-04-16 15:50:10 +00003897 if (schema->elemDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003898 schema->elemDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003899 if (schema->elemDecl == NULL)
3900 return (NULL);
3901
3902 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
3903 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003904 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003905 return (NULL);
3906 }
3907 memset(ret, 0, sizeof(xmlSchemaElement));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003908 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003909 val = xmlHashAddEntry3(schema->elemDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003910 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003911 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003912 if (topLevel) {
3913 xmlSchemaPCustomErr(ctxt,
3914 XML_SCHEMAP_REDEFINED_ELEMENT,
3915 NULL, NULL, node,
3916 "A global element declaration with the name '%s' does "
3917 "already exist", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003918 xmlFree(ret);
3919 return (NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00003920 } else {
3921 char buf[30];
3922
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003923 snprintf(buf, 29, "#eCont%d", ctxt->counter++ + 1);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003924 val = xmlHashAddEntry3(schema->elemDecl, name,
3925 namespace, (xmlChar *) buf, ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00003926 if (val != 0) {
3927 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003928 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00003929 NULL, NULL, node,
3930 "Internal error: xmlSchemaAddElement, "
3931 "a dublicate element declaration with the name '%s' "
3932 "could not be added to the hash.", name);
3933 xmlFree(ret);
3934 return (NULL);
3935 }
3936 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00003937
Daniel Veillard4255d502002-04-16 15:50:10 +00003938 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003939 if (ctxt->assemble != NULL)
3940 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003941 return (ret);
3942}
3943
3944/**
3945 * xmlSchemaAddType:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003946 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003947 * @schema: the schema being built
3948 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003949 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00003950 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00003951 * Add an XML schema item
Daniel Veillard4255d502002-04-16 15:50:10 +00003952 * *WARNING* this interface is highly subject to change
3953 *
3954 * Returns the new struture or NULL in case of error
3955 */
3956static xmlSchemaTypePtr
3957xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003958 const xmlChar * name, const xmlChar * namespace,
3959 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003960{
3961 xmlSchemaTypePtr ret = NULL;
3962 int val;
3963
3964 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3965 return (NULL);
3966
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003967#ifdef DEBUG
3968 fprintf(stderr, "Adding type %s\n", name);
3969 if (namespace != NULL)
3970 fprintf(stderr, " target namespace %s\n", namespace);
3971#endif
3972
Daniel Veillard4255d502002-04-16 15:50:10 +00003973 if (schema->typeDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003974 schema->typeDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003975 if (schema->typeDecl == NULL)
3976 return (NULL);
3977
3978 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
3979 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003980 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003981 return (NULL);
3982 }
3983 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003984 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003985 ret->redef = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003986 val = xmlHashAddEntry2(schema->typeDecl, name, namespace, ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00003987 if (val != 0) {
3988 if (ctxt->includes == 0) {
3989 xmlSchemaPCustomErr(ctxt,
3990 XML_SCHEMAP_REDEFINED_TYPE,
3991 NULL, NULL, node,
3992 "A global type definition with the name '%s' does already exist", name);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003993 xmlFree(ret);
3994 return (NULL);
3995 } else {
3996 xmlSchemaTypePtr prev;
3997
3998 prev = xmlHashLookup2(schema->typeDecl, name, namespace);
3999 if (prev == NULL) {
4000 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004001 XML_ERR_INTERNAL_ERROR,
4002 "Internal error: xmlSchemaAddType, on type "
4003 "'%s'.\n",
4004 name, NULL);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004005 xmlFree(ret);
4006 return (NULL);
4007 }
4008 ret->redef = prev->redef;
4009 prev->redef = ret;
4010 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004011 }
4012 ret->minOccurs = 1;
4013 ret->maxOccurs = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +00004014 ret->attributeUses = NULL;
4015 ret->attributeWildcard = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004016 if (ctxt->assemble != NULL)
4017 xmlSchemaAddAssembledItem(ctxt,ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004018 return (ret);
4019}
4020
4021/**
4022 * xmlSchemaAddGroup:
4023 * @ctxt: a schema validation context
4024 * @schema: the schema being built
4025 * @name: the group name
4026 *
4027 * Add an XML schema Group definition
4028 *
4029 * Returns the new struture or NULL in case of error
4030 */
4031static xmlSchemaTypePtr
4032xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004033 const xmlChar *name, const xmlChar *namespaceName,
4034 xmlNodePtr node)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004035{
4036 xmlSchemaTypePtr ret = NULL;
4037 int val;
4038
4039 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4040 return (NULL);
4041
4042 if (schema->groupDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004043 schema->groupDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004044 if (schema->groupDecl == NULL)
4045 return (NULL);
4046
4047 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
4048 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004049 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004050 return (NULL);
4051 }
4052 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004053 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004054 val =
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004055 xmlHashAddEntry2(schema->groupDecl, name, namespaceName,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004056 ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004057 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004058 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00004059 XML_SCHEMAP_REDEFINED_GROUP,
4060 NULL, NULL, node,
4061 "A global model group definition with the name '%s' does already "
4062 "exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004063 xmlFree(ret);
4064 return (NULL);
4065 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00004066 ret->targetNamespace = namespaceName;
Daniel Veillard4255d502002-04-16 15:50:10 +00004067 ret->minOccurs = 1;
4068 ret->maxOccurs = 1;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004069 if (ctxt->assemble != NULL)
4070 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004071 return (ret);
4072}
4073
Daniel Veillard3646d642004-06-02 19:19:14 +00004074/**
4075 * xmlSchemaNewWildcardNs:
4076 * @ctxt: a schema validation context
4077 *
4078 * Creates a new wildcard namespace constraint.
4079 *
4080 * Returns the new struture or NULL in case of error
4081 */
4082static xmlSchemaWildcardNsPtr
4083xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
4084{
4085 xmlSchemaWildcardNsPtr ret;
4086
4087 ret = (xmlSchemaWildcardNsPtr)
4088 xmlMalloc(sizeof(xmlSchemaWildcardNs));
4089 if (ret == NULL) {
4090 xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
4091 return (NULL);
4092 }
4093 ret->value = NULL;
4094 ret->next = NULL;
4095 return (ret);
4096}
4097
4098/**
4099 * xmlSchemaAddWildcard:
4100 * @ctxt: a schema validation context
Daniel Veillardc0826a72004-08-10 14:17:33 +00004101 * Adds a wildcard. It corresponds to a
4102 * xsd:anyAttribute and is used as storage for namespace
4103 * constraints on a xsd:any.
Daniel Veillard3646d642004-06-02 19:19:14 +00004104 *
4105 * Returns the new struture or NULL in case of error
4106 */
4107static xmlSchemaWildcardPtr
4108xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt)
4109{
4110 xmlSchemaWildcardPtr ret = NULL;
4111
4112 if (ctxt == NULL)
4113 return (NULL);
4114
4115 ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
4116 if (ret == NULL) {
4117 xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
4118 return (NULL);
4119 }
4120 memset(ret, 0, sizeof(xmlSchemaWildcard));
4121 ret->minOccurs = 1;
4122 ret->maxOccurs = 1;
4123
4124 return (ret);
4125}
4126
Daniel Veillard4255d502002-04-16 15:50:10 +00004127/************************************************************************
4128 * *
4129 * Utilities for parsing *
4130 * *
4131 ************************************************************************/
4132
4133/**
4134 * xmlGetQNameProp:
4135 * @ctxt: a schema validation context
4136 * @node: a subtree containing XML Schema informations
4137 * @name: the attribute name
4138 * @namespace: the result namespace if any
4139 *
4140 * Extract a QName Attribute value
4141 *
4142 * Returns the NCName or NULL if not found, and also update @namespace
4143 * with the namespace URI
4144 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004145static const xmlChar *
Daniel Veillard4255d502002-04-16 15:50:10 +00004146xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004147 const char *name, const xmlChar ** namespace)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004148{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004149 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00004150 xmlNsPtr ns;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004151 const xmlChar *ret, *prefix;
4152 int len;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004153 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00004154
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004155 *namespace = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004156 attr = xmlSchemaGetPropNode(node, name);
4157 if (attr == NULL)
4158 return (NULL);
4159 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004160
Daniel Veillard4255d502002-04-16 15:50:10 +00004161 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004162 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004163
Daniel Veillardba0153a2004-04-01 10:42:31 +00004164 if (!strchr((char *) val, ':')) {
Daniel Veillardebcdebd2004-03-05 00:15:50 +00004165 ns = xmlSearchNs(node->doc, node, 0);
4166 if (ns) {
4167 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
4168 return (val);
4169 }
4170 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004171 ret = xmlSplitQName3(val, &len);
4172 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004173 return (val);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004174 }
4175 ret = xmlDictLookup(ctxt->dict, ret, -1);
4176 prefix = xmlDictLookup(ctxt->dict, val, len);
Daniel Veillard4255d502002-04-16 15:50:10 +00004177
4178 ns = xmlSearchNs(node->doc, node, prefix);
4179 if (ns == NULL) {
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004180 xmlSchemaPSimpleTypeErr(ctxt, XML_SCHEMAP_PREFIX_UNDEFINED,
4181 NULL, NULL, (xmlNodePtr) attr,
4182 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, val,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004183 "The QName value '%s' has no corresponding namespace "
4184 "declaration in scope", val, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004185 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004186 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004187 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004188 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004189}
4190
4191/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00004192 * xmlSchemaPValAttrNodeQNameValue:
4193 * @ctxt: a schema parser context
4194 * @schema: the schema context
4195 * @ownerDes: the designation of the parent element
4196 * @ownerItem: the parent as a schema object
4197 * @value: the QName value
4198 * @local: the resulting local part if found, the attribute value otherwise
4199 * @uri: the resulting namespace URI if found
4200 *
4201 * Extracts the local name and the URI of a QName value and validates it.
4202 * This one is intended to be used on attribute values that
4203 * should resolve to schema components.
4204 *
4205 * Returns 0, in case the QName is valid, a positive error code
4206 * if not valid and -1 if an internal error occurs.
4207 */
4208static int
4209xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
4210 xmlSchemaPtr schema,
4211 xmlChar **ownerDes,
4212 xmlSchemaTypePtr ownerItem,
4213 xmlAttrPtr attr,
4214 const xmlChar *value,
4215 const xmlChar **uri,
4216 const xmlChar **prefix,
4217 const xmlChar **local)
4218{
4219 const xmlChar *pref;
4220 xmlNsPtr ns;
4221 int len, ret;
4222
4223 *uri = NULL;
4224 *local = NULL;
4225 if (prefix != 0)
4226 *prefix = NULL;
4227 ret = xmlValidateQName(value, 1);
4228 if (ret > 0) {
4229 xmlSchemaPSimpleTypeErr(ctxt,
4230 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4231 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004232 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
4233 "QName", value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004234 NULL, NULL, NULL);
4235 *local = value;
4236 return (ctxt->err);
4237 } else if (ret < 0)
4238 return (-1);
4239
4240 if (!strchr((char *) value, ':')) {
4241 ns = xmlSearchNs(attr->doc, attr->parent, 0);
4242 if (ns)
4243 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
4244 else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
4245 /*
4246 * This one takes care of included schemas with no
4247 * target namespace.
4248 */
4249 *uri = schema->targetNamespace;
4250 }
4251 *local = value;
4252 return (0);
4253 }
4254 /*
4255 * At this point xmlSplitQName3 has to return a local name.
4256 */
4257 *local = xmlSplitQName3(value, &len);
4258 *local = xmlDictLookup(ctxt->dict, *local, -1);
4259 pref = xmlDictLookup(ctxt->dict, value, len);
4260 if (prefix != 0)
4261 *prefix = pref;
4262 ns = xmlSearchNs(attr->doc, attr->parent, pref);
4263 if (ns == NULL) {
4264 xmlSchemaPSimpleTypeErr(ctxt,
4265 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4266 ownerDes, ownerItem, (xmlNodePtr) attr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004267 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), "QName", value,
4268 "The QName value '%s' has no corresponding namespace "
4269 "declaration in scope", value, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004270 return (ctxt->err);
4271 } else {
4272 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
4273 }
4274 return (0);
4275}
4276
4277/**
4278 * xmlSchemaPValAttrNodeQName:
4279 * @ctxt: a schema parser context
4280 * @schema: the schema context
4281 * @ownerDes: the designation of the owner element
4282 * @ownerItem: the owner as a schema object
4283 * @attr: the attribute node
4284 * @local: the resulting local part if found, the attribute value otherwise
4285 * @uri: the resulting namespace URI if found
4286 *
4287 * Extracts and validates the QName of an attribute value.
4288 * This one is intended to be used on attribute values that
4289 * should resolve to schema components.
4290 *
4291 * Returns 0, in case the QName is valid, a positive error code
4292 * if not valid and -1 if an internal error occurs.
4293 */
4294static int
4295xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
4296 xmlSchemaPtr schema,
4297 xmlChar **ownerDes,
4298 xmlSchemaTypePtr ownerItem,
4299 xmlAttrPtr attr,
4300 const xmlChar **uri,
4301 const xmlChar **prefix,
4302 const xmlChar **local)
4303{
4304 const xmlChar *value;
4305
4306 value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4307 return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
4308 ownerDes, ownerItem, attr, value, uri, prefix, local));
4309}
4310
4311/**
4312 * xmlSchemaPValAttrQName:
4313 * @ctxt: a schema parser context
4314 * @schema: the schema context
4315 * @ownerDes: the designation of the parent element
4316 * @ownerItem: the owner as a schema object
4317 * @ownerElem: the parent node of the attribute
4318 * @name: the name of the attribute
4319 * @local: the resulting local part if found, the attribute value otherwise
4320 * @uri: the resulting namespace URI if found
4321 *
4322 * Extracts and validates the QName of an attribute value.
4323 *
4324 * Returns 0, in case the QName is valid, a positive error code
4325 * if not valid and -1 if an internal error occurs.
4326 */
4327static int
4328xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
4329 xmlSchemaPtr schema,
4330 xmlChar **ownerDes,
4331 xmlSchemaTypePtr ownerItem,
4332 xmlNodePtr ownerElem,
4333 const char *name,
4334 const xmlChar **uri,
4335 const xmlChar **prefix,
4336 const xmlChar **local)
4337{
4338 xmlAttrPtr attr;
4339
4340 attr = xmlSchemaGetPropNode(ownerElem, name);
4341 if (attr == NULL) {
4342 *local = NULL;
4343 *uri = NULL;
4344 return (0);
4345 }
4346 return (xmlSchemaPValAttrNodeQName(ctxt, schema,
4347 ownerDes, ownerItem, attr, uri, prefix, local));
4348}
4349
4350/**
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00004351 * xmlSchemaPValAttrID:
4352 * @ctxt: a schema parser context
4353 * @schema: the schema context
4354 * @ownerDes: the designation of the parent element
4355 * @ownerItem: the owner as a schema object
4356 * @ownerElem: the parent node of the attribute
4357 * @name: the name of the attribute
4358 *
4359 * Extracts and validates the ID of an attribute value.
4360 *
4361 * Returns 0, in case the ID is valid, a positive error code
4362 * if not valid and -1 if an internal error occurs.
4363 */
4364static int
4365xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,
4366 xmlChar **ownerDes,
4367 xmlSchemaTypePtr ownerItem,
4368 xmlNodePtr ownerElem,
4369 const xmlChar *name)
4370{
4371 int ret;
4372 xmlChar *value;
4373 xmlAttrPtr attr;
4374
4375 value = xmlGetNoNsProp(ownerElem, name);
4376 if (value == NULL)
4377 return (0);
4378
4379 attr = xmlSchemaGetPropNode(ownerElem, (const char *) name);
4380 if (attr == NULL)
4381 return (-1);
4382
4383 ret = xmlValidateNCName(BAD_CAST value, 1);
4384 if (ret == 0) {
4385 /*
4386 * NOTE: the IDness might have already be declared in the DTD
4387 */
4388 if (attr->atype != XML_ATTRIBUTE_ID) {
4389 xmlIDPtr res;
4390 xmlChar *strip;
4391
4392 /*
4393 * TODO: Use xmlSchemaStrip here; it's not exported at this
4394 * moment.
4395 */
4396 strip = xmlSchemaCollapseString(BAD_CAST value);
4397 if (strip != NULL)
4398 value = strip;
4399 res = xmlAddID(NULL, ownerElem->doc, BAD_CAST value, attr);
4400 if (res == NULL) {
4401 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
4402 xmlSchemaPSimpleTypeErr(ctxt,
4403 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4404 ownerDes, ownerItem, (xmlNodePtr) attr,
4405 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00004406 NULL, NULL, "The ID '%s' is already defined",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00004407 BAD_CAST value, NULL);
4408 } else
4409 attr->atype = XML_ATTRIBUTE_ID;
4410 if (strip != NULL)
4411 xmlFree(strip);
4412 }
4413 } else if (ret > 0) {
4414 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
4415 xmlSchemaPSimpleTypeErr(ctxt,
4416 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4417 ownerDes, ownerItem, (xmlNodePtr) attr,
4418 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
4419 NULL, BAD_CAST value, NULL, NULL, NULL);
4420 }
4421 xmlFree(value);
4422
4423 return (ret);
4424}
4425
4426/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004427 * xmlGetMaxOccurs:
4428 * @ctxt: a schema validation context
4429 * @node: a subtree containing XML Schema informations
4430 *
4431 * Get the maxOccurs property
4432 *
4433 * Returns the default if not found, or the value
4434 */
4435static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004436xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
4437 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004438{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004439 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00004440 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004441 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00004442
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004443 attr = xmlSchemaGetPropNode(node, "maxOccurs");
4444 if (attr == NULL)
4445 return (def);
4446 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00004447
4448 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004449 if (max != UNBOUNDED) {
4450 xmlSchemaPSimpleTypeErr(ctxt,
4451 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4452 /* XML_SCHEMAP_INVALID_MINOCCURS, */
4453 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
4454 val, NULL, NULL, NULL);
4455 return (def);
4456 } else
4457 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00004458 }
4459
4460 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00004461 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004462 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004463 if (*cur == 0) {
4464 xmlSchemaPSimpleTypeErr(ctxt,
4465 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4466 /* XML_SCHEMAP_INVALID_MINOCCURS, */
4467 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
4468 val, NULL, NULL, NULL);
4469 return (def);
4470 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004471 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004472 ret = ret * 10 + (*cur - '0');
4473 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00004474 }
William M. Brack76e95df2003-10-18 16:20:14 +00004475 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004476 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004477 /*
4478 * TODO: Restrict the maximal value to Integer.
4479 */
4480 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
4481 xmlSchemaPSimpleTypeErr(ctxt,
4482 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4483 /* XML_SCHEMAP_INVALID_MINOCCURS, */
4484 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
4485 val, NULL, NULL, NULL);
4486 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00004487 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004488 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004489}
4490
4491/**
4492 * xmlGetMinOccurs:
4493 * @ctxt: a schema validation context
4494 * @node: a subtree containing XML Schema informations
4495 *
4496 * Get the minOccurs property
4497 *
4498 * Returns the default if not found, or the value
4499 */
4500static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004501xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
4502 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004503{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004504 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00004505 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004506 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00004507
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004508 attr = xmlSchemaGetPropNode(node, "minOccurs");
4509 if (attr == NULL)
4510 return (def);
4511 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00004512 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00004513 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004514 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004515 if (*cur == 0) {
4516 xmlSchemaPSimpleTypeErr(ctxt,
4517 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4518 /* XML_SCHEMAP_INVALID_MINOCCURS, */
4519 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
4520 val, NULL, NULL, NULL);
4521 return (def);
4522 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004523 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004524 ret = ret * 10 + (*cur - '0');
4525 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00004526 }
William M. Brack76e95df2003-10-18 16:20:14 +00004527 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004528 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004529 /*
4530 * TODO: Restrict the maximal value to Integer.
4531 */
4532 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
4533 xmlSchemaPSimpleTypeErr(ctxt,
4534 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4535 /* XML_SCHEMAP_INVALID_MINOCCURS, */
4536 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
4537 val, NULL, NULL, NULL);
4538 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00004539 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004540 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004541}
4542
4543/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004544 * xmlSchemaPGetBoolNodeValue:
4545 * @ctxt: a schema validation context
4546 * @ownerDes: owner designation
4547 * @ownerItem: the owner as a schema item
4548 * @node: the node holding the value
4549 *
4550 * Converts a boolean string value into 1 or 0.
4551 *
4552 * Returns 0 or 1.
4553 */
4554static int
4555xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
4556 xmlChar **ownerDes,
4557 xmlSchemaTypePtr ownerItem,
4558 xmlNodePtr node)
4559{
4560 xmlChar *value = NULL;
4561 int res = 0;
4562
4563 value = xmlNodeGetContent(node);
4564 /*
4565 * 3.2.2.1 Lexical representation
4566 * An instance of a datatype that is defined as ·boolean·
4567 * can have the following legal literals {true, false, 1, 0}.
4568 */
4569 if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
4570 res = 1;
4571 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
4572 res = 0;
4573 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
4574 res = 1;
4575 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
4576 res = 0;
4577 else {
4578 xmlSchemaPSimpleTypeErr(ctxt,
4579 XML_SCHEMAP_INVALID_BOOLEAN,
4580 ownerDes, ownerItem, node,
4581 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
4582 "(1 | 0 | true | false)", BAD_CAST value,
4583 NULL, NULL, NULL);
4584 }
4585 if (value != NULL)
4586 xmlFree(value);
4587 return (res);
4588}
4589
4590/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004591 * xmlGetBooleanProp:
4592 * @ctxt: a schema validation context
4593 * @node: a subtree containing XML Schema informations
4594 * @name: the attribute name
4595 * @def: the default value
4596 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00004597 * Evaluate if a boolean property is set
Daniel Veillard4255d502002-04-16 15:50:10 +00004598 *
4599 * Returns the default if not found, 0 if found to be false,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004600 * 1 if found to be true
Daniel Veillard4255d502002-04-16 15:50:10 +00004601 */
4602static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00004603xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
4604 xmlChar **ownerDes,
4605 xmlSchemaTypePtr ownerItem,
4606 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004607 const char *name, int def)
4608{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004609 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00004610
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004611 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004612 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004613 return (def);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004614 /*
4615 * 3.2.2.1 Lexical representation
4616 * An instance of a datatype that is defined as ·boolean·
4617 * can have the following legal literals {true, false, 1, 0}.
4618 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004619 if (xmlStrEqual(val, BAD_CAST "true"))
4620 def = 1;
4621 else if (xmlStrEqual(val, BAD_CAST "false"))
4622 def = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004623 else if (xmlStrEqual(val, BAD_CAST "1"))
4624 def = 1;
4625 else if (xmlStrEqual(val, BAD_CAST "0"))
4626 def = 0;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00004627 else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004628 xmlSchemaPSimpleTypeErr(ctxt,
4629 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00004630 ownerDes, ownerItem,
4631 (xmlNodePtr) xmlSchemaGetPropNode(node, name),
William M. Brack2f2a6632004-08-20 23:09:47 +00004632 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
4633 "(1 | 0 | true | false)", val, NULL, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004634 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004635 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00004636}
4637
4638/************************************************************************
4639 * *
4640 * Shema extraction from an Infoset *
4641 * *
4642 ************************************************************************/
4643static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
4644 ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00004645 xmlNodePtr node,
4646 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004647static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
4648 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00004649 xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00004650 xmlNodePtr node,
4651 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004652static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
4653 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00004654 xmlSchemaPtr schema,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00004655 xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00004656static xmlSchemaTypePtr xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt,
4657 xmlSchemaPtr schema,
4658 xmlNodePtr node);
4659static xmlSchemaTypePtr xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt,
4660 xmlSchemaPtr schema,
4661 xmlNodePtr node);
4662static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
4663 ctxt,
4664 xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00004665 xmlNodePtr node,
4666 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00004667static xmlSchemaAttributeGroupPtr
4668xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00004669 xmlSchemaPtr schema, xmlNodePtr node,
4670 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00004671static xmlSchemaTypePtr xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt,
4672 xmlSchemaPtr schema,
4673 xmlNodePtr node);
4674static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
4675 xmlSchemaPtr schema,
4676 xmlNodePtr node);
Daniel Veillard3646d642004-06-02 19:19:14 +00004677static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004678xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
4679 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00004680
4681/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004682 * xmlSchemaPValAttrNodeValue:
Daniel Veillard01fa6152004-06-29 17:04:39 +00004683 *
4684 * @ctxt: a schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00004685 * @ownerDes: the designation of the parent element
4686 * @ownerItem: the schema object owner if existent
4687 * @attr: the schema attribute node being validated
4688 * @value: the value
4689 * @type: the built-in type to be validated against
Daniel Veillard01fa6152004-06-29 17:04:39 +00004690 *
4691 * Validates a value against the given built-in type.
4692 * This one is intended to be used internally for validation
4693 * of schema attribute values during parsing of the schema.
4694 *
4695 * Returns 0 if the value is valid, a positive error code
4696 * number otherwise and -1 in case of an internal or API error.
4697 */
4698static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00004699xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr ctxt,
4700 xmlChar **ownerDes,
4701 xmlSchemaTypePtr ownerItem,
4702 xmlAttrPtr attr,
4703 const xmlChar *value,
4704 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +00004705{
Daniel Veillard01fa6152004-06-29 17:04:39 +00004706
Daniel Veillardc0826a72004-08-10 14:17:33 +00004707 int ret = 0;
4708
4709 /*
4710 * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
4711 * one is really meant to be used internally, so better not.
4712 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00004713 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00004714 return (-1);
4715 if (type->type != XML_SCHEMA_TYPE_BASIC) {
4716 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004717 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004718 "Internal error: xmlSchemaPValAttrNodeValue, the given "
Daniel Veillardc0826a72004-08-10 14:17:33 +00004719 "type '%s' is not a built-in type.\n",
4720 type->name, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00004721 return (-1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004722 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00004723 switch (type->builtInType) {
4724 case XML_SCHEMAS_NCNAME:
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004725 case XML_SCHEMAS_QNAME:
4726 case XML_SCHEMAS_ANYURI:
4727 case XML_SCHEMAS_TOKEN:
4728 case XML_SCHEMAS_LANGUAGE:
4729 ret = xmlSchemaValPredefTypeNode(type, value, NULL, (xmlNodePtr) attr);
4730 break;
4731
4732 /*
4733 case XML_SCHEMAS_NCNAME:
Daniel Veillard01fa6152004-06-29 17:04:39 +00004734 ret = xmlValidateNCName(value, 1);
4735 break;
4736 case XML_SCHEMAS_QNAME:
Daniel Veillardc0826a72004-08-10 14:17:33 +00004737 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004738 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004739 "Internal error: xmlSchemaPvalueAttrNode, use "
4740 "the function xmlSchemaExtractSchemaQNamePropvalueidated "
4741 "for extracting QName valueues instead.\n",
4742 NULL, NULL);
4743 return (-1);
4744 case XML_SCHEMAS_ANYURI:
4745 if (value != NULL) {
4746 xmlURIPtr uri = xmlParseURI((const char *) value);
4747 if (uri == NULL)
4748 ret = 1;
4749 else
4750 xmlFreeURI(uri);
Daniel Veillard01fa6152004-06-29 17:04:39 +00004751 }
4752 break;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004753 case XML_SCHEMAS_TOKEN: {
4754 const xmlChar *cur = value;
4755
4756 if (IS_BLANK_CH(*cur)) {
4757 ret = 1;
4758 } else while (*cur != 0) {
4759 if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) {
4760 ret = 1;
4761 break;
4762 } else if (*cur == ' ') {
4763 cur++;
4764 if ((*cur == 0) || (*cur == ' ')) {
4765 ret = 1;
4766 break;
4767 }
4768 } else {
4769 cur++;
4770 }
4771 }
4772 }
4773 break;
4774 case XML_SCHEMAS_LANGUAGE:
4775 if (xmlCheckLanguageID(value) != 1)
4776 ret = 1;
4777 break;
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004778 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00004779 default: {
4780 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004781 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004782 "Internal error: xmlSchemaPValAttrNodeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +00004783 "valueidation using the type '%s' is not implemented "
4784 "yet.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +00004785 type->name, NULL);
4786 return (-1);
4787 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004788 }
4789 /*
4790 * TODO: Should we use the S4S error codes instead?
4791 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004792 if (ret < 0) {
4793 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
4794 XML_SCHEMAP_INTERNAL,
4795 "Internal error: xmlSchemaPValAttrNodeValue, "
4796 "failed to validate a schema attribute value.\n",
4797 NULL, NULL);
4798 return (-1);
4799 } else if (ret > 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004800 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
4801 xmlSchemaPSimpleTypeErr(ctxt,
4802 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2,
4803 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004804 type, NULL, value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004805 NULL, NULL, NULL);
4806 return(XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2);
4807 } else {
4808 xmlSchemaPSimpleTypeErr(ctxt,
4809 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
4810 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004811 type, NULL, value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004812 NULL, NULL, NULL);
4813 return(XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
4814 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00004815 }
4816 return (ret);
4817}
4818
4819/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00004820 * xmlSchemaPValAttrNode:
4821 *
4822 * @ctxt: a schema parser context
4823 * @ownerDes: the designation of the parent element
4824 * @ownerItem: the schema object owner if existent
4825 * @attr: the schema attribute node being validated
4826 * @type: the built-in type to be validated against
4827 * @value: the resulting value if any
4828 *
4829 * Extracts and validates a value against the given built-in type.
4830 * This one is intended to be used internally for validation
4831 * of schema attribute values during parsing of the schema.
4832 *
4833 * Returns 0 if the value is valid, a positive error code
4834 * number otherwise and -1 in case of an internal or API error.
4835 */
4836static int
4837xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
4838 xmlChar **ownerDes,
4839 xmlSchemaTypePtr ownerItem,
4840 xmlAttrPtr attr,
4841 xmlSchemaTypePtr type,
4842 const xmlChar **value)
4843{
4844 const xmlChar *val;
4845
4846 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
4847 return (-1);
4848
4849 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4850 if (value != NULL)
4851 *value = val;
4852
4853 return (xmlSchemaPValAttrNodeValue(ctxt, ownerDes, ownerItem, attr,
4854 val, type));
4855}
4856
4857/**
4858 * xmlSchemaPValAttr:
4859 *
4860 * @ctxt: a schema parser context
4861 * @node: the element node of the attribute
4862 * @ownerDes: the designation of the parent element
4863 * @ownerItem: the schema object owner if existent
4864 * @ownerElem: the owner element node
4865 * @name: the name of the schema attribute node
4866 * @type: the built-in type to be validated against
4867 * @value: the resulting value if any
4868 *
4869 * Extracts and validates a value against the given built-in type.
4870 * This one is intended to be used internally for validation
4871 * of schema attribute values during parsing of the schema.
4872 *
4873 * Returns 0 if the value is valid, a positive error code
4874 * number otherwise and -1 in case of an internal or API error.
4875 */
4876static int
4877xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
4878 xmlChar **ownerDes,
4879 xmlSchemaTypePtr ownerItem,
4880 xmlNodePtr ownerElem,
4881 const char *name,
4882 xmlSchemaTypePtr type,
4883 const xmlChar **value)
4884{
4885 xmlAttrPtr attr;
4886
4887 if ((ctxt == NULL) || (type == NULL)) {
4888 if (value != NULL)
4889 *value = NULL;
4890 return (-1);
4891 }
4892 if (type->type != XML_SCHEMA_TYPE_BASIC) {
4893 if (value != NULL)
4894 *value = NULL;
4895 xmlSchemaPErr(ctxt, ownerElem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004896 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004897 "Internal error: xmlSchemaPValAttr, the given "
4898 "type '%s' is not a built-in type.\n",
4899 type->name, NULL);
4900 return (-1);
4901 }
4902 attr = xmlSchemaGetPropNode(ownerElem, name);
4903 if (attr == NULL) {
4904 if (value != NULL)
4905 *value = NULL;
4906 return (0);
4907 }
4908 return (xmlSchemaPValAttrNode(ctxt, ownerDes, ownerItem, attr,
4909 type, value));
4910}
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00004911
4912static int
4913xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,
4914 xmlSchemaPtr schema,
4915 xmlNodePtr node,
4916 xmlSchemaTypePtr item,
4917 const xmlChar *namespaceName)
4918{
4919 if (xmlStrEqual(schema->targetNamespace, namespaceName))
4920 return (1);
4921 if (pctxt->localImports != NULL) {
4922 int i;
4923 for (i = 0; i < pctxt->nbLocalImports; i++)
4924 if (xmlStrEqual(namespaceName, pctxt->localImports[i]))
4925 return (1);
4926 }
4927 if (namespaceName == NULL)
4928 xmlSchemaPCustomErr(pctxt, XML_SCHEMAP_SRC_RESOLVE,
4929 NULL, item, node, "References from this schema to components in no "
4930 "namespace are not valid, since not indicated by an import "
4931 "statement", NULL);
4932 else
4933 xmlSchemaPCustomErr(pctxt, XML_SCHEMAP_SRC_RESOLVE,
4934 NULL, item, node, "References from this schema to components in the "
4935 "namespace '%s' are not valid, since not indicated by an import "
4936 "statement", namespaceName);
4937 return (0);
4938}
4939
Daniel Veillardc0826a72004-08-10 14:17:33 +00004940/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004941 * xmlSchemaParseAttrDecls:
4942 * @ctxt: a schema validation context
4943 * @schema: the schema being built
4944 * @node: a subtree containing XML Schema informations
4945 * @type: the hosting type
4946 *
4947 * parse a XML schema attrDecls declaration corresponding to
4948 * <!ENTITY % attrDecls
4949 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
4950 */
4951static xmlNodePtr
4952xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4953 xmlNodePtr child, xmlSchemaTypePtr type)
4954{
4955 xmlSchemaAttributePtr lastattr, attr;
4956
4957 lastattr = NULL;
4958 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004959 (IS_SCHEMA(child, "attributeGroup"))) {
4960 attr = NULL;
4961 if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00004962 attr = xmlSchemaParseAttribute(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004963 } else if (IS_SCHEMA(child, "attributeGroup")) {
4964 attr = (xmlSchemaAttributePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00004965 xmlSchemaParseAttributeGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004966 }
4967 if (attr != NULL) {
4968 if (lastattr == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00004969 if (type->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
4970 ((xmlSchemaAttributeGroupPtr) type)->attributes = attr;
4971 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004972 type->attributes = attr;
4973 lastattr = attr;
4974 } else {
4975 lastattr->next = attr;
4976 lastattr = attr;
4977 }
4978 }
4979 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004980 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004981 return (child);
Daniel Veillard4255d502002-04-16 15:50:10 +00004982}
4983
4984/**
4985 * xmlSchemaParseAnnotation:
4986 * @ctxt: a schema validation context
4987 * @schema: the schema being built
4988 * @node: a subtree containing XML Schema informations
4989 *
4990 * parse a XML schema Attrribute declaration
4991 * *WARNING* this interface is highly subject to change
4992 *
William M. Bracke7091952004-05-11 15:09:58 +00004993 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00004994 * 1 in case of success.
4995 */
4996static xmlSchemaAnnotPtr
4997xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4998 xmlNodePtr node)
4999{
5000 xmlSchemaAnnotPtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005001 xmlNodePtr child = NULL;
5002 xmlAttrPtr attr;
5003 int barked = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00005004
Daniel Veillardc0826a72004-08-10 14:17:33 +00005005 /*
5006 * INFO: S4S completed.
5007 */
5008 /*
5009 * id = ID
5010 * {any attributes with non-schema namespace . . .}>
5011 * Content: (appinfo | documentation)*
5012 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005013 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5014 return (NULL);
5015 ret = xmlSchemaNewAnnot(ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005016 attr = node->properties;
5017 while (attr != NULL) {
5018 if (((attr->ns == NULL) &&
5019 (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
5020 ((attr->ns != NULL) &&
5021 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
5022
5023 xmlSchemaPIllegalAttrErr(ctxt,
5024 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5025 NULL, NULL, attr);
5026 }
5027 attr = attr->next;
5028 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005029 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00005030 /*
5031 * And now for the children...
5032 */
5033 child = node->children;
5034 while (child != NULL) {
5035 if (IS_SCHEMA(child, "appinfo")) {
5036 /* TODO: make available the content of "appinfo". */
5037 /*
5038 * source = anyURI
5039 * {any attributes with non-schema namespace . . .}>
5040 * Content: ({any})*
5041 */
5042 attr = child->properties;
5043 while (attr != NULL) {
5044 if (((attr->ns == NULL) &&
5045 (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
5046 ((attr->ns != NULL) &&
5047 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005048
Daniel Veillardc0826a72004-08-10 14:17:33 +00005049 xmlSchemaPIllegalAttrErr(ctxt,
5050 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5051 NULL, NULL, attr);
5052 }
5053 attr = attr->next;
5054 }
5055 xmlSchemaPValAttr(ctxt, NULL, NULL, child, "source",
5056 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
5057 child = child->next;
5058 } else if (IS_SCHEMA(child, "documentation")) {
5059 /* TODO: make available the content of "documentation". */
5060 /*
5061 * source = anyURI
5062 * {any attributes with non-schema namespace . . .}>
5063 * Content: ({any})*
5064 */
5065 attr = child->properties;
5066 while (attr != NULL) {
5067 if (attr->ns == NULL) {
5068 if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
5069 xmlSchemaPIllegalAttrErr(ctxt,
5070 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5071 NULL, NULL, attr);
5072 }
5073 } else {
5074 if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
5075 (xmlStrEqual(attr->name, BAD_CAST "lang") &&
5076 (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
5077
5078 xmlSchemaPIllegalAttrErr(ctxt,
5079 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5080 NULL, NULL, attr);
5081 }
5082 }
5083 attr = attr->next;
5084 }
5085 /*
5086 * Attribute "xml:lang".
5087 */
5088 attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
5089 if (attr != NULL)
5090 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
5091 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
5092 child = child->next;
5093 } else {
5094 if (!barked)
5095 xmlSchemaPContentErr(ctxt,
5096 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5097 NULL, NULL, node, child, NULL, "(appinfo | documentation)*");
5098 barked = 1;
5099 child = child->next;
5100 }
5101 }
5102
Daniel Veillard4255d502002-04-16 15:50:10 +00005103 return (ret);
5104}
5105
5106/**
5107 * xmlSchemaParseFacet:
5108 * @ctxt: a schema validation context
5109 * @schema: the schema being built
5110 * @node: a subtree containing XML Schema informations
5111 *
5112 * parse a XML schema Facet declaration
5113 * *WARNING* this interface is highly subject to change
5114 *
5115 * Returns the new type structure or NULL in case of error
5116 */
5117static xmlSchemaFacetPtr
5118xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005119 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005120{
5121 xmlSchemaFacetPtr facet;
5122 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005123 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00005124
5125 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5126 return (NULL);
5127
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00005128 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005129 if (facet == NULL) {
5130 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
5131 return (NULL);
5132 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005133 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005134 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00005135 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005136 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
5137 "Facet %s has no value\n", node->name, NULL);
5138 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00005139 return (NULL);
5140 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005141 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005142 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005143 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005144 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005145 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005146 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005147 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005148 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005149 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005150 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005151 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005152 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005153 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005154 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005155 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005156 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005157 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005158 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005159 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005160 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005161 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005162 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
5163 } else if (IS_SCHEMA(node, "minLength")) {
5164 facet->type = XML_SCHEMA_FACET_MINLENGTH;
5165 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005166 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
5167 "Unknown facet type %s\n", node->name, NULL);
5168 xmlSchemaFreeFacet(facet);
5169 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005170 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005171 xmlSchemaPValAttrID(ctxt, NULL,
5172 (xmlSchemaTypePtr) facet, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00005173 facet->value = value;
Daniel Veillard01fa6152004-06-29 17:04:39 +00005174 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
5175 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
5176 const xmlChar *fixed;
5177
5178 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
5179 if (fixed != NULL) {
5180 if (xmlStrEqual(fixed, BAD_CAST "true"))
5181 facet->fixed = 1;
5182 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005183 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005184 child = node->children;
5185
5186 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005187 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5188 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005189 }
5190 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005191 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
5192 "Facet %s has unexpected child content\n",
5193 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005194 }
5195 return (facet);
5196}
5197
5198/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005199 * xmlSchemaParseWildcardNs:
5200 * @ctxt: a schema parser context
5201 * @wildc: the wildcard, already created
5202 * @node: a subtree containing XML Schema informations
5203 *
5204 * Parses the attribute "processContents" and "namespace"
5205 * of a xsd:anyAttribute and xsd:any.
5206 * *WARNING* this interface is highly subject to change
5207 *
5208 * Returns 0 if everything goes fine, a positive error code
5209 * if something is not valid and -1 if an internal error occurs.
5210 */
5211static int
5212xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
5213 xmlSchemaPtr schema,
5214 xmlSchemaWildcardPtr wildc,
5215 xmlNodePtr node)
5216{
5217 const xmlChar *pc, *ns, *dictnsItem;
5218 int ret = 0;
5219 xmlChar *nsItem;
5220 xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
5221 xmlAttrPtr attr;
5222
5223 pc = xmlSchemaGetProp(ctxt, node, "processContents");
5224 if ((pc == NULL)
5225 || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
5226 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
5227 } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
5228 wildc->processContents = XML_SCHEMAS_ANY_SKIP;
5229 } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
5230 wildc->processContents = XML_SCHEMAS_ANY_LAX;
5231 } else {
5232 xmlSchemaPSimpleTypeErr(ctxt,
5233 XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD,
5234 NULL, NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00005235 NULL, "(strict | skip | lax)", pc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005236 NULL, NULL, NULL);
5237 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
5238 ret = XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD;
5239 }
5240 /*
5241 * Build the namespace constraints.
5242 */
5243 attr = xmlSchemaGetPropNode(node, "namespace");
5244 ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5245 if ((ns == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
5246 wildc->any = 1;
5247 else if (xmlStrEqual(ns, BAD_CAST "##other")) {
5248 wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
5249 if (wildc->negNsSet == NULL) {
5250 return (-1);
5251 }
5252 wildc->negNsSet->value = schema->targetNamespace;
5253 } else {
5254 const xmlChar *end, *cur;
5255
5256 cur = ns;
5257 do {
5258 while (IS_BLANK_CH(*cur))
5259 cur++;
5260 end = cur;
5261 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
5262 end++;
5263 if (end == cur)
5264 break;
5265 nsItem = xmlStrndup(cur, end - cur);
5266 if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
5267 (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
5268 xmlSchemaPSimpleTypeErr(ctxt,
5269 XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
5270 NULL, NULL, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005271 NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005272 "((##any | ##other) | List of (anyURI | "
5273 "(##targetNamespace | ##local)))",
5274 nsItem, NULL, NULL, NULL);
5275 ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
5276 } else {
5277 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
5278 dictnsItem = schema->targetNamespace;
5279 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
5280 dictnsItem = NULL;
5281 } else {
5282 /*
5283 * Validate the item (anyURI).
5284 */
5285 xmlSchemaPValAttrNodeValue(ctxt, NULL, NULL, attr,
5286 nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
5287 dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
5288 }
5289 /*
5290 * Avoid dublicate namespaces.
5291 */
5292 tmp = wildc->nsSet;
5293 while (tmp != NULL) {
5294 if (dictnsItem == tmp->value)
5295 break;
5296 tmp = tmp->next;
5297 }
5298 if (tmp == NULL) {
5299 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
5300 if (tmp == NULL) {
5301 xmlFree(nsItem);
5302 return (-1);
5303 }
5304 tmp->value = dictnsItem;
5305 tmp->next = NULL;
5306 if (wildc->nsSet == NULL)
5307 wildc->nsSet = tmp;
5308 else
5309 lastNs->next = tmp;
5310 lastNs = tmp;
5311 }
5312
5313 }
5314 xmlFree(nsItem);
5315 cur = end;
5316 } while (*cur != 0);
5317 }
5318 return (ret);
5319}
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005320
5321static int
5322xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
5323 xmlSchemaTypePtr item,
5324 xmlNodePtr node,
5325 int minOccurs,
5326 int maxOccurs) {
5327
5328 if (maxOccurs != UNBOUNDED) {
5329 /*
5330 * TODO: Maby we should better not create the particle,
5331 * if min/max is invalid, since it could confuse the build of the
5332 * content model.
5333 */
5334 /*
5335 * 3.9.6 Schema Component Constraint: Particle Correct
5336 *
5337 */
5338 if (maxOccurs < 1) {
5339 /*
5340 * 2.2 {max occurs} must be greater than or equal to 1.
5341 */
5342 xmlSchemaPCustomAttrErr(ctxt,
5343 XML_SCHEMAP_P_PROPS_CORRECT_2_2,
5344 NULL, item, xmlSchemaGetPropNode(node, "maxOccurs"),
5345 "The value must be greater than or equal to 1");
5346 return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
5347 } else if (minOccurs > maxOccurs) {
5348 /*
5349 * 2.1 {min occurs} must not be greater than {max occurs}.
5350 */
5351 xmlSchemaPCustomAttrErr(ctxt,
5352 XML_SCHEMAP_P_PROPS_CORRECT_2_1,
5353 NULL, item, xmlSchemaGetPropNode(node, "minOccurs"),
5354 "The value must not be greater than the value of 'maxOccurs'");
5355 return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
5356 }
5357 }
5358 return (0);
5359}
5360
Daniel Veillardc0826a72004-08-10 14:17:33 +00005361/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005362 * xmlSchemaParseAny:
5363 * @ctxt: a schema validation context
5364 * @schema: the schema being built
5365 * @node: a subtree containing XML Schema informations
5366 *
5367 * parse a XML schema Any declaration
5368 * *WARNING* this interface is highly subject to change
5369 *
5370 * Returns the new type structure or NULL in case of error
5371 */
5372static xmlSchemaTypePtr
5373xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5374 xmlNodePtr node)
5375{
5376 xmlSchemaTypePtr type;
5377 xmlNodePtr child = NULL;
5378 xmlChar name[30];
Daniel Veillardc0826a72004-08-10 14:17:33 +00005379 xmlSchemaWildcardPtr wildc;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005380 int minOccurs, maxOccurs;
Daniel Veillard4255d502002-04-16 15:50:10 +00005381
5382 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5383 return (NULL);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005384 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
5385 "(nonNegativeInteger | unbounded)");
5386 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
5387 "nonNegativeInteger");
5388 if ((minOccurs == 0) && (maxOccurs == 0))
5389 return (NULL);
5390
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005391 snprintf((char *) name, 30, "#any%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00005392 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005393 if (type == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005394 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005395 type->node = node;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005396 type->type = XML_SCHEMA_TYPE_ANY;
5397
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005398 /*
5399 * TODO: Use a particle component here.
5400 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00005401 wildc = xmlSchemaAddWildcard(ctxt);
5402 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005403 * Check min/max sanity.
5404 */
5405 type->maxOccurs = maxOccurs;
5406 type->minOccurs = minOccurs;
5407 xmlSchemaPCheckParticleCorrect_2(ctxt, type,
5408 node, type->minOccurs, type->maxOccurs);
5409 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005410 * This is not nice, since it is won't be used as a attribute wildcard,
5411 * but better than adding a field to the structure.
5412 */
5413 type->attributeWildcard = wildc;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005414 xmlSchemaParseWildcardNs(ctxt, schema, wildc, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005415 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00005416 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005417 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5418 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005419 }
5420 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005421 xmlSchemaPErr2(ctxt, node, child,
5422 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
5423 "Sequence %s has unexpected content\n", type->name,
5424 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005425 }
5426
5427 return (type);
5428}
5429
5430/**
5431 * xmlSchemaParseNotation:
5432 * @ctxt: a schema validation context
5433 * @schema: the schema being built
5434 * @node: a subtree containing XML Schema informations
5435 *
5436 * parse a XML schema Notation declaration
5437 *
5438 * Returns the new structure or NULL in case of error
5439 */
5440static xmlSchemaNotationPtr
5441xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005442 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005443{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005444 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00005445 xmlSchemaNotationPtr ret;
5446 xmlNodePtr child = NULL;
5447
5448 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5449 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005450 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00005451 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005452 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
5453 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005454 return (NULL);
5455 }
5456 ret = xmlSchemaAddNotation(ctxt, schema, name);
5457 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005458 return (NULL);
5459 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005460 ret->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00005461
5462 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
5463 node, BAD_CAST "id");
5464
5465 if (IS_SCHEMA(child, "annotation")) {
5466 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5467 child = child->next;
5468 }
5469
Daniel Veillard4255d502002-04-16 15:50:10 +00005470 child = node->children;
5471 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005472 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5473 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005474 }
5475 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005476 xmlSchemaPErr2(ctxt, node, child,
5477 XML_SCHEMAP_UNKNOWN_NOTATION_CHILD,
5478 "notation %s has unexpected content\n", name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005479 }
5480
5481 return (ret);
5482}
5483
5484/**
5485 * xmlSchemaParseAnyAttribute:
5486 * @ctxt: a schema validation context
5487 * @schema: the schema being built
5488 * @node: a subtree containing XML Schema informations
5489 *
5490 * parse a XML schema AnyAttrribute declaration
5491 * *WARNING* this interface is highly subject to change
5492 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005493 * Returns a wildcard or NULL.
Daniel Veillard4255d502002-04-16 15:50:10 +00005494 */
Daniel Veillard3646d642004-06-02 19:19:14 +00005495static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005496xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
5497 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005498{
Daniel Veillard3646d642004-06-02 19:19:14 +00005499 xmlSchemaWildcardPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00005500 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005501 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005502
5503 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5504 return (NULL);
5505
Daniel Veillard3646d642004-06-02 19:19:14 +00005506 ret = xmlSchemaAddWildcard(ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00005507 if (ret == NULL) {
5508 return (NULL);
5509 }
William M. Bracke7091952004-05-11 15:09:58 +00005510 ret->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005511 /*
5512 * Check for illegal attributes.
5513 */
5514 attr = node->properties;
5515 while (attr != NULL) {
5516 if (attr->ns == NULL) {
5517 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5518 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
5519 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
5520 xmlSchemaPIllegalAttrErr(ctxt,
5521 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5522 NULL, NULL, attr);
5523 }
5524 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5525 xmlSchemaPIllegalAttrErr(ctxt,
5526 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5527 NULL, NULL, attr);
5528 }
5529 attr = attr->next;
5530 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005531 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
5532 node, BAD_CAST "id");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005533 /*
5534 * Parse the namespace list.
5535 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00005536 if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0) {
5537 xmlSchemaFreeWildcard(ret);
5538 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005539 }
5540 /*
5541 * And now for the children...
5542 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005543 child = node->children;
5544 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005545 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5546 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005547 }
5548 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005549 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005550 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5551 NULL, NULL, node, child,
5552 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005553 }
5554
5555 return (ret);
5556}
5557
5558
5559/**
5560 * xmlSchemaParseAttribute:
5561 * @ctxt: a schema validation context
5562 * @schema: the schema being built
5563 * @node: a subtree containing XML Schema informations
5564 *
5565 * parse a XML schema Attrribute declaration
5566 * *WARNING* this interface is highly subject to change
5567 *
William M. Bracke7091952004-05-11 15:09:58 +00005568 * Returns the attribute declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00005569 */
5570static xmlSchemaAttributePtr
5571xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00005572 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005573{
Daniel Veillardc0826a72004-08-10 14:17:33 +00005574 const xmlChar *name, *attrValue;
5575 xmlChar *repName = NULL; /* The reported designation. */
Daniel Veillard4255d502002-04-16 15:50:10 +00005576 xmlSchemaAttributePtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005577 xmlNodePtr child = NULL;
5578 xmlAttrPtr attr, nameAttr;
5579 int isRef = 0;
William M. Bracke7091952004-05-11 15:09:58 +00005580
5581 /*
5582 * Note that the w3c spec assumes the schema to be validated with schema
5583 * for schemas beforehand.
5584 *
5585 * 3.2.3 Constraints on XML Representations of Attribute Declarations
William M. Bracke7091952004-05-11 15:09:58 +00005586 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005587
5588 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5589 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005590 attr = xmlSchemaGetPropNode(node, "ref");
5591 nameAttr = xmlSchemaGetPropNode(node, "name");
5592
5593 if ((attr == NULL) && (nameAttr == NULL)) {
5594 /*
5595 * 3.2.3 : 3.1
5596 * One of ref or name must be present, but not both
5597 */
5598 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
5599 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, node, NULL,
5600 "One of the attributes 'ref' or 'name' must be present");
5601 return (NULL);
5602 }
5603 if ((topLevel) || (attr == NULL)) {
5604 if (nameAttr == NULL) {
5605 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
5606 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, node,
5607 "name", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005608 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005609 }
5610 } else
5611 isRef = 1;
5612
5613 if (isRef) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005614 char buf[50];
Daniel Veillardc0826a72004-08-10 14:17:33 +00005615 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix = NULL;
5616
5617 /*
5618 * Parse as attribute reference.
5619 */
5620 if (xmlSchemaPValAttrNodeQName(ctxt, schema,
5621 (xmlChar **) &xmlSchemaElemDesAttrRef, NULL, attr, &refNs,
5622 &refPrefix, &ref) != 0) {
5623 return (NULL);
5624 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005625 snprintf(buf, 49, "#aRef%d", ctxt->counter++ + 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005626 name = (const xmlChar *) buf;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005627 ret = xmlSchemaAddAttribute(ctxt, schema, name, NULL, node, 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005628 if (ret == NULL) {
5629 if (repName != NULL)
5630 xmlFree(repName);
5631 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005632 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005633 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
5634 ret->node = node;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005635 ret->refNs = refNs;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005636 ret->refPrefix = refPrefix;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005637 ret->ref = ref;
5638 xmlSchemaCheckReference(ctxt, schema, node, (xmlSchemaTypePtr) ret, refNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005639 /*
5640 xmlSchemaFormatTypeRep(&repName, (xmlSchemaTypePtr) ret, NULL, NULL);
5641 */
5642 if (nameAttr != NULL)
5643 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
5644 &repName, (xmlSchemaTypePtr) ret, nameAttr,
5645 "ref", "name");
5646 /*
5647 * Check for illegal attributes.
5648 */
5649 attr = node->properties;
5650 while (attr != NULL) {
5651 if (attr->ns == NULL) {
5652 if (xmlStrEqual(attr->name, BAD_CAST "type") ||
5653 xmlStrEqual(attr->name, BAD_CAST "form")) {
5654 /*
5655 * 3.2.3 : 3.2
5656 * If ref is present, then all of <simpleType>,
5657 * form and type must be absent.
5658 */
5659 xmlSchemaPIllegalAttrErr(ctxt,
5660 XML_SCHEMAP_SRC_ATTRIBUTE_3_2, &repName,
5661 (xmlSchemaTypePtr) ret, attr);
5662 } else if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
5663 (!xmlStrEqual(attr->name, BAD_CAST "use")) &&
5664 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5665 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
5666 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
5667 (!xmlStrEqual(attr->name, BAD_CAST "default"))) {
5668 xmlSchemaPIllegalAttrErr(ctxt,
5669 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5670 &repName, (xmlSchemaTypePtr) ret, attr);
5671 }
5672 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5673 xmlSchemaPIllegalAttrErr(ctxt,
5674 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5675 &repName, (xmlSchemaTypePtr) ret, attr);
5676 }
5677 attr = attr->next;
5678 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005679 } else {
William M. Bracke7091952004-05-11 15:09:58 +00005680 const xmlChar *ns = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005681
5682 /*
5683 * Parse as attribute declaration.
5684 */
5685 if (xmlSchemaPValAttrNode(ctxt,
5686 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, nameAttr,
5687 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
5688 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005689 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005690 /*
5691 xmlSchemaFormatTypeRep(&repName, NULL, xmlSchemaElemDesAttrDecl, name);
5692 */
5693 /*
5694 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
5695 */
5696 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
5697 xmlSchemaPSimpleTypeErr(ctxt,
5698 XML_SCHEMAP_NO_XMLNS,
5699 &repName, NULL, (xmlNodePtr) nameAttr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005700 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), "NCName", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005701 "The value must not match 'xmlns'",
5702 NULL, NULL);
5703 if (repName != NULL)
5704 xmlFree(repName);
5705 return (NULL);
5706 }
5707 /*
5708 * Evaluate the target namespace
5709 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005710 if (topLevel) {
5711 ns = schema->targetNamespace;
5712 } else {
5713 attr = xmlSchemaGetPropNode(node, "form");
5714 if (attr != NULL) {
5715 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5716 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
5717 ns = schema->targetNamespace;
5718 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
5719 xmlSchemaPSimpleTypeErr(ctxt,
5720 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5721 &repName, NULL, (xmlNodePtr) attr,
5722 NULL, "(qualified | unqualified)",
5723 attrValue, NULL, NULL, NULL);
5724 }
5725 } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
5726 ns = schema->targetNamespace;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005727 }
5728 ret = xmlSchemaAddAttribute(ctxt, schema, name, ns, node, topLevel);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005729 if (ret == NULL) {
5730 if (repName != NULL)
5731 xmlFree(repName);
Daniel Veillard3646d642004-06-02 19:19:14 +00005732 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005733 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005734 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005735 ret->node = node;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005736 if (topLevel)
5737 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
5738 /*
5739 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
5740 */
5741 if (xmlStrEqual(ret->targetNamespace, xmlSchemaInstanceNs)) {
5742 xmlSchemaPCustomErr(ctxt,
5743 XML_SCHEMAP_NO_XSI,
5744 &repName, (xmlSchemaTypePtr) ret, node,
5745 "The target namespace must not match '%s'",
5746 xmlSchemaInstanceNs);
5747 }
5748 /*
5749 * Check for illegal attributes.
5750 */
5751 attr = node->properties;
5752 while (attr != NULL) {
5753 if (attr->ns == NULL) {
5754 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5755 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
5756 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
5757 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
5758 (!xmlStrEqual(attr->name, BAD_CAST "type"))) {
5759 if ((topLevel) ||
5760 ((!xmlStrEqual(attr->name, BAD_CAST "form")) &&
5761 (!xmlStrEqual(attr->name, BAD_CAST "use")))) {
5762 xmlSchemaPIllegalAttrErr(ctxt,
5763 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5764 &repName, (xmlSchemaTypePtr) ret, attr);
5765 }
5766 }
5767 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5768 xmlSchemaPIllegalAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5769 &repName, (xmlSchemaTypePtr) ret, attr);
5770 }
5771 attr = attr->next;
5772 }
5773 xmlSchemaPValAttrQName(ctxt, schema, &repName, (xmlSchemaTypePtr) ret,
5774 node, "type", &ret->typeNs, NULL, &ret->typeName);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005775 }
5776 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
5777 node, BAD_CAST "id");
William M. Bracke7091952004-05-11 15:09:58 +00005778 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005779 * Attribute "fixed".
William M. Bracke7091952004-05-11 15:09:58 +00005780 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00005781 ret->defValue = xmlSchemaGetProp(ctxt, node, "fixed");
5782 if (ret->defValue != NULL)
5783 ret->flags |= XML_SCHEMAS_ATTR_FIXED;
5784 /*
5785 * Attribute "default".
5786 */
5787 attr = xmlSchemaGetPropNode(node, "default");
5788 if (attr != NULL) {
5789 /*
5790 * 3.2.3 : 1
5791 * default and fixed must not both be present.
5792 */
5793 if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
5794 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
5795 &repName, (xmlSchemaTypePtr) ret, attr, "default", "fixed");
5796 } else
5797 ret->defValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5798 }
5799 if (topLevel == 0) {
5800 /*
5801 * Attribute "use".
5802 */
5803 attr = xmlSchemaGetPropNode(node, "use");
5804 if (attr != NULL) {
5805 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5806 if (xmlStrEqual(attrValue, BAD_CAST "optional"))
5807 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
5808 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
5809 ret->occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
5810 else if (xmlStrEqual(attrValue, BAD_CAST "required"))
5811 ret->occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
5812 else
5813 xmlSchemaPSimpleTypeErr(ctxt,
5814 XML_SCHEMAP_INVALID_ATTR_USE,
5815 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005816 NULL, "(optional | prohibited | required)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00005817 attrValue, NULL, NULL, NULL);
5818 } else
5819 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
5820 /*
5821 * 3.2.3 : 2
5822 * If default and use are both present, use must have
5823 * the actual value optional.
5824 */
5825 if ((ret->occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
5826 (ret->defValue != NULL) &&
5827 ((ret->flags & XML_SCHEMAS_ATTR_FIXED) == 0)) {
5828 xmlSchemaPSimpleTypeErr(ctxt,
5829 XML_SCHEMAP_SRC_ATTRIBUTE_2,
5830 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005831 NULL, "(optional | prohibited | required)", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005832 "The value must be 'optional' if the attribute "
5833 "'default' is present as well", NULL, NULL);
5834 }
5835 }
5836 /*
5837 * And now for the children...
5838 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005839 child = node->children;
5840 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005841 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5842 child = child->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005843 }
5844 if (isRef) {
5845 if (child != NULL) {
5846 if (IS_SCHEMA(child, "simpleType"))
5847 /*
5848 * 3.2.3 : 3.2
5849 * If ref is present, then all of <simpleType>,
5850 * form and type must be absent.
5851 */
5852 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
5853 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
5854 "(annotation?)");
5855 else
5856 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5857 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
5858 "(annotation?)");
5859 }
5860 } else {
5861 if (IS_SCHEMA(child, "simpleType")) {
5862 if (ret->typeName != NULL) {
5863 /*
5864 * 3.2.3 : 4
5865 * type and <simpleType> must not both be present.
5866 */
5867 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
5868 &repName, (xmlSchemaTypePtr) ret, node, child,
5869 "The attribute 'type' and the <simpleType> child "
5870 "are mutually exclusive", NULL);
5871 } else
5872 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
5873 child = child->next;
5874 }
5875 if (child != NULL)
5876 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5877 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
5878 "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005879 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005880 /*
5881 * Cleanup.
5882 */
5883 if (repName != NULL)
5884 xmlFree(repName);
Daniel Veillard4255d502002-04-16 15:50:10 +00005885 return (ret);
5886}
5887
5888/**
5889 * xmlSchemaParseAttributeGroup:
5890 * @ctxt: a schema validation context
5891 * @schema: the schema being built
5892 * @node: a subtree containing XML Schema informations
5893 *
5894 * parse a XML schema Attribute Group declaration
5895 * *WARNING* this interface is highly subject to change
5896 *
5897 * Returns the attribute group or NULL in case of error.
5898 */
5899static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005900xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00005901 xmlSchemaPtr schema, xmlNodePtr node,
5902 int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005903{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005904 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00005905 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00005906 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005907 const xmlChar *oldcontainer;
5908 xmlAttrPtr attr, nameAttr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005909
5910 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5911 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005912
5913 nameAttr = xmlSchemaGetPropNode(node, "name");
5914 attr = xmlSchemaGetPropNode(node, "ref");
5915 if ((topLevel) || (attr == NULL)) {
5916 /*
5917 * Parse as an attribute group definition.
5918 * Note that those are allowed at top level only.
5919 */
5920 if (nameAttr == NULL) {
5921 xmlSchemaPMissingAttrErr(ctxt,
5922 XML_SCHEMAP_S4S_ATTR_MISSING,
5923 NULL, NULL, node, "name", NULL);
5924 return (NULL);
5925 }
5926 name = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) nameAttr);
5927 /*
5928 * The name is crucial, exit if invalid.
5929 */
5930 if (xmlSchemaPValAttrNode(ctxt,
5931 NULL, NULL, nameAttr,
5932 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
5933 return (NULL);
5934 }
5935 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
5936 if (ret == NULL)
5937 return (NULL);
5938 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
5939 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
5940 ret->node = node;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005941 ret->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005942 } else {
5943 char buf[50];
5944 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix;
5945
5946 /*
5947 * Parse as an attribute group definition reference.
5948 */
5949 if (attr == NULL) {
5950 xmlSchemaPMissingAttrErr(ctxt,
5951 XML_SCHEMAP_S4S_ATTR_MISSING,
5952 NULL, NULL, node, "ref", NULL);
5953 }
5954 xmlSchemaPValAttrNodeQName(ctxt, schema,
5955 NULL, NULL, attr, &refNs, &refPrefix, &ref);
5956
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005957 snprintf(buf, 49, "#agRef%d", ctxt->counter++ + 1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005958 name = (const xmlChar *) buf;
5959 if (name == NULL) {
5960 xmlSchemaPErrMemory(ctxt, "creating internal name for an "
5961 "attribute group definition reference", node);
5962 return (NULL);
5963 }
5964 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
5965 if (ret == NULL)
5966 return (NULL);
5967 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
5968 ret->ref = ref;
5969 ret->refNs = refNs;
5970 /* TODO: Is @refPrefix currently used? */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005971 ret->refPrefix = refPrefix;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005972 ret->node = node;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005973 xmlSchemaCheckReference(ctxt, schema, node, (xmlSchemaTypePtr) ret, refNs);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005974 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005975 /*
5976 * Check for illegal attributes.
5977 */
5978 attr = node->properties;
5979 while (attr != NULL) {
5980 if (attr->ns == NULL) {
5981 if ((((topLevel == 0) && (!xmlStrEqual(attr->name, BAD_CAST "ref"))) ||
5982 (topLevel && (!xmlStrEqual(attr->name, BAD_CAST "name")))) &&
5983 (!xmlStrEqual(attr->name, BAD_CAST "id")))
5984 {
5985 xmlSchemaPIllegalAttrErr(ctxt,
5986 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5987 NULL, NULL, attr);
5988 }
5989 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5990 xmlSchemaPIllegalAttrErr(ctxt,
5991 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5992 NULL, NULL, attr);
5993 }
5994 attr = attr->next;
5995 }
5996 /* TODO: Validate "id" ? */
5997 /*
5998 * And now for the children...
5999 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006000 oldcontainer = ctxt->container;
Daniel Veillard4255d502002-04-16 15:50:10 +00006001 ctxt->container = name;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006002 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00006003 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006004 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6005 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006006 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006007 if (topLevel) {
6008 child = xmlSchemaParseAttrDecls(ctxt, schema, child, (xmlSchemaTypePtr) ret);
6009 if (IS_SCHEMA(child, "anyAttribute")) {
6010 ret->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
6011 child = child->next;
6012 }
6013 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006014 if (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006015 xmlSchemaPContentErr(ctxt,
6016 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6017 NULL, NULL, node, child, NULL,
6018 "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006019 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006020 ctxt->container = oldcontainer;
6021 return (ret);
6022}
6023
6024/**
William M. Brack2f2a6632004-08-20 23:09:47 +00006025 * xmlSchemaPValAttrFormDefault:
6026 * @value: the value
6027 * @flags: the flags to be modified
6028 * @flagQualified: the specific flag for "qualified"
6029 *
6030 * Returns 0 if the value is valid, 1 otherwise.
6031 */
6032static int
6033xmlSchemaPValAttrFormDefault(const xmlChar *value,
6034 int *flags,
6035 int flagQualified)
6036{
6037 if (xmlStrEqual(value, BAD_CAST "qualified")) {
6038 if ((*flags & flagQualified) == 0)
6039 *flags |= flagQualified;
6040 } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
6041 return (1);
6042
6043 return (0);
6044}
6045
6046/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00006047 * xmlSchemaPValAttrBlockFinal:
6048 * @value: the value
6049 * @flags: the flags to be modified
6050 * @flagAll: the specific flag for "#all"
6051 * @flagExtension: the specific flag for "extension"
6052 * @flagRestriction: the specific flag for "restriction"
6053 * @flagSubstitution: the specific flag for "substitution"
6054 * @flagList: the specific flag for "list"
6055 * @flagUnion: the specific flag for "union"
6056 *
6057 * Validates the value of the attribute "final" and "block". The value
6058 * is converted into the specified flag values and returned in @flags.
6059 *
6060 * Returns 0 if the value is valid, 1 otherwise.
6061 */
6062
6063static int
6064xmlSchemaPValAttrBlockFinal(const xmlChar *value,
6065 int *flags,
6066 int flagAll,
6067 int flagExtension,
6068 int flagRestriction,
6069 int flagSubstitution,
6070 int flagList,
6071 int flagUnion)
6072{
6073 int ret = 0;
6074
6075 /*
6076 * TODO: This does not check for dublicate entries.
6077 */
William M. Brack2f2a6632004-08-20 23:09:47 +00006078 if (value == NULL)
6079 return (1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006080 if (xmlStrEqual(value, BAD_CAST "#all")) {
6081 if (flagAll != -1)
6082 *flags |= flagAll;
6083 else {
6084 if (flagExtension != -1)
6085 *flags |= flagExtension;
6086 if (flagRestriction != -1)
6087 *flags |= flagRestriction;
6088 if (flagSubstitution != -1)
6089 *flags |= flagSubstitution;
6090 if (flagList != -1)
6091 *flags |= flagList;
6092 if (flagUnion != -1)
6093 *flags |= flagUnion;
6094 }
6095 } else {
6096 const xmlChar *end, *cur = value;
6097 xmlChar *item;
6098
6099 do {
6100 while (IS_BLANK_CH(*cur))
6101 cur++;
6102 end = cur;
6103 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
6104 end++;
6105 if (end == cur)
6106 break;
6107 item = xmlStrndup(cur, end - cur);
6108 if (xmlStrEqual(item, BAD_CAST "extension")) {
6109 if (flagExtension != -1) {
6110 if ((*flags & flagExtension) == 0)
6111 *flags |= flagExtension;
6112 } else
6113 ret = 1;
6114 } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
6115 if (flagRestriction != -1) {
6116 if ((*flags & flagRestriction) == 0)
6117 *flags |= flagRestriction;
6118 } else
6119 ret = 1;
6120 } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
6121 if (flagSubstitution != -1) {
6122 if ((*flags & flagSubstitution) == 0)
6123 *flags |= flagSubstitution;
6124 } else
6125 ret = 1;
6126 } else if (xmlStrEqual(item, BAD_CAST "list")) {
6127 if (flagList != -1) {
6128 if ((*flags & flagList) == 0)
6129 *flags |= flagList;
6130 } else
6131 ret = 1;
6132 } else if (xmlStrEqual(item, BAD_CAST "union")) {
6133 if (flagUnion != -1) {
6134 if ((*flags & flagUnion) == 0)
6135 *flags |= flagUnion;
6136 } else
6137 ret = 1;
6138 } else
6139 ret = 1;
6140 if (item != NULL)
6141 xmlFree(item);
6142 cur = end;
6143 } while ((ret == 0) && (*cur != 0));
6144 }
6145
6146 return (ret);
6147}
6148
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006149#ifdef IDC_ENABLED
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006150static int
6151xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006152 xmlSchemaIDCPtr idc,
6153 xmlSchemaIDCSelectPtr selector,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006154 xmlAttrPtr attr,
6155 int isField)
6156{
6157 xmlNodePtr node;
6158
6159 /*
6160 * c-selector-xpath:
6161 * Schema Component Constraint: Selector Value OK
6162 *
6163 * TODO: 1 The {selector} must be a valid XPath expression, as defined
6164 * in [XPath].
6165 */
6166 if (selector == NULL) {
6167 xmlSchemaPErr(ctxt, idc->node,
6168 XML_SCHEMAP_INTERNAL,
6169 "Internal error: xmlSchemaCheckCSelectorXPath, "
6170 "the selector is not specified.\n", NULL, NULL);
6171 return (-1);
6172 }
6173 if (attr == NULL)
6174 node = idc->node;
6175 else
6176 node = (xmlNodePtr) attr;
6177 if (selector->xpath == NULL) {
6178 xmlSchemaPCustomErr(ctxt,
6179 /* TODO: Adjust error code. */
6180 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6181 NULL, NULL, node,
6182 "The XPath expression of the selector is not valid", NULL);
6183 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
6184 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006185 const xmlChar **nsArray = NULL;
6186 xmlNsPtr *nsList = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006187 /*
6188 * Compile the XPath expression.
6189 */
6190 /*
6191 * TODO: We need the array of in-scope namespaces for compilation.
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006192 * TODO: Call xmlPatterncompile with different options for selector/
6193 * field.
6194 */
6195 nsList = xmlGetNsList(attr->doc, attr->parent);
6196 /*
6197 * Build an array of prefixes and namespaces.
6198 */
6199 if (nsList != NULL) {
6200 int i, count = 0;
6201 xmlNsPtr ns;
6202
6203 for (i = 0; nsList[i] != NULL; i++)
6204 count++;
6205
6206 nsArray = (const xmlChar **) xmlMalloc(
6207 (count * 2 + 1) * sizeof(const xmlChar *));
6208 if (nsArray == NULL) {
6209 xmlSchemaPErrMemory(ctxt, "allocating a namespace array",
6210 NULL);
6211 return (-1);
6212 }
6213 for (i = 0; i < count; i++) {
6214 ns = nsList[i];
6215 nsArray[2 * i] = nsList[i]->href;
6216 nsArray[2 * i + 1] = nsList[i]->prefix;
6217 }
6218 nsArray[count * 2] = NULL;
6219 xmlFree(nsList);
6220 }
6221 if (isField)
6222 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik285ebab2005-03-04 18:04:59 +00006223 NULL, 1, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006224 else
6225 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik285ebab2005-03-04 18:04:59 +00006226 NULL, 1, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006227 if (nsArray != NULL)
6228 xmlFree((xmlChar **) nsArray);
6229
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006230#ifdef IDC_XPATH_SUPPORT
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00006231 if (selector->xpathComp == NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006232 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00006233 /* TODO: Adjust error code? */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006234 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6235 NULL, NULL, node,
6236 "The XPath expression '%s' could not be "
6237 "compiled", selector->xpath);
6238 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
6239 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00006240#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006241 }
6242 return (0);
6243}
6244
6245/**
6246 * xmlSchemaAssignAnnotation:
6247 * @item: the schema component
6248 * @annot: the annotation
6249 *
6250 * Adds the annotation to the given schema component.
6251 *
6252 * Returns the given annotaion.
6253 */
6254static xmlSchemaAnnotPtr
6255xmlSchemaAssignAnnotation(xmlSchemaBasicItemPtr item,
6256 xmlSchemaAnnotPtr annot)
6257{
6258 xmlSchemaAnnotPtr cur = item->annot;
6259
6260 if (item->annot == NULL) {
6261 item->annot = annot;
6262 return (annot);
6263 }
6264 cur = item->annot;
6265 if (cur->next != NULL) {
6266 cur = cur->next;
6267 }
6268 cur->next = annot;
6269 return (annot);
6270}
6271
6272/**
6273 * xmlSchemaParseIDCSelectorAndField:
6274 * @ctxt: a schema validation context
6275 * @schema: the schema being built
6276 * @node: a subtree containing XML Schema informations
6277 *
6278 * Parses a XML Schema identity-contraint definition's
6279 * <selector> and <field> elements.
6280 *
6281 * Returns the parsed identity-constraint definition.
6282 */
6283static xmlSchemaIDCSelectPtr
6284xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
6285 xmlSchemaPtr schema,
6286 xmlSchemaIDCPtr idc,
6287 xmlNodePtr node,
6288 int isField)
6289{
6290 xmlSchemaIDCSelectPtr item;
6291 xmlNodePtr child = NULL;
6292 xmlAttrPtr attr;
6293
6294 /*
6295 * Check for illegal attributes.
6296 */
6297 attr = node->properties;
6298 while (attr != NULL) {
6299 if (attr->ns == NULL) {
6300 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6301 (!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
6302 xmlSchemaPIllegalAttrErr(ctxt,
6303 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6304 NULL, NULL, attr);
6305 }
6306 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6307 xmlSchemaPIllegalAttrErr(ctxt,
6308 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6309 NULL, NULL, attr);
6310 }
6311 attr = attr->next;
6312 }
6313 /*
6314 * Create the item.
6315 */
6316 item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
6317 if (item == NULL) {
6318 xmlSchemaPErrMemory(ctxt,
6319 "allocating a 'selector' of an identity-constraint definition",
6320 NULL);
6321 return (NULL);
6322 }
6323 memset(item, 0, sizeof(xmlSchemaIDCSelect));
6324 /*
6325 * Attribute "xpath" (mandatory).
6326 */
6327 attr = xmlSchemaGetPropNode(node, "xpath");
6328 if (attr == NULL) {
6329 xmlSchemaPMissingAttrErr(ctxt,
6330 XML_SCHEMAP_S4S_ATTR_MISSING,
6331 NULL, NULL, node,
6332 "name", NULL);
6333 } else {
6334 item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6335 /*
6336 * URGENT TODO: "field"s have an other syntax than "selector"s.
6337 */
6338
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006339 if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr,
6340 isField) == -1) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006341 xmlSchemaPErr(ctxt,
6342 (xmlNodePtr) attr,
6343 XML_SCHEMAP_INTERNAL,
6344 "Internal error: xmlSchemaParseIDCSelectorAndField, "
6345 "validating the XPath expression of a IDC selector.\n",
6346 NULL, NULL);
6347 }
6348
6349 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00006350 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006351 /*
6352 * And now for the children...
6353 */
6354 child = node->children;
6355 if (IS_SCHEMA(child, "annotation")) {
6356 /*
6357 * Add the annotation to the parent IDC.
6358 */
6359 xmlSchemaAssignAnnotation((xmlSchemaBasicItemPtr) idc,
6360 xmlSchemaParseAnnotation(ctxt, schema, child));
6361 child = child->next;
6362 }
6363 if (child != NULL) {
6364 xmlSchemaPContentErr(ctxt,
6365 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6366 NULL, NULL, node, child,
6367 NULL, "(annotation?)");
6368 }
6369
6370 return (item);
6371}
6372
6373/**
6374 * xmlSchemaParseIDC:
6375 * @ctxt: a schema validation context
6376 * @schema: the schema being built
6377 * @node: a subtree containing XML Schema informations
6378 *
6379 * Parses a XML Schema identity-contraint definition.
6380 *
6381 * Returns the parsed identity-constraint definition.
6382 */
6383static xmlSchemaIDCPtr
6384xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
6385 xmlSchemaPtr schema,
6386 xmlNodePtr node,
6387 xmlSchemaTypeType idcCategory,
6388 const xmlChar *targetNamespace)
6389{
6390 xmlSchemaIDCPtr item = NULL;
6391 xmlNodePtr child = NULL;
6392 xmlAttrPtr attr;
6393 const xmlChar *name = NULL;
6394 xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
6395 int resAdd;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00006396
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006397 /*
6398 * Check for illegal attributes.
6399 */
6400 attr = node->properties;
6401 while (attr != NULL) {
6402 if (attr->ns == NULL) {
6403 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6404 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
6405 ((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
6406 (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
6407 xmlSchemaPIllegalAttrErr(ctxt,
6408 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6409 NULL, NULL, attr);
6410 }
6411 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6412 xmlSchemaPIllegalAttrErr(ctxt,
6413 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6414 NULL, NULL, attr);
6415 }
6416 attr = attr->next;
6417 }
6418 /*
6419 * Attribute "name" (mandatory).
6420 */
6421 attr = xmlSchemaGetPropNode(node, "name");
6422 if (attr == NULL) {
6423 xmlSchemaPMissingAttrErr(ctxt,
6424 XML_SCHEMAP_S4S_ATTR_MISSING,
6425 NULL, NULL, node,
6426 "name", NULL);
6427 return (NULL);
6428 } else if (xmlSchemaPValAttrNode(ctxt,
6429 NULL, NULL, attr,
6430 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
6431 return (NULL);
6432 }
6433 /*
6434 * Create the component.
6435 */
6436 if (schema->idcDef == NULL)
6437 schema->idcDef = xmlHashCreateDict(10, ctxt->dict);
6438 if (schema->idcDef == NULL)
6439 return (NULL);
6440
6441 item = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
6442 if (item == NULL) {
6443 xmlSchemaPErrMemory(ctxt,
6444 "allocating an identity-constraint definition", NULL);
6445 return (NULL);
6446 }
6447 /*
6448 * Add the IDC to the list of IDCs on the schema component.
6449 */
6450 resAdd = xmlHashAddEntry2(schema->idcDef, name, targetNamespace, item);
6451 if (resAdd != 0) {
6452 xmlSchemaPCustomErrExt(ctxt,
6453 XML_SCHEMAP_REDEFINED_TYPE,
6454 NULL, NULL, node,
6455 "An identity-constraint definition with the name '%s' "
6456 "and targetNamespace '%s' does already exist",
6457 name, targetNamespace, NULL);
6458 xmlFree(item);
6459 return (NULL);
6460 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006461 memset(item, 0, sizeof(xmlSchemaIDC));
6462 item->name = name;
6463 item->type = idcCategory;
6464 item->node = node;
6465 /*
6466 * The target namespace of the parent element declaration.
6467 */
6468 item->targetNamespace = targetNamespace;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00006469 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) item,
6470 node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006471 if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
6472 /*
6473 * Attribute "refer" (mandatory).
6474 */
6475 attr = xmlSchemaGetPropNode(node, "refer");
6476 if (attr == NULL) {
6477 xmlSchemaPMissingAttrErr(ctxt,
6478 XML_SCHEMAP_S4S_ATTR_MISSING,
6479 NULL, NULL, node,
6480 "refer", NULL);
6481 } else {
6482 /*
6483 * Create a reference item.
6484 */
6485 item->ref = (xmlSchemaItemQNRefPtr) xmlMalloc(
6486 sizeof(xmlSchemaItemQNRef));
6487 if (item->ref == NULL) {
6488 xmlSchemaPErrMemory(ctxt,
6489 "allocating a QName reference item", NULL);
6490 return (NULL);
6491 }
6492 memset(item->ref, 0, sizeof(xmlSchemaItemQNRef));
6493 xmlSchemaPValAttrNodeQName(ctxt, schema,
6494 NULL, NULL, attr,
6495 &(item->ref->targetNamespace), 0,
6496 &(item->ref->name));
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006497 xmlSchemaCheckReference(ctxt, schema, node, (xmlSchemaTypePtr) item,
6498 item->ref->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006499 }
6500 }
6501 /*
6502 * And now for the children...
6503 */
6504 child = node->children;
6505 if (IS_SCHEMA(child, "annotation")) {
6506 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6507 child = child->next;
6508 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00006509 if (child == NULL) {
6510 xmlSchemaPContentErr(ctxt,
6511 XML_SCHEMAP_S4S_ELEM_MISSING,
6512 NULL, NULL, node, child,
6513 "A child element is missing",
6514 "(annotation?, (selector, field+))");
6515 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006516 /*
6517 * Child element <selector>.
6518 */
6519 if (IS_SCHEMA(child, "selector")) {
6520 item->selector = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
6521 item, child, 0);
6522 child = child->next;
6523 /*
6524 * Child elements <field>.
6525 */
6526 if (IS_SCHEMA(child, "field")) {
6527 do {
6528 field = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
6529 item, child, 1);
6530 if (field != NULL) {
6531 field->index = item->nbFields;
6532 item->nbFields++;
6533 if (lastField != NULL)
6534 lastField->next = field;
6535 else
6536 item->fields = field;
6537 lastField = field;
6538 }
6539 child = child->next;
6540 } while (IS_SCHEMA(child, "field"));
6541 } else {
6542 xmlSchemaPContentErr(ctxt,
6543 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6544 NULL, NULL, node, child,
6545 NULL, "(annotation?, (selector, field+))");
6546 }
6547 }
6548 if (child != NULL) {
6549 xmlSchemaPContentErr(ctxt,
6550 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6551 NULL, NULL, node, child,
6552 NULL, "(annotation?, (selector, field+))");
6553 }
6554
6555 return (item);
6556}
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006557#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006558
Daniel Veillardc0826a72004-08-10 14:17:33 +00006559/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006560 * xmlSchemaParseElement:
6561 * @ctxt: a schema validation context
6562 * @schema: the schema being built
6563 * @node: a subtree containing XML Schema informations
6564 *
6565 * parse a XML schema Element declaration
6566 * *WARNING* this interface is highly subject to change
6567 *
William M. Bracke7091952004-05-11 15:09:58 +00006568 * Returns the parsed element declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00006569 */
6570static xmlSchemaElementPtr
6571xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00006572 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006573{
Daniel Veillardc0826a72004-08-10 14:17:33 +00006574 const xmlChar *name = NULL;
6575 const xmlChar *attrValue;
6576 xmlChar *repName = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00006577 xmlSchemaElementPtr ret;
6578 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006579 const xmlChar *oldcontainer;
6580 xmlAttrPtr attr, nameAttr;
6581 int minOccurs, maxOccurs;
6582 int isRef = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006583#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006584 xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006585#endif
William M. Bracke7091952004-05-11 15:09:58 +00006586
6587 /* 3.3.3 Constraints on XML Representations of Element Declarations */
6588 /* TODO: Complete implementation of 3.3.6 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006589
Daniel Veillard4255d502002-04-16 15:50:10 +00006590 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6591 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006592
Daniel Veillardc0826a72004-08-10 14:17:33 +00006593 oldcontainer = ctxt->container;
6594
6595 nameAttr = xmlSchemaGetPropNode(node, "name");
6596 attr = xmlSchemaGetPropNode(node, "ref");
6597 if ((topLevel) || (attr == NULL)) {
6598 if (nameAttr == NULL) {
6599 xmlSchemaPMissingAttrErr(ctxt,
6600 XML_SCHEMAP_S4S_ATTR_MISSING,
6601 (xmlChar **) &xmlSchemaElemDesElemDecl, NULL, node,
6602 "name", NULL);
6603 return (NULL);
6604 }
6605 name = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) nameAttr);
6606 } else {
6607 isRef = 1;
6608
6609 }
6610 /*
6611 * ... unless minOccurs=maxOccurs=0, in which case the item corresponds
6612 * to no component at all
6613 * TODO: It might be better to validate the element, even if it won't be
6614 * used.
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006615 */
6616 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
6617 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(nonNegativeInteger | unbounded)");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006618 if ((minOccurs == 0) && (maxOccurs == 0))
6619 return (NULL);
6620 /*
6621 * If we get a "ref" attribute on a local <element> we will assume it's
6622 * a reference - even if there's a "name" attribute; this seems to be more
6623 * robust.
6624 */
6625 if (isRef) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006626 char buf[50];
Daniel Veillardc0826a72004-08-10 14:17:33 +00006627 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix;
6628
6629 /*
6630 * Parse as a particle.
6631 */
6632 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006633 (xmlChar **) &xmlSchemaElemDesElemRef,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006634 NULL, attr, &refNs, &refPrefix, &ref);
6635
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006636 snprintf(buf, 49, "#eRef%d", ctxt->counter++ + 1);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006637 ret = xmlSchemaAddElement(ctxt, schema, (const xmlChar *) buf, NULL, node, 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006638 if (ret == NULL) {
6639 if (repName != NULL)
6640 xmlFree(repName);
6641 return (NULL);
6642 }
6643 ret->type = XML_SCHEMA_TYPE_ELEMENT;
6644 ret->node = node;
6645 ret->ref = ref;
6646 ret->refNs = refNs;
6647 ret->refPrefix = refPrefix;
6648 ret->flags |= XML_SCHEMAS_ELEM_REF;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006649 xmlSchemaCheckReference(ctxt, schema, node, (xmlSchemaTypePtr) ret, refNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006650 /*
6651 * Check for illegal attributes.
6652 */
6653 /*
6654 * 3.3.3 : 2.1
6655 * One of ref or name must be present, but not both
6656 */
6657 if (nameAttr != NULL) {
6658 xmlSchemaPMutualExclAttrErr(ctxt,
6659 XML_SCHEMAP_SRC_ELEMENT_2_1,
6660 &repName, (xmlSchemaTypePtr) ret, nameAttr,
6661 "ref", "name");
6662 }
6663 /* 3.3.3 : 2.2 */
6664 attr = node->properties;
6665 while (attr != NULL) {
6666 if (attr->ns == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006667 if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
6668 xmlStrEqual(attr->name, BAD_CAST "name") ||
6669 xmlStrEqual(attr->name, BAD_CAST "id") ||
6670 xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
6671 xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
6672 {
6673 attr = attr->next;
6674 continue;
6675 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006676 xmlSchemaPCustomAttrErr(ctxt,
6677 XML_SCHEMAP_SRC_ELEMENT_2_2,
6678 &repName, (xmlSchemaTypePtr) ret, attr,
6679 "Only the attributes 'minOccurs', 'maxOccurs' and "
6680 "'id' are allowed in addition to 'ref'");
6681 break;
6682 }
6683 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6684 xmlSchemaPIllegalAttrErr(ctxt,
6685 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6686 &repName, (xmlSchemaTypePtr) ret, attr);
6687 }
6688 attr = attr->next;
6689 }
6690 } else {
6691 const xmlChar *ns = NULL, *fixed;
6692
6693 /*
6694 * Parse as an element declaration.
6695 */
6696 if (xmlSchemaPValAttrNode(ctxt,
6697 (xmlChar **) &xmlSchemaElemDesElemDecl, NULL, nameAttr,
6698 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
6699 return (NULL);
6700 /*
6701 * Evaluate the target namespace.
6702 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006703 if (topLevel) {
6704 ns = schema->targetNamespace;
6705 } else {
6706 attr = xmlSchemaGetPropNode(node, "form");
6707 if (attr != NULL) {
6708 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6709 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
William M. Bracke7091952004-05-11 15:09:58 +00006710 ns = schema->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006711 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
6712 xmlSchemaPSimpleTypeErr(ctxt,
6713 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6714 &repName, NULL, (xmlNodePtr) attr,
6715 NULL, "(qualified | unqualified)",
6716 attrValue, NULL, NULL, NULL);
6717 }
6718 } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
6719 ns = schema->targetNamespace;
William M. Brack2f2a6632004-08-20 23:09:47 +00006720 }
6721 ret = xmlSchemaAddElement(ctxt, schema, name, ns, node, topLevel);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006722 if (ret == NULL) {
6723 if (repName != NULL)
6724 xmlFree(repName);
6725 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006726 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006727 ret->type = XML_SCHEMA_TYPE_ELEMENT;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006728 ret->node = node;
6729 ret->targetNamespace = ns;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006730 /*
6731 * Check for illegal attributes.
6732 */
William M. Bracke7091952004-05-11 15:09:58 +00006733 attr = node->properties;
6734 while (attr != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006735 if (attr->ns == NULL) {
6736 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
6737 (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
6738 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6739 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
6740 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
6741 (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006742 (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
6743 {
6744 if (topLevel == 0) {
6745 if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006746 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006747 (!xmlStrEqual(attr->name, BAD_CAST "form")))
6748 {
6749 if (xmlStrEqual(attr->name, BAD_CAST "substitutionGroup")) {
6750 /*
6751 * 3.3.6 : 3 If there is a non-·absent· {substitution
6752 * group affiliation}, then {scope} must be global.
6753 * TODO: This one is redundant, since the S4S does
6754 * prohibit this attribute on local declarations already;
6755 * so why an explicit error code? Weird spec.
6756 * TODO: Move this to the proper constraint layer.
6757 * TODO: Or better wait for spec 1.1 to come.
6758 */
6759 xmlSchemaPIllegalAttrErr(ctxt,
6760 XML_SCHEMAP_E_PROPS_CORRECT_3,
6761 &repName, (xmlSchemaTypePtr) ret, attr);
6762 } else {
6763 xmlSchemaPIllegalAttrErr(ctxt,
6764 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6765 &repName, (xmlSchemaTypePtr) ret, attr);
6766 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006767 }
6768 } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
6769 (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
6770 (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
6771
6772 xmlSchemaPIllegalAttrErr(ctxt,
6773 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6774 &repName, (xmlSchemaTypePtr) ret, attr);
6775 }
6776 }
6777 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6778
6779 xmlSchemaPIllegalAttrErr(ctxt,
6780 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6781 &repName, (xmlSchemaTypePtr) ret, attr);
William M. Bracke7091952004-05-11 15:09:58 +00006782 }
6783 attr = attr->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006784 }
William M. Bracke7091952004-05-11 15:09:58 +00006785 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006786 * Extract/validate attributes.
6787 */
6788 if (topLevel) {
6789 /*
6790 * Process top attributes of global element declarations here.
6791 */
6792 ret->flags |= XML_SCHEMAS_ELEM_GLOBAL;
6793 ret->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
6794 xmlSchemaPValAttrQName(ctxt, schema, &repName,
6795 (xmlSchemaTypePtr) ret, node, "substitutionGroup",
6796 &(ret->substGroupNs), NULL, &(ret->substGroup));
6797 if (xmlGetBooleanProp(ctxt, &repName, (xmlSchemaTypePtr) ret,
6798 node, "abstract", 0))
6799 ret->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
6800 /*
6801 * Attribute "final".
6802 */
6803 attr = xmlSchemaGetPropNode(node, "final");
6804 if (attr == NULL) {
6805 ret->flags |= XML_SCHEMAS_ELEM_FINAL_ABSENT;
6806 } else {
6807 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6808 if (xmlSchemaPValAttrBlockFinal(attrValue, &(ret->flags),
6809 -1,
6810 XML_SCHEMAS_ELEM_FINAL_EXTENSION,
6811 XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
6812 xmlSchemaPSimpleTypeErr(ctxt,
6813 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6814 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00006815 NULL, "(#all | List of (extension | restriction))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00006816 attrValue, NULL, NULL, NULL);
6817 }
6818 }
6819 }
6820 /*
6821 * Attribute "block".
6822 */
6823 attr = xmlSchemaGetPropNode(node, "block");
6824 if (attr == NULL) {
6825 ret->flags |= XML_SCHEMAS_ELEM_BLOCK_ABSENT;
6826 } else {
6827 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6828 if (xmlSchemaPValAttrBlockFinal(attrValue, &(ret->flags),
6829 -1,
6830 XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
6831 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
6832 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
6833 xmlSchemaPSimpleTypeErr(ctxt,
6834 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6835 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00006836 NULL, "(#all | List of (extension | "
Daniel Veillardc0826a72004-08-10 14:17:33 +00006837 "restriction | substitution))", attrValue,
6838 NULL, NULL, NULL);
6839 }
6840 }
6841 if (xmlGetBooleanProp(ctxt, &repName, (xmlSchemaTypePtr) ret,
6842 node, "nillable", 0))
6843 ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006844
Daniel Veillardc0826a72004-08-10 14:17:33 +00006845 xmlSchemaPValAttrQName(ctxt, schema,
6846 &repName, (xmlSchemaTypePtr) ret, node,
6847 "type", &(ret->namedTypeNs), NULL, &(ret->namedType));
Daniel Veillard4255d502002-04-16 15:50:10 +00006848
Daniel Veillardc0826a72004-08-10 14:17:33 +00006849 ret->value = xmlSchemaGetProp(ctxt, node, "default");
6850 attr = xmlSchemaGetPropNode(node, "fixed");
6851 if (attr != NULL) {
6852 fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6853 if (ret->value != NULL) {
6854 /*
6855 * 3.3.3 : 1
6856 * default and fixed must not both be present.
6857 */
6858 xmlSchemaPMutualExclAttrErr(ctxt,
6859 XML_SCHEMAP_SRC_ELEMENT_1,
6860 &repName, (xmlSchemaTypePtr) ret, attr,
6861 "default", "fixed");
6862 } else {
6863 ret->flags |= XML_SCHEMAS_ELEM_FIXED;
6864 ret->value = fixed;
6865 }
6866 }
6867 }
6868 /*
6869 * Extract/validate common attributes.
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006870 */
6871 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6872 node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006873 ret->minOccurs = minOccurs;
6874 ret->maxOccurs = maxOccurs;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006875 if (topLevel != 1)
6876 xmlSchemaPCheckParticleCorrect_2(ctxt, (xmlSchemaTypePtr) ret,
6877 node, minOccurs, maxOccurs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006878 /*
6879 * And now for the children...
6880 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006881 ctxt->container = ret->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006882 child = node->children;
6883 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006884 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6885 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006886 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006887 if (isRef) {
6888 if (child != NULL) {
6889 xmlSchemaPContentErr(ctxt,
6890 XML_SCHEMAP_SRC_ELEMENT_2_2,
6891 &repName, (xmlSchemaTypePtr) ret, node, child,
6892 NULL, "(annotation?)");
William M. Bracke7091952004-05-11 15:09:58 +00006893 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006894 } else {
William M. Bracke7091952004-05-11 15:09:58 +00006895 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006896 /*
6897 * 3.3.3 : 3
6898 * "type" and either <simpleType> or <complexType> are mutually
6899 * exclusive
6900 */
William M. Bracke7091952004-05-11 15:09:58 +00006901 if (ret->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006902 xmlSchemaPContentErr(ctxt,
6903 XML_SCHEMAP_SRC_ELEMENT_3,
6904 &repName, (xmlSchemaTypePtr) ret, node, child,
6905 "The attribute 'type' and the <complexType> child are "
6906 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006907 } else
Daniel Veillard3646d642004-06-02 19:19:14 +00006908 ret->subtypes = xmlSchemaParseComplexType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00006909 child = child->next;
6910 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006911 /*
6912 * 3.3.3 : 3
6913 * "type" and either <simpleType> or <complexType> are
6914 * mutually exclusive
6915 */
William M. Bracke7091952004-05-11 15:09:58 +00006916 if (ret->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006917 xmlSchemaPContentErr(ctxt,
6918 XML_SCHEMAP_SRC_ELEMENT_3,
6919 &repName, (xmlSchemaTypePtr) ret, node, child,
6920 "The attribute 'type' and the <simpleType> child are "
6921 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006922 } else
Daniel Veillard3646d642004-06-02 19:19:14 +00006923 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00006924 child = child->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006925 }
William M. Bracke7091952004-05-11 15:09:58 +00006926 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00006927 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006928#ifdef IDC_ENABLED
6929 if (IS_SCHEMA(child, "unique")) {
6930 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
6931 XML_SCHEMA_TYPE_IDC_UNIQUE, ret->targetNamespace);
6932 } else if (IS_SCHEMA(child, "key")) {
6933 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
6934 XML_SCHEMA_TYPE_IDC_KEY, ret->targetNamespace);
6935 } else if (IS_SCHEMA(child, "keyref")) {
6936 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
6937 XML_SCHEMA_TYPE_IDC_KEYREF, ret->targetNamespace);
6938 }
6939 if (lastIDC != NULL)
6940 lastIDC->next = curIDC;
6941 else
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006942 ret->idcs = (void *) curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006943 lastIDC = curIDC;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006944#else
6945 TODO
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006946#endif
6947 child = child->next;
William M. Bracke7091952004-05-11 15:09:58 +00006948 }
6949 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006950 xmlSchemaPContentErr(ctxt,
6951 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6952 &repName, (xmlSchemaTypePtr) ret, node, child,
6953 NULL, "(annotation?, ((simpleType | complexType)?, "
6954 "(unique | key | keyref)*))");
6955 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006956
Daniel Veillardc0826a72004-08-10 14:17:33 +00006957 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006958 ctxt->container = oldcontainer;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006959 /*
6960 * Cleanup.
6961 */
6962 if (repName != NULL)
6963 xmlFree(repName);
6964 /*
6965 * NOTE: Element Declaration Representation OK 4. will be checked at a
6966 * different layer.
6967 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006968 return (ret);
6969}
6970
6971/**
6972 * xmlSchemaParseUnion:
6973 * @ctxt: a schema validation context
6974 * @schema: the schema being built
6975 * @node: a subtree containing XML Schema informations
6976 *
6977 * parse a XML schema Union definition
6978 * *WARNING* this interface is highly subject to change
6979 *
William M. Bracke7091952004-05-11 15:09:58 +00006980 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00006981 * 1 in case of success.
6982 */
6983static xmlSchemaTypePtr
6984xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006985 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006986{
6987 xmlSchemaTypePtr type, subtype, last = NULL;
6988 xmlNodePtr child = NULL;
6989 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00006990 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006991
6992 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6993 return (NULL);
6994
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006995 snprintf((char *) name, 30, "#union%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00006996 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006997 if (type == NULL)
6998 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00006999 type->type = XML_SCHEMA_TYPE_UNION;
Daniel Veillard4255d502002-04-16 15:50:10 +00007000 type->node = node;
William M. Brack2f2a6632004-08-20 23:09:47 +00007001 /*
7002 * Check for illegal attributes.
7003 */
7004 attr = node->properties;
7005 while (attr != NULL) {
7006 if (attr->ns == NULL) {
7007 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7008 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
7009 xmlSchemaPIllegalAttrErr(ctxt,
7010 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7011 NULL, type, attr);
7012 }
7013 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7014 xmlSchemaPIllegalAttrErr(ctxt,
7015 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7016 NULL, type, attr);
7017 }
7018 attr = attr->next;
7019 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00007020 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00007021 /*
7022 * Attribute "memberTypes". This is a list of QNames.
7023 * TODO: Validate the QNames.
7024 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00007025 type->base = xmlSchemaGetProp(ctxt, node, "memberTypes");
William M. Brack2f2a6632004-08-20 23:09:47 +00007026 /*
7027 * And now for the children...
7028 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007029 child = node->children;
7030 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007031 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7032 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007033 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007034 while (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007035 subtype = (xmlSchemaTypePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00007036 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007037 if (subtype != NULL) {
7038 if (last == NULL) {
7039 type->subtypes = subtype;
7040 last = subtype;
7041 } else {
7042 last->next = subtype;
7043 last = subtype;
7044 }
7045 last->next = NULL;
7046 }
7047 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007048 }
7049 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007050 /* TODO: Think about the error code. */
7051 xmlSchemaPContentErr(ctxt,
7052 XML_SCHEMAP_UNKNOWN_UNION_CHILD,
7053 NULL, type, node, child, NULL, "(annotation?, simpleType*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00007054 }
7055 return (type);
7056}
7057
7058/**
7059 * xmlSchemaParseList:
7060 * @ctxt: a schema validation context
7061 * @schema: the schema being built
7062 * @node: a subtree containing XML Schema informations
7063 *
7064 * parse a XML schema List definition
7065 * *WARNING* this interface is highly subject to change
7066 *
William M. Bracke7091952004-05-11 15:09:58 +00007067 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00007068 * 1 in case of success.
7069 */
7070static xmlSchemaTypePtr
7071xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007072 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007073{
7074 xmlSchemaTypePtr type, subtype;
7075 xmlNodePtr child = NULL;
7076 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00007077 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00007078
7079 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7080 return (NULL);
7081
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00007082 snprintf((char *) name, 30, "#list%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007083 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007084 if (type == NULL)
7085 return (NULL);
7086 type->node = node;
7087 type->type = XML_SCHEMA_TYPE_LIST;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00007088 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00007089 /*
7090 * Check for illegal attributes.
7091 */
7092 attr = node->properties;
7093 while (attr != NULL) {
7094 if (attr->ns == NULL) {
7095 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7096 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
7097 xmlSchemaPIllegalAttrErr(ctxt,
7098 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7099 NULL, type, attr);
7100 }
7101 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7102 xmlSchemaPIllegalAttrErr(ctxt,
7103 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7104 NULL, type, attr);
7105 }
7106 attr = attr->next;
7107 }
7108 /*
7109 * Attribute "itemType".
7110 */
7111 xmlSchemaPValAttrQName(ctxt, schema, NULL, NULL,
7112 node, "itemType", &(type->baseNs), NULL, &(type->base));
7113 /*
7114 * And now for the children...
7115 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007116 child = node->children;
7117 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007118 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7119 child = child->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00007120 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007121 subtype = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00007122 if (IS_SCHEMA(child, "simpleType")) {
7123 if (type->base != NULL) {
7124 xmlSchemaPCustomErr(ctxt,
7125 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
7126 NULL, type, node,
7127 "The attribute 'itemType' and the <simpleType> child "
7128 "are mutually exclusive", NULL);
7129 } else {
7130 subtype = (xmlSchemaTypePtr)
7131 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
7132 type->subtypes = subtype;
7133 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00007134 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007135 }
7136 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007137 /* TODO: Think about the error code. */
7138 xmlSchemaPContentErr(ctxt,
7139 XML_SCHEMAP_UNKNOWN_LIST_CHILD,
7140 NULL, type, node, child, NULL, "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00007141 }
7142 return (type);
7143}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007144
Daniel Veillard4255d502002-04-16 15:50:10 +00007145/**
7146 * xmlSchemaParseSimpleType:
7147 * @ctxt: a schema validation context
7148 * @schema: the schema being built
7149 * @node: a subtree containing XML Schema informations
7150 *
7151 * parse a XML schema Simple Type definition
7152 * *WARNING* this interface is highly subject to change
7153 *
William M. Bracke7091952004-05-11 15:09:58 +00007154 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardc0826a72004-08-10 14:17:33 +00007155 * 1 in case of success.
Daniel Veillard4255d502002-04-16 15:50:10 +00007156 */
7157static xmlSchemaTypePtr
7158xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00007159 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00007160{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007161 xmlSchemaTypePtr type, subtype, oldCtxtType, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00007162 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007163 const xmlChar *attrValue = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007164 xmlChar *des = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007165 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00007166
7167 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7168 return (NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007169
Daniel Veillardc0826a72004-08-10 14:17:33 +00007170 if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007171 attr = xmlSchemaGetPropNode(node, "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007172 if (attr == NULL) {
7173 xmlSchemaPMissingAttrErr(ctxt,
7174 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007175 (xmlChar **) &xmlSchemaElemDesST, NULL, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007176 "name", NULL);
7177 return (NULL);
7178 } else if (xmlSchemaPValAttrNode(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007179 (xmlChar **) &xmlSchemaElemDesST, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007180 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00007181 return (NULL);
7182 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007183 }
7184
7185 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007186 char buf[40];
Daniel Veillardc0826a72004-08-10 14:17:33 +00007187
Daniel Veillard01fa6152004-06-29 17:04:39 +00007188 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007189 * Parse as local simple type definition.
Daniel Veillard01fa6152004-06-29 17:04:39 +00007190 */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00007191 snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007192 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007193 if (type == NULL)
7194 return (NULL);
7195 type->node = node;
7196 type->type = XML_SCHEMA_TYPE_SIMPLE;
7197 /*
7198 * Check for illegal attributes.
7199 */
7200 attr = node->properties;
7201 while (attr != NULL) {
7202 if (attr->ns == NULL) {
7203 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
7204 xmlSchemaPIllegalAttrErr(ctxt,
7205 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007206 &des, type, attr);
Daniel Veillard01fa6152004-06-29 17:04:39 +00007207 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007208 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7209 xmlSchemaPIllegalAttrErr(ctxt,
7210 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007211 &des, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007212 }
7213 attr = attr->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +00007214 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007215 } else {
7216 /*
7217 * Parse as global simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007218 *
7219 * Note that attrValue is the value of the attribute "name" here.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007220 */
William M. Brack2f2a6632004-08-20 23:09:47 +00007221 type = xmlSchemaAddType(ctxt, schema, attrValue, schema->targetNamespace, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007222 if (type == NULL)
7223 return (NULL);
7224 type->node = node;
7225 type->type = XML_SCHEMA_TYPE_SIMPLE;
7226 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
7227 /*
7228 * Check for illegal attributes.
7229 */
7230 attr = node->properties;
7231 while (attr != NULL) {
7232 if (attr->ns == NULL) {
7233 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7234 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007235 (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007236 xmlSchemaPIllegalAttrErr(ctxt,
7237 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007238 &des, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007239 }
7240 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7241 xmlSchemaPIllegalAttrErr(ctxt,
7242 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007243 &des, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007244 }
7245 attr = attr->next;
7246 }
7247 /*
7248 * Attribute "final".
7249 */
7250 attr = xmlSchemaGetPropNode(node, "final");
7251 if (attr == NULL) {
7252 type->flags |= XML_SCHEMAS_TYPE_FINAL_DEFAULT;
7253 } else {
7254 attrValue = xmlSchemaGetProp(ctxt, node, "final");
7255 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
7256 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
7257 XML_SCHEMAS_TYPE_FINAL_LIST,
7258 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
7259
7260 xmlSchemaPSimpleTypeErr(ctxt,
7261 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007262 &des, type, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00007263 NULL, "(#all | List of (list | union | restriction)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00007264 attrValue, NULL, NULL, NULL);
7265 }
7266 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00007267 }
7268 type->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00007269 xmlSchemaPValAttrID(ctxt, NULL, type, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007270 /*
7271 * And now for the children...
7272 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007273 oldCtxtType = ctxt->ctxtType;
7274 oldParentItem = ctxt->parentItem;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007275 ctxt->ctxtType = type;
7276 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00007277 child = node->children;
7278 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007279 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7280 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007281 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007282 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00007283 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007284 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00007285 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007286 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007287 } else if (IS_SCHEMA(child, "list")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007288 subtype = (xmlSchemaTypePtr)
7289 xmlSchemaParseList(ctxt, schema, child);
7290 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007291 } else if (IS_SCHEMA(child, "union")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007292 subtype = (xmlSchemaTypePtr)
7293 xmlSchemaParseUnion(ctxt, schema, child);
7294 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007295 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007296 type->subtypes = subtype;
7297 if ((child != NULL) || (subtype == NULL)) {
7298 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007299 &des, type, node, child, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007300 "(annotation?, (restriction | list | union))");
Daniel Veillard4255d502002-04-16 15:50:10 +00007301 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007302 ctxt->parentItem = oldParentItem;
7303 ctxt->ctxtType = oldCtxtType;
7304 FREE_AND_NULL(des)
Daniel Veillard01fa6152004-06-29 17:04:39 +00007305
Daniel Veillard4255d502002-04-16 15:50:10 +00007306 return (type);
7307}
7308
7309
7310/**
7311 * xmlSchemaParseGroup:
7312 * @ctxt: a schema validation context
7313 * @schema: the schema being built
7314 * @node: a subtree containing XML Schema informations
7315 *
7316 * parse a XML schema Group definition
7317 * *WARNING* this interface is highly subject to change
7318 *
William M. Bracke7091952004-05-11 15:09:58 +00007319 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00007320 * 1 in case of success.
7321 */
7322static xmlSchemaTypePtr
7323xmlSchemaParseGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00007324 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00007325{
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00007326 xmlSchemaTypePtr item;
7327 xmlNodePtr child = NULL;
7328 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00007329
7330 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00007331 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007332
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00007333 if (topLevel) {
7334 const xmlChar *name;
7335 /*
7336 * Parse as model group definition.
7337 */
7338 attr = xmlSchemaGetPropNode(node, "name");
7339 if (attr == NULL) {
7340 xmlSchemaPMissingAttrErr(ctxt,
7341 XML_SCHEMAP_S4S_ATTR_MISSING,
7342 NULL, NULL, node,
7343 "name", NULL);
7344 return (NULL);
7345 } else if (xmlSchemaPValAttrNode(ctxt,
7346 NULL, NULL, attr,
7347 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7348 return (NULL);
7349 }
7350 item = xmlSchemaAddGroup(ctxt, schema, name,
7351 schema->targetNamespace, node);
7352 if (item == NULL)
7353 return (NULL);
7354 item->node = node;
7355 item->type = XML_SCHEMA_TYPE_GROUP;
7356 item->flags |= XML_SCHEMAS_TYPE_GLOBAL;
7357 /*
7358 * Check for illegal attributes.
7359 */
7360 attr = node->properties;
7361 while (attr != NULL) {
7362 if (attr->ns == NULL) {
7363 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7364 (!xmlStrEqual(attr->name, BAD_CAST "id"))) {
7365 xmlSchemaPIllegalAttrErr(ctxt,
7366 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7367 NULL, item, attr);
7368 }
7369 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7370 xmlSchemaPIllegalAttrErr(ctxt,
7371 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7372 NULL, item, attr);
7373 }
7374 attr = attr->next;
7375 }
7376 xmlSchemaPValAttrID(ctxt, NULL, item, node, BAD_CAST "id");
7377 /*
7378 * And now for the children...
7379 */
7380 child = node->children;
7381 if (IS_SCHEMA(child, "annotation")) {
7382 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7383 child = child->next;
7384 }
7385 if (IS_SCHEMA(child, "all")) {
7386 item->subtypes = (xmlSchemaTypePtr)
7387 xmlSchemaParseAll(ctxt, schema, child);
7388 child = child->next;
7389 } else if (IS_SCHEMA(child, "choice")) {
7390 item->subtypes = xmlSchemaParseChoice(ctxt, schema, child);
7391 child = child->next;
7392 } else if (IS_SCHEMA(child, "sequence")) {
7393 item->subtypes = xmlSchemaParseSequence(ctxt, schema, child);
7394 child = child->next;
7395 }
7396 if (child != NULL) {
7397 xmlSchemaPContentErr(ctxt,
7398 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7399 NULL, item, node, child, NULL,
7400 "(annotation?, (all | choice | sequence)?)");
7401 }
7402 } else {
7403 const xmlChar *ref = NULL, *refNs = NULL, *refPrefix = NULL;
7404 int minOccurs, maxOccurs;
7405 char buf[40];
Daniel Veillard4255d502002-04-16 15:50:10 +00007406
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00007407 /*
7408 * Parse as particle.
7409 */
7410 attr = xmlSchemaGetPropNode(node, "ref");
7411 if (attr == NULL) {
7412 xmlSchemaPMissingAttrErr(ctxt,
7413 XML_SCHEMAP_S4S_ATTR_MISSING,
7414 NULL, NULL, node,
7415 "ref", NULL);
7416 return (NULL);
7417 } else if (xmlSchemaPValAttrNodeQName(ctxt, schema, NULL, NULL,
7418 attr, &refNs, &refPrefix, &ref) != 0) {
7419 return (NULL);
7420 }
7421
7422 /*
7423 * TODO: Validate the element even if no item is created
7424 * (i.e. min/maxOccurs == 0).
7425 */
7426 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
7427 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
7428 "(nonNegativeInteger | unbounded)");
7429 if ((minOccurs == 0) && (maxOccurs == 0)) {
7430 return (NULL);
7431 }
7432
7433 snprintf(buf, 39, "#grRef%d", ctxt->counter++ + 1);
7434 item = xmlSchemaAddGroup(ctxt, schema, (const xmlChar *)buf, NULL, node);
7435 if (item == NULL)
7436 return (NULL);
7437 item->node = node;
7438 item->type = XML_SCHEMA_TYPE_GROUP;
7439 item->ref = ref;
7440 item->refNs = refNs;
7441 xmlSchemaCheckReference(ctxt, schema, node, item, refNs);
7442 item->minOccurs = minOccurs;
7443 item->maxOccurs = maxOccurs;
7444 xmlSchemaPCheckParticleCorrect_2(ctxt, item,
7445 node, item->minOccurs, item->maxOccurs);
7446 /*
7447 * Check for illegal attributes.
7448 */
7449 attr = node->properties;
7450 while (attr != NULL) {
7451 if (attr->ns == NULL) {
7452 if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
7453 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7454 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
7455 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs"))) {
7456 xmlSchemaPIllegalAttrErr(ctxt,
7457 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7458 NULL, item, attr);
7459 }
7460 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7461 xmlSchemaPIllegalAttrErr(ctxt,
7462 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7463 NULL, item, attr);
7464 }
7465 attr = attr->next;
7466 }
7467 xmlSchemaPValAttrID(ctxt, NULL, item, node, BAD_CAST "id");
7468 /*
7469 * And now for the children...
7470 */
7471 child = node->children;
7472 if (IS_SCHEMA(child, "annotation")) {
7473 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7474 child = child->next;
7475 }
7476 if (child != NULL) {
7477 xmlSchemaPContentErr(ctxt,
7478 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7479 NULL, item, node, child, NULL,
7480 "(annotation?, (all | choice | sequence)?)");
7481 }
7482 }
7483
7484 return (item);
Daniel Veillard4255d502002-04-16 15:50:10 +00007485}
7486
7487/**
7488 * xmlSchemaParseAll:
7489 * @ctxt: a schema validation context
7490 * @schema: the schema being built
7491 * @node: a subtree containing XML Schema informations
7492 *
7493 * parse a XML schema All definition
7494 * *WARNING* this interface is highly subject to change
7495 *
William M. Bracke7091952004-05-11 15:09:58 +00007496 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00007497 * 1 in case of success.
7498 */
7499static xmlSchemaTypePtr
7500xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007501 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007502{
7503 xmlSchemaTypePtr type, subtype, last = NULL;
7504 xmlNodePtr child = NULL;
7505 xmlChar name[30];
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00007506 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007507
7508 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7509 return (NULL);
7510
7511
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00007512 snprintf((char *) name, 30, "#all%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007513 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007514 if (type == NULL)
7515 return (NULL);
7516 type->node = node;
Daniel Veillard7646b182002-04-20 06:41:40 +00007517 type->type = XML_SCHEMA_TYPE_ALL;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00007518
7519 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007520
7521 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
7522 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00007523
7524 oldcontainer = ctxt->container;
7525 ctxt->container = (const xmlChar *) name;
Daniel Veillard4255d502002-04-16 15:50:10 +00007526 child = node->children;
7527 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007528 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7529 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007530 }
7531 while (IS_SCHEMA(child, "element")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007532 subtype = (xmlSchemaTypePtr)
7533 xmlSchemaParseElement(ctxt, schema, child, 0);
7534 if (subtype != NULL) {
William M. Brackb15351e2003-12-27 04:34:42 +00007535 if (subtype->minOccurs > 1)
7536 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MINOCCURS,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007537 "invalid value for minOccurs (must be 0 or 1).\n",
William M. Brackb15351e2003-12-27 04:34:42 +00007538 NULL, NULL);
7539 if (subtype->maxOccurs > 1)
7540 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MAXOCCURS,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007541 "invalid value for maxOccurs (must be 0 or 1).\n",
William M. Brackb15351e2003-12-27 04:34:42 +00007542 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007543 if (last == NULL) {
7544 type->subtypes = subtype;
7545 last = subtype;
7546 } else {
7547 last->next = subtype;
7548 last = subtype;
7549 }
7550 last->next = NULL;
7551 }
7552 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007553 }
7554 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007555 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ALL_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007556 "<all> has unexpected content.\n", type->name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007557 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007558 }
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00007559 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007560 return (type);
7561}
7562
7563/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007564 * xmlSchemaCleanupDoc:
7565 * @ctxt: a schema validation context
7566 * @node: the root of the document.
7567 *
7568 * removes unwanted nodes in a schemas document tree
7569 */
7570static void
7571xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
7572{
7573 xmlNodePtr delete, cur;
7574
7575 if ((ctxt == NULL) || (root == NULL)) return;
7576
7577 /*
7578 * Remove all the blank text nodes
7579 */
7580 delete = NULL;
7581 cur = root;
7582 while (cur != NULL) {
7583 if (delete != NULL) {
7584 xmlUnlinkNode(delete);
7585 xmlFreeNode(delete);
7586 delete = NULL;
7587 }
7588 if (cur->type == XML_TEXT_NODE) {
7589 if (IS_BLANK_NODE(cur)) {
7590 if (xmlNodeGetSpacePreserve(cur) != 1) {
7591 delete = cur;
7592 }
7593 }
7594 } else if ((cur->type != XML_ELEMENT_NODE) &&
7595 (cur->type != XML_CDATA_SECTION_NODE)) {
7596 delete = cur;
7597 goto skip_children;
7598 }
7599
7600 /*
7601 * Skip to next node
7602 */
7603 if (cur->children != NULL) {
7604 if ((cur->children->type != XML_ENTITY_DECL) &&
7605 (cur->children->type != XML_ENTITY_REF_NODE) &&
7606 (cur->children->type != XML_ENTITY_NODE)) {
7607 cur = cur->children;
7608 continue;
7609 }
7610 }
7611 skip_children:
7612 if (cur->next != NULL) {
7613 cur = cur->next;
7614 continue;
7615 }
7616
7617 do {
7618 cur = cur->parent;
7619 if (cur == NULL)
7620 break;
7621 if (cur == root) {
7622 cur = NULL;
7623 break;
7624 }
7625 if (cur->next != NULL) {
7626 cur = cur->next;
7627 break;
7628 }
7629 } while (cur != NULL);
7630 }
7631 if (delete != NULL) {
7632 xmlUnlinkNode(delete);
7633 xmlFreeNode(delete);
7634 delete = NULL;
7635 }
7636}
7637
William M. Brack2f2a6632004-08-20 23:09:47 +00007638
7639/**
7640 * xmlSchemaImportSchema
7641 *
7642 * @ctxt: a schema validation context
7643 * @schemaLocation: an URI defining where to find the imported schema
7644 *
7645 * import a XML schema
7646 * *WARNING* this interface is highly subject to change
7647 *
7648 * Returns -1 in case of error and 1 in case of success.
7649 */
7650#if 0
7651static xmlSchemaImportPtr
7652xmlSchemaImportSchema(xmlSchemaParserCtxtPtr ctxt,
7653 const xmlChar *schemaLocation)
7654{
7655 xmlSchemaImportPtr import;
7656 xmlSchemaParserCtxtPtr newctxt;
7657
7658 newctxt = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
7659 if (newctxt == NULL) {
7660 xmlSchemaPErrMemory(ctxt, "allocating schema parser context",
7661 NULL);
7662 return (NULL);
7663 }
7664 memset(newctxt, 0, sizeof(xmlSchemaParserCtxt));
7665 /* Keep the same dictionnary for parsing, really */
7666 xmlDictReference(ctxt->dict);
7667 newctxt->dict = ctxt->dict;
7668 newctxt->includes = 0;
7669 newctxt->URL = xmlDictLookup(newctxt->dict, schemaLocation, -1);
7670
7671 xmlSchemaSetParserErrors(newctxt, ctxt->error, ctxt->warning,
7672 ctxt->userData);
7673
7674 import = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
7675 if (import == NULL) {
7676 xmlSchemaPErrMemory(NULL, "allocating imported schema",
7677 NULL);
7678 xmlSchemaFreeParserCtxt(newctxt);
7679 return (NULL);
7680 }
7681
7682 memset(import, 0, sizeof(xmlSchemaImport));
7683 import->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
7684 import->schema = xmlSchemaParse(newctxt);
7685
7686 if (import->schema == NULL) {
7687 /* FIXME use another error enum here ? */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00007688 xmlSchemaPErr(ctxt, NULL, XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00007689 "Failed to import schema from location \"%s\".\n",
7690 schemaLocation, NULL);
7691
7692 xmlSchemaFreeParserCtxt(newctxt);
7693 /* The schemaLocation is held by the dictionary.
7694 if (import->schemaLocation != NULL)
7695 xmlFree((xmlChar *)import->schemaLocation);
7696 */
7697 xmlFree(import);
7698 return NULL;
7699 }
7700
7701 xmlSchemaFreeParserCtxt(newctxt);
7702 return import;
7703}
7704#endif
7705
7706static void
7707xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
7708{
7709 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
7710 schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
7711
7712 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
7713 schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
7714
7715 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
7716 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
7717 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
7718 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
7719 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
7720 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
7721 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
7722 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
7723
7724 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
7725 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
7726 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
7727 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
7728 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
7729 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
7730}
7731
7732static void
7733xmlSchemaParseSchemaDefaults(xmlSchemaParserCtxtPtr ctxt,
7734 xmlSchemaPtr schema,
7735 xmlNodePtr node)
7736{
7737 xmlAttrPtr attr;
7738 const xmlChar *val;
7739
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00007740 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
7741 if (schema->version == NULL)
7742 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
7743 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &(schema->version));
7744 else
7745 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
7746 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), NULL);
7747
William M. Brack2f2a6632004-08-20 23:09:47 +00007748 attr = xmlSchemaGetPropNode(node, "elementFormDefault");
7749 if (attr != NULL) {
7750 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7751 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
7752 XML_SCHEMAS_QUALIF_ELEM) != 0) {
7753 xmlSchemaPSimpleTypeErr(ctxt,
7754 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
7755 NULL, NULL, (xmlNodePtr) attr, NULL,
7756 "(qualified | unqualified)", val, NULL, NULL, NULL);
7757 }
7758 }
7759
7760 attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
7761 if (attr != NULL) {
7762 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7763 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
7764 XML_SCHEMAS_QUALIF_ATTR) != 0) {
7765 xmlSchemaPSimpleTypeErr(ctxt,
7766 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
7767 NULL, NULL, (xmlNodePtr) attr, NULL,
7768 "(qualified | unqualified)", val, NULL, NULL, NULL);
7769 }
7770 }
7771
7772 attr = xmlSchemaGetPropNode(node, "finalDefault");
7773 if (attr != NULL) {
7774 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7775 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
7776 XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
7777 XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
7778 -1,
7779 XML_SCHEMAS_FINAL_DEFAULT_LIST,
7780 XML_SCHEMAS_FINAL_DEFAULT_UNION) != 0) {
7781 xmlSchemaPSimpleTypeErr(ctxt,
7782 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7783 NULL, NULL, (xmlNodePtr) attr, NULL,
7784 "(#all | List of (extension | restriction | list | union))",
7785 val, NULL, NULL, NULL);
7786 }
7787 }
7788
7789 attr = xmlSchemaGetPropNode(node, "blockDefault");
7790 if (attr != NULL) {
7791 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7792 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
7793 XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
7794 XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
7795 XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1) != 0) {
7796 xmlSchemaPSimpleTypeErr(ctxt,
7797 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7798 NULL, NULL, (xmlNodePtr) attr, NULL,
7799 "(#all | List of (extension | restriction | substitution))",
7800 val, NULL, NULL, NULL);
7801 }
7802 }
7803}
7804
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007805/**
7806 * xmlSchemaParseSchemaTopLevel:
7807 * @ctxt: a schema validation context
7808 * @schema: the schemas
7809 * @nodes: the list of top level nodes
7810 *
7811 * Returns the internal XML Schema structure built from the resource or
7812 * NULL in case of error
7813 */
7814static void
7815xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
7816 xmlSchemaPtr schema, xmlNodePtr nodes)
7817{
7818 xmlNodePtr child;
7819 xmlSchemaAnnotPtr annot;
7820
7821 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
7822 return;
7823
7824 child = nodes;
7825 while ((IS_SCHEMA(child, "include")) ||
7826 (IS_SCHEMA(child, "import")) ||
7827 (IS_SCHEMA(child, "redefine")) ||
7828 (IS_SCHEMA(child, "annotation"))) {
7829 if (IS_SCHEMA(child, "annotation")) {
7830 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7831 if (schema->annot == NULL)
7832 schema->annot = annot;
7833 else
7834 xmlSchemaFreeAnnot(annot);
7835 } else if (IS_SCHEMA(child, "import")) {
7836 xmlSchemaParseImport(ctxt, schema, child);
7837 } else if (IS_SCHEMA(child, "include")) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00007838 ctxt->includes++;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007839 xmlSchemaParseInclude(ctxt, schema, child);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00007840 ctxt->includes--;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007841 } else if (IS_SCHEMA(child, "redefine")) {
7842 TODO
7843 }
7844 child = child->next;
7845 }
7846 while (child != NULL) {
7847 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007848 xmlSchemaParseComplexType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007849 child = child->next;
7850 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007851 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007852 child = child->next;
7853 } else if (IS_SCHEMA(child, "element")) {
7854 xmlSchemaParseElement(ctxt, schema, child, 1);
7855 child = child->next;
7856 } else if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00007857 xmlSchemaParseAttribute(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007858 child = child->next;
7859 } else if (IS_SCHEMA(child, "attributeGroup")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007860 xmlSchemaParseAttributeGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007861 child = child->next;
7862 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007863 xmlSchemaParseGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007864 child = child->next;
7865 } else if (IS_SCHEMA(child, "notation")) {
7866 xmlSchemaParseNotation(ctxt, schema, child);
7867 child = child->next;
7868 } else {
7869 xmlSchemaPErr2(ctxt, NULL, child,
7870 XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007871 "Unexpected element \"%s\" as child of <schema>.\n",
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007872 child->name, NULL);
7873 child = child->next;
7874 }
7875 while (IS_SCHEMA(child, "annotation")) {
7876 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7877 if (schema->annot == NULL)
7878 schema->annot = annot;
7879 else
7880 xmlSchemaFreeAnnot(annot);
7881 child = child->next;
7882 }
7883 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00007884 ctxt->parentItem = NULL;
7885 ctxt->ctxtType = NULL;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007886}
7887
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007888static xmlSchemaImportPtr
7889xmlSchemaAddImport(xmlSchemaParserCtxtPtr ctxt,
7890 xmlHashTablePtr *imports,
7891 const xmlChar *nsName)
7892{
7893 xmlSchemaImportPtr ret;
7894
7895 if (*imports == NULL) {
Daniel Veillardb9e2f262005-01-23 23:48:34 +00007896 *imports = xmlHashCreateDict(10, ctxt->dict);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007897 if (*imports == NULL) {
7898 xmlSchemaPCustomErr(ctxt,
7899 XML_SCHEMAP_FAILED_BUILD_IMPORT,
7900 NULL, NULL, (xmlNodePtr) ctxt->doc,
7901 "Internal error: failed to build the import table",
7902 NULL);
7903 return (NULL);
7904 }
7905 }
7906 ret = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
7907 if (ret == NULL) {
7908 xmlSchemaPErrMemory(NULL, "allocating import struct", NULL);
7909 return (NULL);
7910 }
7911 memset(ret, 0, sizeof(xmlSchemaImport));
7912 if (nsName == NULL)
7913 nsName = XML_SCHEMAS_NO_NAMESPACE;
7914 xmlHashAddEntry(*imports, nsName, ret);
7915
7916 return (ret);
7917}
7918
7919static int
7920xmlSchemaAcquireSchemaDoc(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007921 xmlSchemaPtr schema,
7922 xmlNodePtr node,
7923 const xmlChar *nsName,
7924 const xmlChar *location,
7925 xmlDocPtr *doc,
7926 const xmlChar **targetNamespace,
7927 int absolute)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007928{
7929 xmlParserCtxtPtr parserCtxt;
7930 xmlSchemaImportPtr import;
7931 const xmlChar *ns;
7932 xmlNodePtr root;
7933
7934 /*
7935 * NOTE: This will be used for <import>, <xsi:schemaLocation> and
7936 * <xsi:noNamespaceSchemaLocation>.
7937 */
7938 *doc = NULL;
7939 /*
7940 * Given that the schemaLocation [attribute] is only a hint, it is open
7941 * to applications to ignore all but the first <import> for a given
7942 * namespace, regardless of the ·actual value· of schemaLocation, but
7943 * such a strategy risks missing useful information when new
7944 * schemaLocations are offered.
7945 *
7946 * XSV (ver 2.5-2) does use the first <import> which resolves to a valid schema.
7947 * Xerces-J (ver 2.5.1) ignores all but the first given <import> - regardless if
7948 * valid or not.
7949 * We will follow XSV here.
7950 */
7951 if (location == NULL) {
7952 /*
7953 * Schema Document Location Strategy:
7954 *
7955 * 3 Based on the namespace name, identify an existing schema document,
7956 * either as a resource which is an XML document or a <schema> element
7957 * information item, in some local schema repository;
7958 *
7959 * 5 Attempt to resolve the namespace name to locate such a resource.
7960 *
7961 * NOTE: Those stategies are not supported, so we will skip.
7962 */
7963 return (0);
7964 }
7965 if (nsName == NULL)
7966 ns = XML_SCHEMAS_NO_NAMESPACE;
7967 else
7968 ns = nsName;
7969
7970 import = xmlHashLookup(schema->schemasImports, ns);
7971 if (import != NULL) {
7972 /*
7973 * There was a valid resource for the specified namespace already
7974 * defined, so skip.
7975 * TODO: This might be changed someday to allow import of
7976 * components from multiple documents for a single target namespace.
7977 */
7978 return (0);
7979 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007980
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007981 /*
7982 * Schema Document Location Strategy:
7983 *
7984 * 2 Based on the location URI, identify an existing schema document,
7985 * either as a resource which is an XML document or a <schema> element
7986 * information item, in some local schema repository;
7987 *
7988 * 4 Attempt to resolve the location URI, to locate a resource on the
7989 * web which is or contains or references a <schema> element;
7990 * TODO: Hmm, I don't know if the reference stuff in 4. will work.
7991 *
7992 */
7993 if ((absolute == 0) && (node != NULL)) {
7994 xmlChar *base, *URI;
7995
7996 base = xmlNodeGetBase(node->doc, node);
7997 if (base == NULL) {
7998 URI = xmlBuildURI(location, node->doc->URL);
7999 } else {
8000 URI = xmlBuildURI(location, base);
8001 xmlFree(base);
8002 }
8003 if (URI != NULL) {
8004 location = xmlDictLookup(ctxt->dict, URI, -1);
8005 xmlFree(URI);
8006 }
8007 }
8008 parserCtxt = xmlNewParserCtxt();
8009 if (parserCtxt == NULL) {
8010 xmlSchemaPErrMemory(NULL, "xmlSchemaParseImport: "
8011 "allocating a parser context", NULL);
8012 return(-1);
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00008013 }
8014
8015 if ((ctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
8016 xmlDictFree(parserCtxt->dict);
8017 parserCtxt->dict = ctxt->dict;
8018 xmlDictReference(parserCtxt->dict);
8019 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008020
8021 *doc = xmlCtxtReadFile(parserCtxt, (const char *) location,
8022 NULL, SCHEMAS_PARSE_OPTIONS);
8023
8024 /*
8025 * 2.1 The referent is (a fragment of) a resource which is an
8026 * XML document (see clause 1.1), which in turn corresponds to
8027 * a <schema> element information item in a well-formed information
8028 * set, which in turn corresponds to a valid schema.
8029 * TODO: What to do with the "fragment" stuff?
8030 *
8031 * 2.2 The referent is a <schema> element information item in
8032 * a well-formed information set, which in turn corresponds
8033 * to a valid schema.
8034 * NOTE: 2.2 won't apply, since only XML documents will be processed
8035 * here.
8036 */
8037 if (*doc == NULL) {
8038 xmlErrorPtr lerr;
8039 /*
8040 * It is *not* an error for the application schema reference
8041 * strategy to fail.
8042 *
8043 * If the doc is NULL and the parser error is an IO error we
8044 * will assume that the resource could not be located or accessed.
8045 *
8046 * TODO: Try to find specific error codes to react only on
8047 * localisation failures.
8048 *
8049 * TODO, FIXME: Check the spec: is a namespace added to the imported
8050 * namespaces, even if the schemaLocation did not provide
8051 * a resource? I guess so, since omitting the "schemaLocation"
8052 * attribute, imports a namespace as well.
8053 */
8054 lerr = xmlGetLastError();
8055 if ((lerr != NULL) && (lerr->domain == XML_FROM_IO)) {
8056 xmlFreeParserCtxt(parserCtxt);
8057 return(0);
8058 }
8059
8060 xmlSchemaPCustomErr(ctxt,
8061 XML_SCHEMAP_SRC_IMPORT_2_1,
8062 NULL, NULL, node,
8063 "Failed to parse the resource '%s' for import",
8064 location);
8065 xmlFreeParserCtxt(parserCtxt);
8066 return(XML_SCHEMAP_SRC_IMPORT_2_1);
8067 }
8068 xmlFreeParserCtxt(parserCtxt);
8069
8070 root = xmlDocGetRootElement(*doc);
8071 if (root == NULL) {
8072 xmlSchemaPCustomErr(ctxt,
8073 XML_SCHEMAP_SRC_IMPORT_2_1,
8074 NULL, NULL, node,
8075 "The XML document '%s' to be imported has no document "
8076 "element", location);
8077 xmlFreeDoc(*doc);
8078 *doc = NULL;
8079 return (XML_SCHEMAP_SRC_IMPORT_2_1);
8080 }
8081
8082 xmlSchemaCleanupDoc(ctxt, root);
8083
8084 if (!IS_SCHEMA(root, "schema")) {
8085 xmlSchemaPCustomErr(ctxt,
8086 XML_SCHEMAP_SRC_IMPORT_2_1,
8087 NULL, NULL, node,
8088 "The XML document '%s' to be imported is not a XML schema document",
8089 location);
8090 xmlFreeDoc(*doc);
8091 *doc = NULL;
8092 return (XML_SCHEMAP_SRC_IMPORT_2_1);
8093 }
8094 *targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
8095 /*
8096 * Schema Representation Constraint: Import Constraints and Semantics
8097 */
8098 if (nsName == NULL) {
8099 if (*targetNamespace != NULL) {
8100 xmlSchemaPCustomErr(ctxt,
8101 XML_SCHEMAP_SRC_IMPORT_3_2,
8102 NULL, NULL, node,
8103 "The XML schema to be imported is not expected "
8104 "to have a target namespace; this differs from "
8105 "its target namespace of '%s'", *targetNamespace);
8106 xmlFreeDoc(*doc);
8107 *doc = NULL;
8108 return (XML_SCHEMAP_SRC_IMPORT_3_2);
8109 }
8110 } else {
8111 if (*targetNamespace == NULL) {
8112 xmlSchemaPCustomErr(ctxt,
8113 XML_SCHEMAP_SRC_IMPORT_3_1,
8114 NULL, NULL, node,
8115 "The XML schema to be imported is expected to have a target "
8116 "namespace of '%s'", nsName);
8117 xmlFreeDoc(*doc);
8118 *doc = NULL;
8119 return (XML_SCHEMAP_SRC_IMPORT_3_1);
8120 } else if (!xmlStrEqual(*targetNamespace, nsName)) {
8121 xmlSchemaPCustomErrExt(ctxt,
8122 XML_SCHEMAP_SRC_IMPORT_3_1,
8123 NULL, NULL, node,
8124 "The XML schema to be imported is expected to have a "
8125 "target namespace of '%s'; this differs from "
8126 "its target namespace of '%s'",
8127 nsName, *targetNamespace, NULL);
8128 xmlFreeDoc(*doc);
8129 *doc = NULL;
8130 return (XML_SCHEMAP_SRC_IMPORT_3_1);
8131 }
8132 }
8133
8134 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports), nsName);
8135 if (import == NULL) {
8136 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT,
8137 NULL, NULL, NULL,
8138 "Internal error: xmlSchemaAcquireSchemaDoc, "
8139 "failed to build import table", NULL);
8140 xmlFreeDoc(*doc);
8141 *doc = NULL;
8142 return (-1);
8143 }
8144 import->schemaLocation = location;
8145 import->doc = *doc;
8146 return (0);
8147}
William M. Brack2f2a6632004-08-20 23:09:47 +00008148
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008149static void
8150xmlSchemaParseForImpInc(xmlSchemaParserCtxtPtr pctxt,
8151 xmlSchemaPtr schema,
8152 const xmlChar *targetNamespace,
8153 xmlNodePtr node)
8154{
8155 const xmlChar *oldURL, **oldLocImps, *oldTNS;
8156 int oldFlags, oldNumLocImps, oldSizeLocImps;
8157
8158 /*
8159 * Save and reset the context & schema.
8160 */
8161 oldURL = pctxt->URL;
8162 /* TODO: Is using the doc->URL here correct? */
8163 pctxt->URL = node->doc->URL;
8164 oldLocImps = pctxt->localImports;
8165 pctxt->localImports = NULL;
8166 oldNumLocImps = pctxt->nbLocalImports;
8167 pctxt->nbLocalImports = 0;
8168 oldSizeLocImps = pctxt->sizeLocalImports;
8169 pctxt->sizeLocalImports = 0;
8170 oldFlags = schema->flags;
8171 xmlSchemaClearSchemaDefaults(schema);
8172 oldTNS = schema->targetNamespace;
8173 schema->targetNamespace = targetNamespace;
8174 /*
8175 * Parse the schema.
8176 */
8177 xmlSchemaParseSchemaDefaults(pctxt, schema, node);
8178 xmlSchemaParseSchemaTopLevel(pctxt, schema, node->children);
8179 /*
8180 * Restore the context & schema.
8181 */
8182 schema->flags = oldFlags;
8183 schema->targetNamespace = oldTNS;
8184 if (pctxt->localImports != NULL)
8185 xmlFree((xmlChar *) pctxt->localImports);
8186 pctxt->localImports = oldLocImps;
8187 pctxt->nbLocalImports = oldNumLocImps;
8188 pctxt->sizeLocalImports = oldSizeLocImps;
8189 pctxt->URL = oldURL;
8190}
8191
William M. Brack2f2a6632004-08-20 23:09:47 +00008192/**
8193 * xmlSchemaParseImport:
8194 * @ctxt: a schema validation context
8195 * @schema: the schema being built
8196 * @node: a subtree containing XML Schema informations
8197 *
8198 * parse a XML schema Import definition
8199 * *WARNING* this interface is highly subject to change
8200 *
8201 * Returns 0 in case of success, a positive error code if
8202 * not valid and -1 in case of an internal error.
8203 */
8204static int
8205xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
8206 xmlNodePtr node)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008207{
8208 xmlNodePtr child;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008209 const xmlChar *namespaceName = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00008210 const xmlChar *schemaLocation = NULL;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008211 const xmlChar *targetNamespace;
William M. Brack2f2a6632004-08-20 23:09:47 +00008212 xmlAttrPtr attr;
8213 xmlDocPtr doc;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008214 int ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00008215
8216 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8217 return (-1);
8218
8219 /*
8220 * Check for illegal attributes.
8221 */
8222 attr = node->properties;
8223 while (attr != NULL) {
8224 if (attr->ns == NULL) {
8225 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8226 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
8227 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
8228 xmlSchemaPIllegalAttrErr(ctxt,
8229 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8230 NULL, NULL, attr);
8231 }
8232 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8233 xmlSchemaPIllegalAttrErr(ctxt,
8234 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8235 NULL, NULL, attr);
8236 }
8237 attr = attr->next;
8238 }
8239 /*
8240 * Extract and validate attributes.
8241 */
8242 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
8243 "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008244 &namespaceName) != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008245 xmlSchemaPSimpleTypeErr(ctxt,
8246 XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI,
8247 NULL, NULL, node,
8248 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008249 NULL, namespaceName, NULL, NULL, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00008250 return (XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI);
8251 }
8252
8253 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
8254 "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
8255 &schemaLocation) != 0) {
8256 xmlSchemaPSimpleTypeErr(ctxt,
8257 XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI,
8258 NULL, NULL, node,
8259 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008260 NULL, namespaceName, NULL, NULL, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00008261 return (XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI);
8262 }
8263 /*
8264 * And now for the children...
8265 */
8266 child = node->children;
8267 if (IS_SCHEMA(child, "annotation")) {
8268 /*
8269 * the annotation here is simply discarded ...
8270 */
8271 child = child->next;
8272 }
8273 if (child != NULL) {
8274 xmlSchemaPContentErr(ctxt,
8275 XML_SCHEMAP_UNKNOWN_IMPORT_CHILD,
8276 NULL, NULL, node, child, NULL,
8277 "(annotation?)");
8278 }
8279 /*
8280 * Apply additional constraints.
8281 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008282 if (namespaceName != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008283 /*
8284 * 1.1 If the namespace [attribute] is present, then its ·actual value·
8285 * must not match the ·actual value· of the enclosing <schema>'s
8286 * targetNamespace [attribute].
8287 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008288 if (xmlStrEqual(schema->targetNamespace, namespaceName)) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008289 xmlSchemaPCustomErr(ctxt,
8290 XML_SCHEMAP_SRC_IMPORT_1_1,
8291 NULL, NULL, node,
8292 "The value of the attribute 'namespace' must not match "
8293 "the target namespace '%s' of the importing schema",
8294 schema->targetNamespace);
8295 return (XML_SCHEMAP_SRC_IMPORT_1_1);
8296 }
8297 } else {
8298 /*
8299 * 1.2 If the namespace [attribute] is not present, then the enclosing
8300 * <schema> must have a targetNamespace [attribute].
8301 */
8302 if (schema->targetNamespace == NULL) {
8303 xmlSchemaPCustomErr(ctxt,
8304 XML_SCHEMAP_SRC_IMPORT_1_2,
8305 NULL, NULL, node,
8306 "The attribute 'namespace' must be existent if "
8307 "the importing schema has no target namespace",
8308 NULL);
8309 return (XML_SCHEMAP_SRC_IMPORT_1_2);
8310 }
8311 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008312 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008313 * Add the namespace to the list of locally imported namespace.
8314 */
8315 if (ctxt->localImports == NULL) {
8316 ctxt->localImports = (const xmlChar **) xmlMalloc(10 *
8317 sizeof(const xmlChar*));
8318 ctxt->sizeLocalImports = 10;
8319 ctxt->nbLocalImports = 0;
8320 } else if (ctxt->sizeLocalImports <= ctxt->nbLocalImports) {
8321 ctxt->sizeLocalImports *= 2;
8322 ctxt->localImports = (const xmlChar **) xmlRealloc(
8323 (xmlChar **) ctxt->localImports,
8324 ctxt->sizeLocalImports * sizeof(const xmlChar*));
8325 }
8326 ctxt->localImports[ctxt->nbLocalImports++] = namespaceName;
8327 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008328 * Locate and aquire the schema document.
William M. Brack2f2a6632004-08-20 23:09:47 +00008329 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008330 ret = xmlSchemaAcquireSchemaDoc(ctxt, schema, node, namespaceName,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008331 schemaLocation, &doc, &targetNamespace, 0);
8332 if (ret != 0) {
8333 if (doc != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00008334 xmlFreeDoc(doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008335 return (ret);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008336 } else if (doc != NULL) {
8337 xmlSchemaParseForImpInc(ctxt, schema, targetNamespace,
8338 xmlDocGetRootElement(doc));
William M. Brack2f2a6632004-08-20 23:09:47 +00008339 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008340
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008341 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +00008342}
8343
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008344/**
8345 * xmlSchemaParseInclude:
8346 * @ctxt: a schema validation context
8347 * @schema: the schema being built
8348 * @node: a subtree containing XML Schema informations
8349 *
8350 * parse a XML schema Include definition
8351 *
William M. Bracke7091952004-05-11 15:09:58 +00008352 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008353 * 1 in case of success.
8354 */
8355static int
8356xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
8357 xmlNodePtr node)
8358{
8359 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008360 const xmlChar *schemaLocation, *targetNamespace;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008361 xmlDocPtr doc = NULL;
8362 xmlNodePtr root = NULL;
Daniel Veillardcffc1c72005-03-12 18:54:55 +00008363 xmlSchemaIncludePtr include = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008364 int wasConvertingNs = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00008365 xmlAttrPtr attr;
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00008366 xmlParserCtxtPtr parserCtxt;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008367
8368
8369 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8370 return (-1);
8371
8372 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00008373 * Check for illegal attributes.
8374 */
8375 attr = node->properties;
8376 while (attr != NULL) {
8377 if (attr->ns == NULL) {
8378 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8379 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
8380 xmlSchemaPIllegalAttrErr(ctxt,
8381 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8382 NULL, NULL, attr);
8383 }
8384 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8385 xmlSchemaPIllegalAttrErr(ctxt,
8386 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8387 NULL, NULL, attr);
8388 }
8389 attr = attr->next;
8390 }
8391 /*
8392 * Extract and validate attributes.
8393 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008394 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00008395 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008396 * Preliminary step, extract the URI-Reference for the include and
8397 * make an URI from the base.
8398 */
William M. Brack2f2a6632004-08-20 23:09:47 +00008399 attr = xmlSchemaGetPropNode(node, "schemaLocation");
8400 if (attr != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008401 xmlChar *base = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00008402 xmlChar *uri = NULL;
8403
8404 if (xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
8405 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &schemaLocation) != 0)
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008406 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008407 base = xmlNodeGetBase(node->doc, node);
8408 if (base == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008409 uri = xmlBuildURI(schemaLocation, node->doc->URL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008410 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00008411 uri = xmlBuildURI(schemaLocation, base);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008412 xmlFree(base);
8413 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008414 if (uri == NULL) {
8415 xmlSchemaPErr(ctxt,
8416 node,
8417 XML_SCHEMAP_INTERNAL,
8418 "Internal error: xmlSchemaParseInclude, "
8419 "could not build an URI from the schemaLocation.\n",
8420 NULL, NULL);
8421 goto exit_failure;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008422 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008423 schemaLocation = xmlDictLookup(ctxt->dict, uri, -1);
8424 xmlFree(uri);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008425 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00008426 xmlSchemaPMissingAttrErr(ctxt,
8427 XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI,
8428 NULL, NULL, node, "schemaLocation", NULL);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008429 goto exit_invalid;
8430 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008431 /*
8432 * And now for the children...
8433 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008434 child = node->children;
8435 while (IS_SCHEMA(child, "annotation")) {
8436 /*
8437 * the annotations here are simply discarded ...
8438 */
8439 child = child->next;
8440 }
8441 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008442 xmlSchemaPContentErr(ctxt,
8443 XML_SCHEMAP_UNKNOWN_INCLUDE_CHILD,
8444 NULL, NULL, node, child, NULL,
8445 "(annotation?)");
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008446 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008447 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008448 * Report self-inclusion.
8449 */
8450 if (xmlStrEqual(schemaLocation, ctxt->URL)) {
8451 xmlSchemaPCustomErr(ctxt,
8452 XML_SCHEMAP_SRC_INCLUDE,
8453 NULL, NULL, node,
8454 "The schema document '%s' cannot include itself.",
8455 schemaLocation);
8456 return (XML_SCHEMAP_SRC_INCLUDE);
8457 }
8458 /*
8459 * Check if this one was already processed to avoid incorrect
8460 * duplicate component errors and infinite circular inclusion.
8461 */
8462 include = schema->includes;
8463 while (include != NULL) {
8464 if (xmlStrEqual(include->schemaLocation, schemaLocation)) {
8465 targetNamespace = include->origTargetNamespace;
8466 if (targetNamespace == NULL) {
8467 /*
8468 * Chameleon include: skip only if it was build for
8469 * the targetNamespace of the including schema.
8470 */
8471 if (xmlStrEqual(schema->targetNamespace,
8472 include->targetNamespace)) {
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008473 goto check_targetNamespace;
8474 }
8475 } else {
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008476 goto check_targetNamespace;
8477 }
8478 }
8479 include = include->next;
8480 }
8481 /*
8482 * First step is to parse the input document into an DOM/Infoset
8483 * TODO: Use xmlCtxtReadFile to share the dictionary?
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00008484 */
8485 parserCtxt = xmlNewParserCtxt();
8486 if (parserCtxt == NULL) {
8487 xmlSchemaPErrMemory(NULL, "xmlSchemaParseInclude: "
8488 "allocating a parser context", NULL);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008489 goto exit_failure;
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00008490 }
8491
8492 if ((ctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
8493 xmlDictFree(parserCtxt->dict);
8494 parserCtxt->dict = ctxt->dict;
8495 xmlDictReference(parserCtxt->dict);
8496 }
8497
8498 doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
8499 NULL, SCHEMAS_PARSE_OPTIONS);
8500 xmlFreeParserCtxt(parserCtxt);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008501 if (doc == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008502 /*
8503 * TODO: It is not an error for the ·actual value· of the
8504 * schemaLocation [attribute] to fail to resolve it all, in which
8505 * case no corresponding inclusion is performed.
8506 * So do we need a warning report here?
8507 */
8508 xmlSchemaPCustomErr(ctxt,
8509 XML_SCHEMAP_FAILED_LOAD,
8510 NULL, NULL, node,
8511 "Failed to load the document '%s' for inclusion", schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008512 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008513 }
8514
8515 /*
8516 * Then extract the root of the schema
8517 */
8518 root = xmlDocGetRootElement(doc);
8519 if (root == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008520 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008521 XML_SCHEMAP_NOROOT,
William M. Brack2f2a6632004-08-20 23:09:47 +00008522 NULL, NULL, node,
8523 "The included document '%s' has no document "
8524 "element", schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008525 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008526 }
8527
8528 /*
8529 * Remove all the blank text nodes
8530 */
8531 xmlSchemaCleanupDoc(ctxt, root);
8532
8533 /*
8534 * Check the schemas top level element
8535 */
8536 if (!IS_SCHEMA(root, "schema")) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008537 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008538 XML_SCHEMAP_NOT_SCHEMA,
William M. Brack2f2a6632004-08-20 23:09:47 +00008539 NULL, NULL, node,
8540 "The document '%s' to be included is not a schema document",
8541 schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008542 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008543 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008544
William M. Brack2f2a6632004-08-20 23:09:47 +00008545 targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008546 /*
8547 * 2.1 SII has a targetNamespace [attribute], and its ·actual
8548 * value· is identical to the ·actual value· of the targetNamespace
8549 * [attribute] of SIIÂ’ (which must have such an [attribute]).
8550 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008551check_targetNamespace:
Daniel Veillardc0826a72004-08-10 14:17:33 +00008552 if (targetNamespace != NULL) {
8553 if (schema->targetNamespace == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008554 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008555 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00008556 NULL, NULL, node,
8557 "The target namespace of the included schema "
8558 "'%s' has to be absent, since the including schema "
8559 "has no target namespace",
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008560 schemaLocation);
8561 goto exit_invalid;
William M. Brack2f2a6632004-08-20 23:09:47 +00008562 } else if (!xmlStrEqual(targetNamespace, schema->targetNamespace)) {
8563 xmlSchemaPCustomErrExt(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008564 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00008565 NULL, NULL, node,
8566 "The target namespace '%s' of the included schema '%s' "
8567 "differs from '%s' of the including schema",
8568 targetNamespace, schemaLocation, schema->targetNamespace);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008569 goto exit_invalid;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008570 }
8571 } else if (schema->targetNamespace != NULL) {
8572 if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
8573 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
8574 } else
8575 wasConvertingNs = 1;
8576 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008577
8578 if (include != NULL)
8579 goto exit;
8580
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008581 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008582 * URGENT TODO: If the schema is a chameleon-include then copy the
8583 * components into the including schema and modify the targetNamespace
8584 * of those components, do nothing otherwise.
8585 * NOTE: This is currently worked-around by compiling the chameleon
8586 * for every destinct including targetNamespace; thus not performant at
8587 * the moment.
8588 * TODO: Check when the namespace in wildcards for chameleons needs
8589 * to be converted: before we built wildcard intersections or after.
8590 */
8591 /*
8592 * Register the include.
8593 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008594 include = (xmlSchemaIncludePtr) xmlMalloc(sizeof(xmlSchemaInclude));
8595 if (include == NULL) {
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008596 xmlSchemaPErrMemory(ctxt, "allocating include entry", NULL);
8597 goto exit_failure;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008598 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008599 memset(include, 0, sizeof(xmlSchemaInclude));
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008600 include->next = schema->includes;
8601 schema->includes = include;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008602 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008603 * TODO: Use the resolved URI for the this location, since it might
8604 * differ if using filenames/URIs simultaneosly.
Daniel Veillardc0826a72004-08-10 14:17:33 +00008605 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008606 include->schemaLocation = schemaLocation;
8607 include->doc = doc;
8608 /*
8609 * In case of chameleons, the original target namespace will differ
8610 * from the resulting namespace.
8611 */
8612 include->origTargetNamespace = targetNamespace;
8613 include->targetNamespace = schema->targetNamespace;
8614 /*
8615 * Compile the included schema.
8616 */
8617 xmlSchemaParseForImpInc(ctxt, schema, schema->targetNamespace, root);
8618
8619exit:
Daniel Veillardc0826a72004-08-10 14:17:33 +00008620 /*
8621 * Remove the converting flag.
8622 */
William M. Brack2f2a6632004-08-20 23:09:47 +00008623 if ((wasConvertingNs == 0) &&
8624 (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS))
Daniel Veillardc0826a72004-08-10 14:17:33 +00008625 schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008626 return (1);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008627
8628exit_invalid:
8629 if (doc != NULL) {
8630 if (include != NULL)
8631 include->doc = NULL;
8632 xmlFreeDoc(doc);
8633 }
8634 return (ctxt->err);
8635
8636exit_failure:
8637 if (doc != NULL) {
8638 if (include != NULL)
8639 include->doc = NULL;
8640 xmlFreeDoc(doc);
8641 }
8642 return (-1);
8643
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008644}
8645
8646/**
Daniel Veillard4255d502002-04-16 15:50:10 +00008647 * xmlSchemaParseChoice:
8648 * @ctxt: a schema validation context
8649 * @schema: the schema being built
8650 * @node: a subtree containing XML Schema informations
8651 *
8652 * parse a XML schema Choice definition
8653 * *WARNING* this interface is highly subject to change
8654 *
William M. Bracke7091952004-05-11 15:09:58 +00008655 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00008656 * 1 in case of success.
8657 */
8658static xmlSchemaTypePtr
8659xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008660 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008661{
8662 xmlSchemaTypePtr type, subtype, last = NULL;
8663 xmlNodePtr child = NULL;
8664 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00008665 xmlAttrPtr attr;
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00008666 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00008667
8668 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8669 return (NULL);
8670
8671
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008672 snprintf((char *) name, 30, "#ch%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008673 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00008674 if (type == NULL)
8675 return (NULL);
8676 type->node = node;
8677 type->type = XML_SCHEMA_TYPE_CHOICE;
William M. Brack2f2a6632004-08-20 23:09:47 +00008678 /*
8679 * Check for illegal attributes.
8680 */
8681 attr = node->properties;
8682 while (attr != NULL) {
8683 if (attr->ns == NULL) {
8684 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8685 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
8686 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
8687 xmlSchemaPIllegalAttrErr(ctxt,
8688 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8689 NULL, type, attr);
8690 }
8691 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8692 xmlSchemaPIllegalAttrErr(ctxt,
8693 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8694 NULL, type, attr);
8695 }
8696 attr = attr->next;
8697 }
8698 /*
8699 * Extract and validate attributes.
8700 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00008701 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008702 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
8703 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
8704 "(nonNegativeInteger | unbounded)");
William M. Brack2f2a6632004-08-20 23:09:47 +00008705 /*
8706 * And now for the children...
8707 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00008708 oldcontainer = ctxt->container;
8709 ctxt->container = (const xmlChar *) name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008710 child = node->children;
8711 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008712 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8713 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008714 }
8715 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008716 (IS_SCHEMA(child, "group")) ||
8717 (IS_SCHEMA(child, "any")) ||
8718 (IS_SCHEMA(child, "choice")) ||
8719 (IS_SCHEMA(child, "sequence"))) {
8720 subtype = NULL;
8721 if (IS_SCHEMA(child, "element")) {
8722 subtype = (xmlSchemaTypePtr)
8723 xmlSchemaParseElement(ctxt, schema, child, 0);
8724 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008725 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008726 } else if (IS_SCHEMA(child, "any")) {
8727 subtype = xmlSchemaParseAny(ctxt, schema, child);
8728 } else if (IS_SCHEMA(child, "sequence")) {
8729 subtype = xmlSchemaParseSequence(ctxt, schema, child);
8730 } else if (IS_SCHEMA(child, "choice")) {
8731 subtype = xmlSchemaParseChoice(ctxt, schema, child);
8732 }
8733 if (subtype != NULL) {
8734 if (last == NULL) {
8735 type->subtypes = subtype;
8736 last = subtype;
8737 } else {
8738 last->next = subtype;
8739 last = subtype;
8740 }
8741 last->next = NULL;
8742 }
8743 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008744 }
8745 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008746 /* TODO: error code. */
8747 xmlSchemaPContentErr(ctxt,
8748 XML_SCHEMAP_UNKNOWN_CHOICE_CHILD,
8749 NULL, type, node, child, NULL,
8750 "(annotation?, (element | group | choice | sequence | any)*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00008751 }
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00008752 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00008753 return (type);
8754}
8755
8756/**
8757 * xmlSchemaParseSequence:
8758 * @ctxt: a schema validation context
8759 * @schema: the schema being built
8760 * @node: a subtree containing XML Schema informations
8761 *
8762 * parse a XML schema Sequence definition
8763 * *WARNING* this interface is highly subject to change
8764 *
William M. Bracke7091952004-05-11 15:09:58 +00008765 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00008766 * 1 in case of success.
8767 */
8768static xmlSchemaTypePtr
8769xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008770 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008771{
8772 xmlSchemaTypePtr type, subtype, last = NULL;
8773 xmlNodePtr child = NULL;
8774 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00008775 xmlAttrPtr attr;
8776 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00008777
8778 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8779 return (NULL);
8780
William M. Brack2f2a6632004-08-20 23:09:47 +00008781 oldcontainer = ctxt->container;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008782 snprintf((char *) name, 30, "#seq%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008783 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00008784 if (type == NULL)
8785 return (NULL);
8786 type->node = node;
8787 type->type = XML_SCHEMA_TYPE_SEQUENCE;
William M. Brack2f2a6632004-08-20 23:09:47 +00008788 /*
8789 * Check for illegal attributes.
8790 */
8791 attr = node->properties;
8792 while (attr != NULL) {
8793 if (attr->ns == NULL) {
8794 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8795 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
8796 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
8797 xmlSchemaPIllegalAttrErr(ctxt,
8798 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8799 NULL, type, attr);
8800 }
8801 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8802 xmlSchemaPIllegalAttrErr(ctxt,
8803 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8804 NULL, type, attr);
8805 }
8806 attr = attr->next;
8807 }
8808 /*
8809 * Extract and validate attributes.
8810 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00008811 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008812 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
8813 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
8814 "(nonNegativeInteger | unbounded)");
William M. Brack2f2a6632004-08-20 23:09:47 +00008815 /*
8816 * And now for the children...
8817 */
8818 ctxt->container = (const xmlChar *) name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008819 child = node->children;
8820 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008821 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8822 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008823 }
8824 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008825 (IS_SCHEMA(child, "group")) ||
8826 (IS_SCHEMA(child, "any")) ||
8827 (IS_SCHEMA(child, "choice")) ||
8828 (IS_SCHEMA(child, "sequence"))) {
8829 subtype = NULL;
8830 if (IS_SCHEMA(child, "element")) {
8831 subtype = (xmlSchemaTypePtr)
8832 xmlSchemaParseElement(ctxt, schema, child, 0);
8833 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008834 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008835 } else if (IS_SCHEMA(child, "any")) {
8836 subtype = xmlSchemaParseAny(ctxt, schema, child);
8837 } else if (IS_SCHEMA(child, "choice")) {
8838 subtype = xmlSchemaParseChoice(ctxt, schema, child);
8839 } else if (IS_SCHEMA(child, "sequence")) {
8840 subtype = xmlSchemaParseSequence(ctxt, schema, child);
8841 }
8842 if (subtype != NULL) {
8843 if (last == NULL) {
8844 type->subtypes = subtype;
8845 last = subtype;
8846 } else {
8847 last->next = subtype;
8848 last = subtype;
8849 }
8850 last->next = NULL;
8851 }
8852 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008853 }
8854 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008855 xmlSchemaPContentErr(ctxt,
8856 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
8857 NULL, type, node, child, NULL,
8858 "(annotation?, (element | group | choice | sequence | any)*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00008859 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008860 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00008861
8862 return (type);
8863}
8864
8865/**
8866 * xmlSchemaParseRestriction:
8867 * @ctxt: a schema validation context
8868 * @schema: the schema being built
8869 * @node: a subtree containing XML Schema informations
Daniel Veillard4255d502002-04-16 15:50:10 +00008870 *
8871 * parse a XML schema Restriction definition
8872 * *WARNING* this interface is highly subject to change
8873 *
8874 * Returns the type definition or NULL in case of error
8875 */
8876static xmlSchemaTypePtr
8877xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00008878 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008879{
Daniel Veillard01fa6152004-06-29 17:04:39 +00008880 xmlSchemaTypePtr type, subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00008881 xmlNodePtr child = NULL;
8882 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008883 const xmlChar *oldcontainer;
William M. Brack2f2a6632004-08-20 23:09:47 +00008884 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00008885
8886 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8887 return (NULL);
8888
8889 oldcontainer = ctxt->container;
8890
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008891 snprintf((char *) name, 30, "#restr%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008892 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00008893 if (type == NULL)
8894 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00008895 type->type = XML_SCHEMA_TYPE_RESTRICTION;
Daniel Veillard4255d502002-04-16 15:50:10 +00008896 type->node = node;
William M. Brack2f2a6632004-08-20 23:09:47 +00008897 /*
8898 * Check for illegal attributes.
8899 */
8900 attr = node->properties;
8901 while (attr != NULL) {
8902 if (attr->ns == NULL) {
8903 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8904 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
8905 xmlSchemaPIllegalAttrErr(ctxt,
8906 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8907 NULL, type, attr);
8908 }
8909 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8910 xmlSchemaPIllegalAttrErr(ctxt,
8911 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8912 NULL, type, attr);
8913 }
8914 attr = attr->next;
8915 }
8916 /*
8917 * Extract and validate attributes.
8918 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00008919 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00008920 /*
8921 * Attribute "base".
8922 */
Daniel Veillard4255d502002-04-16 15:50:10 +00008923 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
Daniel Veillard01fa6152004-06-29 17:04:39 +00008924 if ((type->base == NULL) &&
William M. Brack2f2a6632004-08-20 23:09:47 +00008925 (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX)) {
8926 /* TODO: Think about the error code. */
8927 xmlSchemaPMissingAttrErr(ctxt,
8928 XML_SCHEMAP_RESTRICTION_NONAME_NOREF,
8929 NULL, type, node, "base", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008930 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008931 /*
8932 * And now for the children...
8933 */
Daniel Veillard4255d502002-04-16 15:50:10 +00008934 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008935 child = node->children;
8936 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008937 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8938 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008939 }
8940 subtype = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008941 if (ctxt->parentItem->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
8942 if (IS_SCHEMA(child, "all")) {
8943 subtype = (xmlSchemaTypePtr)
8944 xmlSchemaParseAll(ctxt, schema, child);
8945 child = child->next;
8946 type->subtypes = subtype;
8947 } else if (IS_SCHEMA(child, "choice")) {
8948 subtype = xmlSchemaParseChoice(ctxt, schema, child);
8949 child = child->next;
8950 type->subtypes = subtype;
8951 } else if (IS_SCHEMA(child, "sequence")) {
8952 subtype = (xmlSchemaTypePtr)
8953 xmlSchemaParseSequence(ctxt, schema, child);
8954 child = child->next;
8955 type->subtypes = subtype;
8956 } else if (IS_SCHEMA(child, "group")) {
8957 subtype = (xmlSchemaTypePtr)
8958 xmlSchemaParseGroup(ctxt, schema, child, 0);
8959 child = child->next;
8960 type->subtypes = subtype;
8961 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008962 } else if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_SIMPLE) {
8963 if (IS_SCHEMA(child, "simpleType")) {
8964 if (type->base != NULL) {
8965 /*
8966 * src-restriction-base-or-simpleType
8967 * Either the base [attribute] or the simpleType [child] of the
8968 * <restriction> element must be present, but not both.
8969 */
8970 xmlSchemaPContentErr(ctxt,
8971 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
8972 NULL, NULL, type->node, child,
8973 "The attribute 'base' and the <simpleType> child are "
8974 "mutually exclusive", NULL);
8975 } else {
8976 subtype = (xmlSchemaTypePtr)
8977 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
8978 type->baseType = subtype;
8979 }
8980 child = child->next;
8981 }
8982 } else if (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00008983 if (IS_SCHEMA(child, "simpleType")) {
8984 subtype = (xmlSchemaTypePtr)
8985 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008986 type->subtypes = subtype;
8987 child = child->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00008988 }
8989 }
8990 if ((ctxt->ctxtType->type == XML_SCHEMA_TYPE_SIMPLE) ||
8991 (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
8992 xmlSchemaFacetPtr facet, lastfacet = NULL;
8993
Daniel Veillard01fa6152004-06-29 17:04:39 +00008994 /*
8995 * Add the facets to the parent simpleType/complexType.
8996 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00008997 /*
8998 * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
8999 * Simple Type Definition Schema Representation Constraint:
9000 * *Single Facet Value*
9001 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00009002 while ((IS_SCHEMA(child, "minInclusive")) ||
9003 (IS_SCHEMA(child, "minExclusive")) ||
9004 (IS_SCHEMA(child, "maxInclusive")) ||
9005 (IS_SCHEMA(child, "maxExclusive")) ||
9006 (IS_SCHEMA(child, "totalDigits")) ||
9007 (IS_SCHEMA(child, "fractionDigits")) ||
9008 (IS_SCHEMA(child, "pattern")) ||
9009 (IS_SCHEMA(child, "enumeration")) ||
9010 (IS_SCHEMA(child, "whiteSpace")) ||
9011 (IS_SCHEMA(child, "length")) ||
9012 (IS_SCHEMA(child, "maxLength")) ||
9013 (IS_SCHEMA(child, "minLength"))) {
9014 facet = xmlSchemaParseFacet(ctxt, schema, child);
9015 if (facet != NULL) {
9016 if (lastfacet == NULL)
9017 ctxt->ctxtType->facets = facet;
9018 else
9019 lastfacet->next = facet;
9020 lastfacet = facet;
9021 lastfacet->next = NULL;
9022 }
9023 child = child->next;
9024 }
9025 /*
9026 * Create links for derivation and validation.
9027 */
9028 if (lastfacet != NULL) {
9029 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
9030
9031 facet = ctxt->ctxtType->facets;
9032 do {
9033 facetLink = (xmlSchemaFacetLinkPtr) xmlMalloc(sizeof(xmlSchemaFacetLink));
9034 if (facetLink == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009035 xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009036 xmlFree(facetLink);
9037 return (NULL);
9038 }
9039 facetLink->facet = facet;
9040 facetLink->next = NULL;
9041 if (lastFacetLink == NULL)
9042 ctxt->ctxtType->facetSet = facetLink;
9043 else
9044 lastFacetLink->next = facetLink;
9045 lastFacetLink = facetLink;
9046 facet = facet->next;
9047 } while (facet != NULL);
9048 }
9049 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009050 if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX) {
9051 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
9052 if (IS_SCHEMA(child, "anyAttribute")) {
9053 ctxt->ctxtType->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
9054 child = child->next;
9055 }
9056 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009057 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009058 /* TODO: Think about the error code. */
9059 if (ctxt->parentItem->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
9060 xmlSchemaPContentErr(ctxt,
9061 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
9062 NULL, type, node, child, NULL,
9063 "annotation?, (group | all | choice | sequence)?, "
9064 "((attribute | attributeGroup)*, anyAttribute?))");
9065 } else if (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
9066 xmlSchemaPContentErr(ctxt,
9067 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
9068 NULL, type, node, child, NULL,
9069 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
9070 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
9071 "length | minLength | maxLength | enumeration | whiteSpace | "
9072 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
9073 } else {
9074 /* Simple type */
9075 xmlSchemaPContentErr(ctxt,
9076 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
9077 NULL, type, node, child, NULL,
9078 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
9079 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
9080 "length | minLength | maxLength | enumeration | whiteSpace | "
9081 "pattern)*))");
9082 }
9083 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009084 ctxt->container = oldcontainer;
9085 return (type);
9086}
9087
9088/**
9089 * xmlSchemaParseExtension:
9090 * @ctxt: a schema validation context
9091 * @schema: the schema being built
9092 * @node: a subtree containing XML Schema informations
9093 *
9094 * parse a XML schema Extension definition
9095 * *WARNING* this interface is highly subject to change
9096 *
9097 * Returns the type definition or NULL in case of error
9098 */
9099static xmlSchemaTypePtr
9100xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009101 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00009102{
9103 xmlSchemaTypePtr type, subtype;
9104 xmlNodePtr child = NULL;
9105 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009106 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00009107
9108 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9109 return (NULL);
9110
9111 oldcontainer = ctxt->container;
9112
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00009113 snprintf((char *) name, 30, "#ext%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00009114 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00009115 if (type == NULL)
9116 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00009117 type->type = XML_SCHEMA_TYPE_EXTENSION;
Daniel Veillard4255d502002-04-16 15:50:10 +00009118 type->node = node;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00009119
9120 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
9121
Daniel Veillard4255d502002-04-16 15:50:10 +00009122 ctxt->container = name;
9123
9124 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
9125 if (type->base == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009126 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_EXTENSION_NO_BASE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009127 "<extension>: The attribute \"base\" is missing.\n",
9128 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009129 }
9130 child = node->children;
9131 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009132 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
9133 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009134 }
9135 subtype = NULL;
9136
9137 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009138 subtype = xmlSchemaParseAll(ctxt, schema, child);
9139 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009140 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009141 subtype = xmlSchemaParseChoice(ctxt, schema, child);
9142 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009143 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009144 subtype = xmlSchemaParseSequence(ctxt, schema, child);
9145 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009146 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009147 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009148 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009149 }
9150 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009151 type->subtypes = subtype;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009152 if ((ctxt->ctxtType != NULL) &&
9153 (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX)) {
9154 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
9155 if (IS_SCHEMA(child, "anyAttribute")) {
9156 ctxt->ctxtType->attributeWildcard =
9157 xmlSchemaParseAnyAttribute(ctxt, schema, child);
9158 child = child->next;
9159 }
9160 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009161 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009162 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009163 XML_SCHEMAP_UNKNOWN_EXTENSION_CHILD,
9164 "<extension> has unexpected content.\n", type->name,
9165 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009166 }
9167 ctxt->container = oldcontainer;
9168 return (type);
9169}
9170
9171/**
9172 * xmlSchemaParseSimpleContent:
9173 * @ctxt: a schema validation context
9174 * @schema: the schema being built
9175 * @node: a subtree containing XML Schema informations
9176 *
9177 * parse a XML schema SimpleContent definition
9178 * *WARNING* this interface is highly subject to change
9179 *
9180 * Returns the type definition or NULL in case of error
9181 */
9182static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009183xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
9184 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00009185{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009186 xmlSchemaTypePtr type, subtype, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00009187 xmlNodePtr child = NULL;
9188 xmlChar name[30];
9189
9190 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9191 return (NULL);
9192
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00009193 snprintf((char *) name, 30, "#SC%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00009194 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00009195 if (type == NULL)
9196 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00009197 type->type = XML_SCHEMA_TYPE_SIMPLE_CONTENT;
Daniel Veillard4255d502002-04-16 15:50:10 +00009198 type->node = node;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00009199
9200 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00009201
9202 child = node->children;
9203 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009204 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
9205 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009206 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009207 oldParentItem = ctxt->parentItem;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009208 ctxt->parentItem = type;
9209 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00009210 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009211 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009212 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009213 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009214 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009215 subtype = (xmlSchemaTypePtr)
9216 xmlSchemaParseExtension(ctxt, schema, child);
9217 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009218 }
9219 type->subtypes = subtype;
9220 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009221 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009222 XML_SCHEMAP_UNKNOWN_SIMPLECONTENT_CHILD,
9223 "<simpleContent> has unexpected content.\n",
9224 NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009225 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009226 ctxt->parentItem = oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00009227 return (type);
9228}
9229
9230/**
9231 * xmlSchemaParseComplexContent:
9232 * @ctxt: a schema validation context
9233 * @schema: the schema being built
9234 * @node: a subtree containing XML Schema informations
9235 *
9236 * parse a XML schema ComplexContent definition
9237 * *WARNING* this interface is highly subject to change
9238 *
9239 * Returns the type definition or NULL in case of error
9240 */
9241static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009242xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
9243 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00009244{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009245 xmlSchemaTypePtr type, subtype, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00009246 xmlNodePtr child = NULL;
9247 xmlChar name[30];
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009248 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00009249
9250 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9251 return (NULL);
9252
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00009253 snprintf((char *) name, 30, "#CC%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00009254 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00009255 if (type == NULL)
9256 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00009257 type->type = XML_SCHEMA_TYPE_COMPLEX_CONTENT;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009258 type->node = node;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009259 /*
9260 * Check for illegal attributes.
9261 */
9262 attr = node->properties;
9263 while (attr != NULL) {
9264 if (attr->ns == NULL) {
9265 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9266 (!xmlStrEqual(attr->name, BAD_CAST "mixed")))
9267 {
9268 xmlSchemaPIllegalAttrErr(ctxt,
9269 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9270 NULL, NULL, attr);
9271 }
9272 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9273 xmlSchemaPIllegalAttrErr(ctxt,
9274 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9275 NULL, NULL, attr);
9276 }
9277 attr = attr->next;
9278 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00009279
9280 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
9281
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009282 /*
9283 * Handle attribute 'mixed'.
9284 */
9285 if (xmlGetBooleanProp(ctxt, NULL, type, node, "mixed", 0)) {
9286 if ((ctxt->ctxtType->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
9287 ctxt->ctxtType->flags |= XML_SCHEMAS_TYPE_MIXED;
9288 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009289 child = node->children;
9290 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009291 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
9292 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009293 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009294 oldParentItem = ctxt->parentItem;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009295 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00009296 subtype = NULL;
9297 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009298 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009299 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009300 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009301 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009302 subtype = (xmlSchemaTypePtr)
9303 xmlSchemaParseExtension(ctxt, schema, child);
9304 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009305 }
9306 type->subtypes = subtype;
9307 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009308 xmlSchemaPContentErr(ctxt,
9309 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9310 NULL, NULL, node, child,
9311 NULL, "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +00009312 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009313 ctxt->parentItem = oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00009314 return (type);
9315}
9316
9317/**
9318 * xmlSchemaParseComplexType:
9319 * @ctxt: a schema validation context
9320 * @schema: the schema being built
9321 * @node: a subtree containing XML Schema informations
9322 *
9323 * parse a XML schema Complex Type definition
9324 * *WARNING* this interface is highly subject to change
9325 *
9326 * Returns the type definition or NULL in case of error
9327 */
9328static xmlSchemaTypePtr
9329xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00009330 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00009331{
Daniel Veillard01fa6152004-06-29 17:04:39 +00009332 xmlSchemaTypePtr type, subtype, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00009333 xmlNodePtr child = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009334 const xmlChar *name = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00009335 const xmlChar *oldcontainer;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009336 xmlAttrPtr attr;
9337 const xmlChar *attrValue;
9338 xmlChar *des = NULL; /* The reported designation. */
Daniel Veillard1a380b82004-10-21 16:00:06 +00009339 char buf[40];
9340
Daniel Veillard4255d502002-04-16 15:50:10 +00009341
9342 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9343 return (NULL);
9344
Daniel Veillard01fa6152004-06-29 17:04:39 +00009345 ctxtType = ctxt->ctxtType;
9346
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009347 if (topLevel) {
9348 attr = xmlSchemaGetPropNode(node, "name");
9349 if (attr == NULL) {
9350 xmlSchemaPMissingAttrErr(ctxt,
9351 XML_SCHEMAP_S4S_ATTR_MISSING,
9352 (xmlChar **) &xmlSchemaElemDesCT, NULL, node,
9353 "name", NULL);
9354 return (NULL);
9355 } else if (xmlSchemaPValAttrNode(ctxt,
9356 (xmlChar **) &xmlSchemaElemDesCT, NULL, attr,
9357 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
9358 return (NULL);
9359 }
9360 }
9361
9362 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009363 /*
9364 * Parse as local complex type definition.
9365 */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00009366 snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009367 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
9368 if (type == NULL)
9369 return (NULL);
9370 name = (const xmlChar *) buf;
9371 type->node = node;
9372 type->type = XML_SCHEMA_TYPE_COMPLEX;
9373 /*
9374 * TODO: We need the target namespace.
9375 */
9376 } else {
9377 /*
9378 * Parse as global complex type definition.
9379 */
William M. Brack2f2a6632004-08-20 23:09:47 +00009380 type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace, node);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009381 if (type == NULL)
9382 return (NULL);
9383 type->node = node;
9384 type->type = XML_SCHEMA_TYPE_COMPLEX;
9385 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
9386 /*
9387 * Set defaults.
9388 */
9389 type->flags |= XML_SCHEMAS_TYPE_FINAL_DEFAULT;
9390 type->flags |= XML_SCHEMAS_TYPE_BLOCK_DEFAULT;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00009391 }
9392 type->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009393 /*
9394 * Handle attributes.
9395 */
9396 attr = node->properties;
9397 while (attr != NULL) {
9398 if (attr->ns == NULL) {
9399 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
9400 /*
9401 * Attribute "id".
9402 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00009403 xmlSchemaPValAttrID(ctxt, NULL, type, node,
9404 BAD_CAST "id");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009405 } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
9406 /*
9407 * Attribute "mixed".
9408 */
9409 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
9410 (xmlNodePtr) attr))
9411 type->flags |= XML_SCHEMAS_TYPE_MIXED;
9412 } else if (topLevel) {
9413 /*
9414 * Attributes of global complex type definitions.
9415 */
9416 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
9417 /* Pass. */
9418 } else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
9419 /*
9420 * Attribute "abstract".
9421 */
9422 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
9423 (xmlNodePtr) attr))
9424 type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
9425 } else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
9426 /*
9427 * Attribute "final".
9428 */
9429 attrValue = xmlSchemaGetNodeContent(ctxt,
9430 (xmlNodePtr) attr);
9431 if (xmlSchemaPValAttrBlockFinal(attrValue,
9432 &(type->flags),
9433 -1,
9434 XML_SCHEMAS_TYPE_FINAL_EXTENSION,
9435 XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
9436 -1, -1, -1) != 0)
9437 {
9438 xmlSchemaPSimpleTypeErr(ctxt,
9439 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9440 &des, type, (xmlNodePtr) attr,
9441 NULL,
9442 "(#all | List of (extension | restriction))",
9443 attrValue, NULL, NULL, NULL);
9444 }
9445 } else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
9446 /*
9447 * Attribute "block".
9448 */
9449 attrValue = xmlSchemaGetNodeContent(ctxt,
9450 (xmlNodePtr) attr);
9451 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
9452 -1,
9453 XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
9454 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
9455 -1, -1, -1) != 0) {
9456 xmlSchemaPSimpleTypeErr(ctxt,
9457 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9458 &des, type, (xmlNodePtr) attr,
9459 NULL,
9460 "(#all | List of (extension | restriction)) ",
9461 attrValue, NULL, NULL, NULL);
9462 }
9463 } else {
9464 xmlSchemaPIllegalAttrErr(ctxt,
9465 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9466 &des, type, attr);
9467 }
9468 } else {
9469 xmlSchemaPIllegalAttrErr(ctxt,
9470 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9471 &des, type, attr);
9472 }
9473 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9474 xmlSchemaPIllegalAttrErr(ctxt,
9475 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9476 &des, type, attr);
9477 }
9478 attr = attr->next;
9479 }
9480 /*
9481 * Set as default for attribute wildcards.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009482 * This will be only changed if a complex type
9483 * inherits an attribute wildcard from a base type.
9484 */
9485 type->flags |= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009486 /*
9487 * And now for the children...
9488 */
9489 oldcontainer = ctxt->container;
9490 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +00009491 child = node->children;
9492 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009493 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
9494 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009495 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00009496 ctxt->ctxtType = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00009497 if (IS_SCHEMA(child, "simpleContent")) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009498 /*
9499 * 3.4.3 : 2.2
9500 * Specifying mixed='true' when the <simpleContent>
9501 * alternative is chosen has no effect
9502 */
William M. Bracke7091952004-05-11 15:09:58 +00009503 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
9504 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009505 type->subtypes = xmlSchemaParseSimpleContent(ctxt, schema, child);
9506 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009507 } else if (IS_SCHEMA(child, "complexContent")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009508 type->subtypes = xmlSchemaParseComplexContent(ctxt, schema, child);
9509 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009510 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009511 subtype = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009512 /*
9513 * Parse model groups.
9514 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009515 if (IS_SCHEMA(child, "all")) {
9516 subtype = xmlSchemaParseAll(ctxt, schema, child);
9517 child = child->next;
9518 } else if (IS_SCHEMA(child, "choice")) {
9519 subtype = xmlSchemaParseChoice(ctxt, schema, child);
9520 child = child->next;
9521 } else if (IS_SCHEMA(child, "sequence")) {
9522 subtype = xmlSchemaParseSequence(ctxt, schema, child);
9523 child = child->next;
9524 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009525 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009526 child = child->next;
9527 }
9528 if (subtype != NULL)
9529 type->subtypes = subtype;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009530 /*
9531 * Parse attribute decls/refs.
9532 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009533 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009534 /*
9535 * Parse attribute wildcard.
9536 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009537 if (IS_SCHEMA(child, "anyAttribute")) {
9538 type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
9539 child = child->next;
9540 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009541 }
9542 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009543 xmlSchemaPContentErr(ctxt,
9544 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9545 &des, type, node, child,
9546 NULL, "(annotation?, (simpleContent | complexContent | "
9547 "((group | all | choice | sequence)?, ((attribute | "
9548 "attributeGroup)*, anyAttribute?))))");
Daniel Veillard4255d502002-04-16 15:50:10 +00009549 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009550 FREE_AND_NULL(des);
Daniel Veillard4255d502002-04-16 15:50:10 +00009551 ctxt->container = oldcontainer;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009552 ctxt->ctxtType = ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00009553 return (type);
9554}
9555
Daniel Veillard4255d502002-04-16 15:50:10 +00009556/**
9557 * xmlSchemaParseSchema:
9558 * @ctxt: a schema validation context
9559 * @node: a subtree containing XML Schema informations
9560 *
9561 * parse a XML schema definition from a node set
9562 * *WARNING* this interface is highly subject to change
9563 *
9564 * Returns the internal XML Schema structure built from the resource or
9565 * NULL in case of error
9566 */
9567static xmlSchemaPtr
9568xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
9569{
9570 xmlSchemaPtr schema = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009571 const xmlChar *val;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00009572 int nberrors;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009573 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00009574
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009575 /*
9576 * This one is called by xmlSchemaParse only and is used if
9577 * the schema to be parsed was specified via the API; i.e. not
9578 * automatically by the validated instance document.
9579 */
Daniel Veillard4255d502002-04-16 15:50:10 +00009580 if ((ctxt == NULL) || (node == NULL))
9581 return (NULL);
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00009582 nberrors = ctxt->nberrors;
9583 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00009584 if (IS_SCHEMA(node, "schema")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009585 xmlSchemaImportPtr import;
9586
Daniel Veillard4255d502002-04-16 15:50:10 +00009587 schema = xmlSchemaNewSchema(ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009588 if (schema == NULL)
9589 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009590 /*
9591 * Disable build of list of items.
9592 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00009593 attr = xmlSchemaGetPropNode(node, "targetNamespace");
9594 if (attr != NULL) {
9595 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
9596 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &val);
9597 /*
9598 * TODO: Should we proceed with an invalid target namespace?
9599 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009600 schema->targetNamespace = xmlDictLookup(ctxt->dict, val, -1);
9601 } else {
9602 schema->targetNamespace = NULL;
9603 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009604 /*
9605 * Add the current ns name and location to the import table;
9606 * this is needed to have a consistent mechanism, regardless
9607 * if all schemata are constructed dynamically fired by the
9608 * instance or if the schema to be used was specified via
9609 * the API.
9610 */
9611 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports),
9612 schema->targetNamespace);
9613 if (import == NULL) {
9614 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT,
9615 NULL, NULL, (xmlNodePtr) ctxt->doc,
9616 "Internal error: xmlSchemaParseSchema, "
9617 "failed to add an import entry", NULL);
9618 xmlSchemaFree(schema);
9619 schema = NULL;
9620 return (NULL);
9621 }
9622 import->schemaLocation = ctxt->URL;
9623 /*
9624 * NOTE: We won't set the doc here, otherwise it will be freed
9625 * if the import struct is freed.
9626 * import->doc = ctxt->doc;
9627 */
William M. Brack2f2a6632004-08-20 23:09:47 +00009628 xmlSchemaParseSchemaDefaults(ctxt, schema, node);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009629 xmlSchemaParseSchemaTopLevel(ctxt, schema, node->children);
9630 } else {
9631 xmlDocPtr doc;
9632
9633 doc = node->doc;
9634
9635 if ((doc != NULL) && (doc->URL != NULL)) {
9636 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
9637 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009638 "The file \"%s\" is not a XML schema.\n", doc->URL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009639 } else {
9640 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
9641 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009642 "The file is not a XML schema.\n", NULL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009643 }
9644 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009645 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00009646 if (ctxt->nberrors != 0) {
9647 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009648 xmlSchemaFree(schema);
9649 schema = NULL;
9650 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00009651 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009652 if (schema != NULL)
9653 schema->counter = ctxt->counter;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00009654 ctxt->nberrors = nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00009655#ifdef DEBUG
9656 if (schema == NULL)
9657 xmlGenericError(xmlGenericErrorContext,
9658 "xmlSchemaParse() failed\n");
9659#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00009660 return (schema);
9661}
9662
9663/************************************************************************
9664 * *
9665 * Validating using Schemas *
9666 * *
9667 ************************************************************************/
9668
9669/************************************************************************
9670 * *
9671 * Reading/Writing Schemas *
9672 * *
9673 ************************************************************************/
9674
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009675#if 0 /* Will be enabled if it is clear what options are needed. */
9676/**
9677 * xmlSchemaParserCtxtSetOptions:
9678 * @ctxt: a schema parser context
9679 * @options: a combination of xmlSchemaParserOption
9680 *
9681 * Sets the options to be used during the parse.
9682 *
9683 * Returns 0 in case of success, -1 in case of an
9684 * API error.
9685 */
9686static int
9687xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
9688 int options)
9689
9690{
9691 int i;
9692
9693 if (ctxt == NULL)
9694 return (-1);
9695 /*
9696 * WARNING: Change the start value if adding to the
9697 * xmlSchemaParseOption.
9698 */
9699 for (i = 1; i < (int) sizeof(int) * 8; i++) {
9700 if (options & 1<<i) {
9701 return (-1);
9702 }
9703 }
9704 ctxt->options = options;
9705 return (0);
9706}
9707
9708/**
9709 * xmlSchemaValidCtxtGetOptions:
9710 * @ctxt: a schema parser context
9711 *
9712 * Returns the option combination of the parser context.
9713 */
9714static int
9715xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
9716
9717{
9718 if (ctxt == NULL)
9719 return (-1);
9720 else
9721 return (ctxt->options);
9722}
9723
9724 void *curItems; /* used for dynamic addition of schemata */
9725 int nbCurItems; /* used for dynamic addition of schemata */
9726 int sizeCurItems; /* used for dynamic addition of schemata */
9727
9728#endif
9729
Daniel Veillard4255d502002-04-16 15:50:10 +00009730/**
9731 * xmlSchemaNewParserCtxt:
9732 * @URL: the location of the schema
9733 *
9734 * Create an XML Schemas parse context for that file/resource expected
9735 * to contain an XML Schemas file.
9736 *
9737 * Returns the parser context or NULL in case of error
9738 */
9739xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009740xmlSchemaNewParserCtxt(const char *URL)
9741{
Daniel Veillard4255d502002-04-16 15:50:10 +00009742 xmlSchemaParserCtxtPtr ret;
9743
9744 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009745 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009746
9747 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9748 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009749 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009750 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009751 return (NULL);
9752 }
9753 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009754 ret->dict = xmlDictCreate();
9755 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00009756 ret->includes = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00009757 return (ret);
9758}
9759
9760/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009761 * xmlSchemaNewParserCtxtUseDict:
9762 * @URL: the location of the schema
9763 * @dict: the dictionary to be used
9764 *
9765 * Create an XML Schemas parse context for that file/resource expected
9766 * to contain an XML Schemas file.
9767 *
9768 * Returns the parser context or NULL in case of error
9769 */
9770static xmlSchemaParserCtxtPtr
9771xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
9772{
9773 xmlSchemaParserCtxtPtr ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009774 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009775 if (URL == NULL)
9776 return (NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009777 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009778
9779 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9780 if (ret == NULL) {
9781 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
9782 NULL);
9783 return (NULL);
9784 }
9785 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
9786 ret->dict = dict;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009787 xmlDictReference(dict);
9788 if (URL != NULL)
9789 ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009790 ret->includes = 0;
9791 return (ret);
9792}
9793
9794
9795/**
Daniel Veillard6045c902002-10-09 21:13:59 +00009796 * xmlSchemaNewMemParserCtxt:
9797 * @buffer: a pointer to a char array containing the schemas
9798 * @size: the size of the array
9799 *
9800 * Create an XML Schemas parse context for that memory buffer expected
9801 * to contain an XML Schemas file.
9802 *
9803 * Returns the parser context or NULL in case of error
9804 */
9805xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009806xmlSchemaNewMemParserCtxt(const char *buffer, int size)
9807{
Daniel Veillard6045c902002-10-09 21:13:59 +00009808 xmlSchemaParserCtxtPtr ret;
9809
9810 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009811 return (NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00009812
9813 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9814 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009815 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009816 NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00009817 return (NULL);
9818 }
9819 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
9820 ret->buffer = buffer;
9821 ret->size = size;
William M. Brackcf9eadf2003-12-25 13:24:05 +00009822 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +00009823 return (ret);
9824}
9825
9826/**
Daniel Veillard9d751502003-10-29 13:21:47 +00009827 * xmlSchemaNewDocParserCtxt:
9828 * @doc: a preparsed document tree
9829 *
9830 * Create an XML Schemas parse context for that document.
9831 * NB. The document may be modified during the parsing process.
9832 *
9833 * Returns the parser context or NULL in case of error
9834 */
9835xmlSchemaParserCtxtPtr
9836xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
9837{
9838 xmlSchemaParserCtxtPtr ret;
9839
9840 if (doc == NULL)
9841 return (NULL);
9842
9843 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9844 if (ret == NULL) {
9845 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
9846 NULL);
9847 return (NULL);
9848 }
9849 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
9850 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +00009851 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +00009852 /* The application has responsibility for the document */
9853 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +00009854
9855 return (ret);
9856}
9857
9858/**
Daniel Veillard4255d502002-04-16 15:50:10 +00009859 * xmlSchemaFreeParserCtxt:
9860 * @ctxt: the schema parser context
9861 *
9862 * Free the resources associated to the schema parser context
9863 */
9864void
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009865xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
9866{
Daniel Veillard4255d502002-04-16 15:50:10 +00009867 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009868 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +00009869 if (ctxt->doc != NULL && !ctxt->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009870 xmlFreeDoc(ctxt->doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009871 if (ctxt->assemble != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009872 xmlFree((xmlSchemaTypePtr *) ctxt->assemble->items);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009873 xmlFree(ctxt->assemble);
9874 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009875 if (ctxt->vctxt != NULL) {
9876 xmlSchemaFreeValidCtxt(ctxt->vctxt);
9877 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009878 if (ctxt->localImports != NULL)
9879 xmlFree((xmlChar *) ctxt->localImports);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009880 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00009881 xmlFree(ctxt);
9882}
9883
9884/************************************************************************
9885 * *
9886 * Building the content models *
9887 * *
9888 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009889
Daniel Veillard4255d502002-04-16 15:50:10 +00009890/**
9891 * xmlSchemaBuildAContentModel:
9892 * @type: the schema type definition
9893 * @ctxt: the schema parser context
9894 * @name: the element name whose content is being built
9895 *
9896 * Generate the automata sequence needed for that type
9897 */
9898static void
9899xmlSchemaBuildAContentModel(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009900 xmlSchemaParserCtxtPtr ctxt,
9901 const xmlChar * name)
9902{
Daniel Veillard4255d502002-04-16 15:50:10 +00009903 if (type == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009904 xmlGenericError(xmlGenericErrorContext,
9905 "Found unexpected type = NULL in %s content model\n",
9906 name);
9907 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00009908 }
9909 switch (type->type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009910 case XML_SCHEMA_TYPE_ANY: {
9911 xmlAutomataStatePtr start, end;
9912 xmlSchemaWildcardPtr wild;
9913 xmlSchemaWildcardNsPtr ns;
Daniel Veillard32370232002-10-16 14:08:14 +00009914
Daniel Veillardc0826a72004-08-10 14:17:33 +00009915 wild = type->attributeWildcard;
9916
9917 if (wild == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00009918 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009919 "Internal error: xmlSchemaBuildAContentModel, "
9920 "no wildcard on xsd:any.\n", NULL, NULL);
9921 return;
9922 }
9923
9924 start = ctxt->state;
9925 end = xmlAutomataNewState(ctxt->am);
9926
9927 if (type->maxOccurs == 1) {
9928 if (wild->any == 1) {
9929 /*
9930 * We need to add both transitions:
9931 *
9932 * 1. the {"*", "*"} for elements in a namespace.
9933 */
9934 ctxt->state =
9935 xmlAutomataNewTransition2(ctxt->am,
9936 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
9937 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9938 /*
9939 * 2. the {"*"} for elements in no namespace.
9940 */
9941 ctxt->state =
9942 xmlAutomataNewTransition2(ctxt->am,
9943 start, NULL, BAD_CAST "*", NULL, type);
9944 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9945
9946 } else if (wild->nsSet != NULL) {
9947 ns = wild->nsSet;
9948 do {
9949 ctxt->state = start;
9950 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9951 ctxt->state, NULL, BAD_CAST "*", ns->value, type);
9952 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9953 ns = ns->next;
9954 } while (ns != NULL);
9955
9956 } else if (wild->negNsSet != NULL) {
9957 xmlAutomataStatePtr deadEnd;
9958
9959 deadEnd = xmlAutomataNewState(ctxt->am);
9960 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9961 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, type);
9962 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9963 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
9964 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9965 }
9966 } else {
9967 int counter;
9968 xmlAutomataStatePtr hop;
9969 int maxOccurs =
9970 type->maxOccurs == UNBOUNDED ? UNBOUNDED : type->maxOccurs - 1;
9971 int minOccurs =
9972 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
9973
9974 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
9975 hop = xmlAutomataNewState(ctxt->am);
9976 if (wild->any == 1) {
9977 ctxt->state =
9978 xmlAutomataNewTransition2(ctxt->am,
9979 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
9980 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
9981 ctxt->state =
9982 xmlAutomataNewTransition2(ctxt->am,
9983 start, NULL, BAD_CAST "*", NULL, type);
9984 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
9985 } else if (wild->nsSet != NULL) {
9986 ns = wild->nsSet;
9987 do {
9988 ctxt->state =
9989 xmlAutomataNewTransition2(ctxt->am,
9990 start, NULL, BAD_CAST "*", ns->value, type);
9991 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
9992 ns = ns->next;
9993 } while (ns != NULL);
9994
9995 } else if (wild->negNsSet != NULL) {
9996 xmlAutomataStatePtr deadEnd;
9997
9998 deadEnd = xmlAutomataNewState(ctxt->am);
9999 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
10000 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, type);
10001 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
10002 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
10003 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
10004 }
10005 xmlAutomataNewCountedTrans(ctxt->am, hop, start, counter);
10006 xmlAutomataNewCounterTrans(ctxt->am, hop, end, counter);
10007 }
10008 if (type->minOccurs == 0) {
10009 xmlAutomataNewEpsilon(ctxt->am, start, end);
10010 }
10011 ctxt->state = end;
10012 break;
10013 }
10014 case XML_SCHEMA_TYPE_ELEMENT:{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010015 xmlAutomataStatePtr oldstate;
10016 xmlSchemaElementPtr particle, elemDecl;
Daniel Veillard32370232002-10-16 14:08:14 +000010017
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010018 /*
10019 * IMPORTANT: This puts element declarations
10020 * (and never element decl. references) into the
10021 * automaton. This is crucial and should not be changed,
10022 * since validating functions rely now on it.
10023 */
10024 particle = (xmlSchemaElementPtr) type;
10025 if (particle->ref != NULL) {
10026 if (particle->refDecl == NULL) {
10027 /*
10028 * Skip content model creation if the reference
10029 * did not resolve to a declaration.
10030 */
10031 break;
10032 } else {
10033 /*
10034 * Referenced global element declaration.
10035 */
10036 elemDecl = particle->refDecl;
10037 }
10038 } else {
10039 /*
10040 * Anonymous element declaration.
10041 */
10042 elemDecl = particle;
10043 }
10044
10045 oldstate = ctxt->state;
10046
10047 if (particle->maxOccurs >= UNBOUNDED) {
10048 if (particle->minOccurs > 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010049 xmlAutomataStatePtr tmp;
10050 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +000010051
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010052 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010053 oldstate, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010054 oldstate = ctxt->state;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010055 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010056 particle->minOccurs - 1, UNBOUNDED);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000010057 ctxt->state =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010058 xmlAutomataNewTransition2(ctxt->am,
10059 ctxt->state, NULL,
10060 elemDecl->name,
10061 elemDecl->targetNamespace,
10062 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010063 tmp = ctxt->state;
10064 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010065 counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010066 ctxt->state =
10067 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010068 counter);
Daniel Veillard32370232002-10-16 14:08:14 +000010069
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010070 } else {
10071 ctxt->state =
10072 xmlAutomataNewTransition2(ctxt->am,
10073 ctxt->state, NULL,
10074 elemDecl->name,
10075 elemDecl->targetNamespace,
10076 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010077 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
10078 oldstate);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010079 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010080 /* basically an elem* */
10081 xmlAutomataNewEpsilon(ctxt->am, oldstate,
10082 ctxt->state);
10083 }
10084 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010085 } else if ((particle->maxOccurs > 1) || (particle->minOccurs > 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010086 xmlAutomataStatePtr tmp;
10087 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +000010088
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010089 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
10090 oldstate, NULL);
10091 oldstate = ctxt->state;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010092 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010093 particle->minOccurs - 1,
10094 particle->maxOccurs - 1);
10095 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
10096 ctxt->state,
10097 NULL,
10098 elemDecl->name,
10099 elemDecl->targetNamespace,
10100 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010101 tmp = ctxt->state;
10102 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010103 counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010104 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, tmp,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010105 NULL, counter);
10106 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010107 /* basically an elem? */
10108 xmlAutomataNewEpsilon(ctxt->am, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010109 ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010110 }
Daniel Veillardb39bc392002-10-26 19:29:51 +000010111
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010112 } else {
10113 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
10114 ctxt->state,
10115 NULL,
10116 elemDecl->name,
10117 elemDecl->targetNamespace,
10118 (xmlSchemaTypePtr) elemDecl);
10119 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010120 /* basically an elem? */
10121 xmlAutomataNewEpsilon(ctxt->am, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010122 ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010123 }
10124 }
10125 break;
10126 }
10127 case XML_SCHEMA_TYPE_SEQUENCE:{
10128 xmlSchemaTypePtr subtypes;
Daniel Veillardb39bc392002-10-26 19:29:51 +000010129
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010130 /*
10131 * If max and min occurances are default (1) then
10132 * simply iterate over the subtypes
10133 */
10134 if ((type->minOccurs == 1) && (type->maxOccurs == 1)) {
10135 subtypes = type->subtypes;
10136 while (subtypes != NULL) {
10137 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
10138 subtypes = subtypes->next;
10139 }
10140 } else {
10141 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000010142
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010143 if (type->maxOccurs >= UNBOUNDED) {
10144 if (type->minOccurs > 1) {
10145 xmlAutomataStatePtr tmp;
10146 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000010147
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010148 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
10149 oldstate,
10150 NULL);
10151 oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000010152
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010153 counter = xmlAutomataNewCounter(ctxt->am,
10154 type->
10155 minOccurs - 1,
10156 UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +000010157
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010158 subtypes = type->subtypes;
10159 while (subtypes != NULL) {
10160 xmlSchemaBuildAContentModel(subtypes, ctxt,
10161 name);
10162 subtypes = subtypes->next;
10163 }
10164 tmp = ctxt->state;
10165 xmlAutomataNewCountedTrans(ctxt->am, tmp,
10166 oldstate, counter);
10167 ctxt->state =
10168 xmlAutomataNewCounterTrans(ctxt->am, tmp,
10169 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +000010170
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010171 } else {
10172 subtypes = type->subtypes;
10173 while (subtypes != NULL) {
10174 xmlSchemaBuildAContentModel(subtypes, ctxt,
10175 name);
10176 subtypes = subtypes->next;
10177 }
10178 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
10179 oldstate);
10180 if (type->minOccurs == 0) {
10181 xmlAutomataNewEpsilon(ctxt->am, oldstate,
10182 ctxt->state);
10183 }
10184 }
10185 } else if ((type->maxOccurs > 1)
10186 || (type->minOccurs > 1)) {
10187 xmlAutomataStatePtr tmp;
10188 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000010189
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010190 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
10191 oldstate,
10192 NULL);
10193 oldstate = ctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +000010194
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010195 counter = xmlAutomataNewCounter(ctxt->am,
10196 type->minOccurs -
10197 1,
10198 type->maxOccurs -
10199 1);
Daniel Veillard4255d502002-04-16 15:50:10 +000010200
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010201 subtypes = type->subtypes;
10202 while (subtypes != NULL) {
10203 xmlSchemaBuildAContentModel(subtypes, ctxt,
10204 name);
10205 subtypes = subtypes->next;
10206 }
10207 tmp = ctxt->state;
10208 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
10209 counter);
10210 ctxt->state =
10211 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
10212 counter);
10213 if (type->minOccurs == 0) {
10214 xmlAutomataNewEpsilon(ctxt->am, oldstate,
10215 ctxt->state);
10216 }
Daniel Veillardb509f152002-04-17 16:28:10 +000010217
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010218 } else {
10219 subtypes = type->subtypes;
10220 while (subtypes != NULL) {
10221 xmlSchemaBuildAContentModel(subtypes, ctxt,
10222 name);
10223 subtypes = subtypes->next;
10224 }
10225 if (type->minOccurs == 0) {
10226 xmlAutomataNewEpsilon(ctxt->am, oldstate,
10227 ctxt->state);
10228 }
10229 }
10230 }
10231 break;
10232 }
10233 case XML_SCHEMA_TYPE_CHOICE:{
10234 xmlSchemaTypePtr subtypes;
10235 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +000010236
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010237 start = ctxt->state;
10238 end = xmlAutomataNewState(ctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +000010239
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010240 /*
10241 * iterate over the subtypes and remerge the end with an
10242 * epsilon transition
10243 */
10244 if (type->maxOccurs == 1) {
10245 subtypes = type->subtypes;
10246 while (subtypes != NULL) {
10247 ctxt->state = start;
10248 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
10249 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
10250 subtypes = subtypes->next;
10251 }
10252 } else {
10253 int counter;
10254 xmlAutomataStatePtr hop;
10255 int maxOccurs = type->maxOccurs == UNBOUNDED ?
10256 UNBOUNDED : type->maxOccurs - 1;
10257 int minOccurs =
10258 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +000010259
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010260 /*
10261 * use a counter to keep track of the number of transtions
10262 * which went through the choice.
10263 */
10264 counter =
10265 xmlAutomataNewCounter(ctxt->am, minOccurs,
10266 maxOccurs);
10267 hop = xmlAutomataNewState(ctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +000010268
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010269 subtypes = type->subtypes;
10270 while (subtypes != NULL) {
10271 ctxt->state = start;
10272 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
10273 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
10274 subtypes = subtypes->next;
10275 }
10276 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
10277 counter);
10278 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
10279 counter);
10280 }
10281 if (type->minOccurs == 0) {
10282 xmlAutomataNewEpsilon(ctxt->am, start, end);
10283 }
10284 ctxt->state = end;
10285 break;
10286 }
10287 case XML_SCHEMA_TYPE_ALL:{
10288 xmlAutomataStatePtr start;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000010289 xmlSchemaElementPtr elemDecl, particle;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010290 int lax;
10291
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000010292 particle = (xmlSchemaElementPtr) type->subtypes;
10293 if (particle == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010294 break;
10295 start = ctxt->state;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000010296 while (particle != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010297 ctxt->state = start;
William M. Brack9989c7d2004-05-12 14:39:38 +000010298 /*
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000010299 * Changed to put the element declaration and
10300 * never the element decl. reference into the
10301 * automaton. This fixes bug 139897 and bug 167754.
William M. Brack9989c7d2004-05-12 14:39:38 +000010302 */
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000010303 if (particle->ref != NULL) {
10304 if (particle->refDecl == NULL) {
10305 /*
10306 * TODO: Note that we break on missing
10307 * sub-components.
10308 */
10309 break;
10310 } else
10311 elemDecl = particle->refDecl;
10312 } else
10313 elemDecl = particle;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010314 /*
10315 * NOTE: The {max occurs} of all the particles in the
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000010316 * {particles} of the group must be 0 or 1; this is
10317 * already ensured during the parse of the content of
10318 * <all>.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010319 */
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000010320 if ((particle->minOccurs == 1) &&
10321 (particle->maxOccurs == 1)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010322 xmlAutomataNewOnceTrans2(ctxt->am, ctxt->state,
10323 ctxt->state,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000010324 elemDecl->name,
10325 elemDecl->targetNamespace,
10326 1, 1, elemDecl);
10327 } else if ((particle->minOccurs == 0) &&
10328 (particle->maxOccurs == 1)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010329
10330 xmlAutomataNewCountTrans2(ctxt->am, ctxt->state,
10331 ctxt->state,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000010332 elemDecl->name,
10333 elemDecl->targetNamespace,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010334 0,
10335 1,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000010336 elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010337 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000010338 particle = (xmlSchemaElementPtr) particle->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010339 }
10340 lax = type->minOccurs == 0;
10341 ctxt->state =
10342 xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL,
10343 lax);
10344 break;
10345 }
10346 case XML_SCHEMA_TYPE_RESTRICTION:
10347 if (type->subtypes != NULL)
10348 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
10349 break;
10350 case XML_SCHEMA_TYPE_EXTENSION:
10351 if (type->baseType != NULL) {
10352 xmlSchemaTypePtr subtypes;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010353
10354 /*
10355 * TODO: Circular definitions will be checked at the
10356 * constraint level. So remove this when the complex type
10357 * constraints are implemented.
10358 */
Daniel Veillardf7627552004-04-22 07:15:40 +000010359 if (type->recurse) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010360 /* TODO: Change the error code. */
10361 xmlSchemaPCustomErr(ctxt,
10362 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
10363 NULL, type, type->node,
10364 "This item is circular", NULL);
Daniel Veillardf7627552004-04-22 07:15:40 +000010365 return;
10366 }
10367 type->recurse = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010368 xmlSchemaBuildAContentModel(type->baseType, ctxt, name);
Daniel Veillardf7627552004-04-22 07:15:40 +000010369 type->recurse = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010370 subtypes = type->subtypes;
10371 while (subtypes != NULL) {
10372 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
10373 subtypes = subtypes->next;
10374 }
10375 } else if (type->subtypes != NULL)
10376 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
10377 break;
10378 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000010379 /*
10380 * Handle model group definition references.
10381 * NOTE: type->subtypes is the referenced model grop definition;
10382 * and type->subtypes->subtypes is the model group (i.e. <all> or
10383 * <choice> or <sequence>).
10384 */
10385 if ((type->ref != NULL) && (type->subtypes != NULL) &&
10386 (type->subtypes->subtypes != NULL)) {
10387 xmlSchemaTypePtr modelGr;
10388 xmlAutomataStatePtr start, end;
10389
10390 modelGr = type->subtypes->subtypes;
10391 start = ctxt->state;
10392 end = xmlAutomataNewState(ctxt->am);
10393 if (type->maxOccurs == 1) {
10394 ctxt->state = start;
10395 xmlSchemaBuildAContentModel(modelGr, ctxt, name);
10396 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
10397 } else {
10398 int counter;
10399 xmlAutomataStatePtr hop;
10400 int maxOccurs = type->maxOccurs == UNBOUNDED ?
10401 UNBOUNDED : type->maxOccurs - 1;
10402 int minOccurs =
10403 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
10404
10405 counter =
10406 xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
10407 hop = xmlAutomataNewState(ctxt->am);
10408 ctxt->state = start;
10409 xmlSchemaBuildAContentModel(modelGr, ctxt, name);
10410 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
10411 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
10412 counter);
10413 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
10414 counter);
10415 }
10416 if (type->minOccurs == 0) {
10417 xmlAutomataNewEpsilon(ctxt->am, start, end);
10418 }
10419 ctxt->state = end;
10420 break;
10421 }
10422 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010423 case XML_SCHEMA_TYPE_COMPLEX:
10424 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
10425 if (type->subtypes != NULL)
10426 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
10427 break;
William M. Brack2f2a6632004-08-20 23:09:47 +000010428 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
10429 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010430 default:
10431 xmlGenericError(xmlGenericErrorContext,
10432 "Found unexpected type %d in %s content model\n",
10433 type->type, name);
10434 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000010435 }
10436}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010437
Daniel Veillard4255d502002-04-16 15:50:10 +000010438/**
10439 * xmlSchemaBuildContentModel:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010440 * @type: the type definition (or reference)
Daniel Veillard4255d502002-04-16 15:50:10 +000010441 * @ctxt: the schema parser context
Daniel Veillarda84c0b32003-06-02 16:58:46 +000010442 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +000010443 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010444 * Builds the content model of the complex type.
Daniel Veillard4255d502002-04-16 15:50:10 +000010445 */
10446static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010447xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010448 xmlSchemaParserCtxtPtr ctxt,
10449 const xmlChar * name)
10450{
Daniel Veillard4255d502002-04-16 15:50:10 +000010451 xmlAutomataStatePtr start;
10452
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010453 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) || (type->ref != NULL) ||
10454 (type->contentType == XML_SCHEMA_CONTENT_BASIC) ||
10455 (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
10456 (type->contModel != NULL))
10457 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +000010458
10459#ifdef DEBUG_CONTENT
10460 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010461 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000010462#endif
10463
Daniel Veillard4255d502002-04-16 15:50:10 +000010464 ctxt->am = xmlNewAutomata();
10465 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010466 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010467 "Cannot create automata for complex tpye %s\n", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010468 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000010469 }
10470 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010471 xmlSchemaBuildAContentModel(type, ctxt, name);
Daniel Veillard4255d502002-04-16 15:50:10 +000010472 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010473 type->contModel = xmlAutomataCompile(ctxt->am);
10474 if (type->contModel == NULL) {
10475 xmlSchemaPCustomErr(ctxt,
10476 XML_SCHEMAP_INTERNAL,
10477 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010478 "Failed to compile the content model", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010479 } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010480 xmlSchemaPCustomErr(ctxt,
10481 XML_SCHEMAP_NOT_DETERMINISTIC,
10482 /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010483 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010484 "The content model is not determinist", NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +000010485 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +000010486#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010487 xmlGenericError(xmlGenericErrorContext,
10488 "Content model of %s:\n", name);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010489 xmlRegexpPrint(stderr, type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +000010490#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +000010491 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +000010492 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000010493 xmlFreeAutomata(ctxt->am);
10494 ctxt->am = NULL;
10495}
10496
10497/**
10498 * xmlSchemaRefFixupCallback:
10499 * @elem: the schema element context
10500 * @ctxt: the schema parser context
10501 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000010502 * Resolves the references of an element declaration
10503 * or particle, which has an element declaration as it's
10504 * term.
Daniel Veillard4255d502002-04-16 15:50:10 +000010505 */
10506static void
10507xmlSchemaRefFixupCallback(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010508 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010509 const xmlChar * name ATTRIBUTE_UNUSED,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010510 const xmlChar * context ATTRIBUTE_UNUSED,
10511 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000010512{
Daniel Veillardc0826a72004-08-10 14:17:33 +000010513 if ((ctxt == NULL) || (elem == NULL) ||
10514 ((elem != NULL) && (elem->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010515 return;
Daniel Veillardc0826a72004-08-10 14:17:33 +000010516 elem->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
Daniel Veillard4255d502002-04-16 15:50:10 +000010517 if (elem->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010518 xmlSchemaElementPtr elemDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +000010519
Daniel Veillardc0826a72004-08-10 14:17:33 +000010520 /*
10521 * TODO: Evaluate, what errors could occur if the declaration is not
10522 * found. It might be possible that the "typefixup" might crash if
10523 * no ref declaration was found.
10524 */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010525 elemDecl = xmlSchemaGetElem(ctxt->schema, elem->ref, elem->refNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +000010526 if (elemDecl == NULL) {
10527 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010528 XML_SCHEMAP_SRC_RESOLVE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010529 NULL, (xmlSchemaTypePtr) elem, elem->node,
10530 "ref", elem->ref, elem->refNs,
10531 XML_SCHEMA_TYPE_ELEMENT, NULL);
10532 } else
10533 elem->refDecl = elemDecl;
10534 } else {
10535 if ((elem->subtypes == NULL) && (elem->namedType != NULL)) {
10536 xmlSchemaTypePtr type;
10537
10538 /* (type definition) ... otherwise the type definition ·resolved·
10539 * to by the ·actual value· of the type [attribute] ...
10540 */
10541 type = xmlSchemaGetType(ctxt->schema, elem->namedType,
10542 elem->namedTypeNs);
10543 if (type == NULL) {
10544 xmlSchemaPResCompAttrErr(ctxt,
10545 XML_SCHEMAP_SRC_RESOLVE,
10546 NULL, (xmlSchemaTypePtr) elem, elem->node,
10547 "type", elem->namedType, elem->namedTypeNs,
10548 XML_SCHEMA_TYPE_BASIC, "type definition");
10549 } else
10550 elem->subtypes = type;
10551 }
10552 if (elem->substGroup != NULL) {
10553 xmlSchemaElementPtr substHead;
10554
10555 /*
10556 * FIXME TODO: Do we need a new field in _xmlSchemaElement for
10557 * substitutionGroup?
10558 */
10559 substHead = xmlSchemaGetElem(ctxt->schema, elem->substGroup,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010560 elem->substGroupNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +000010561 if (substHead == NULL) {
10562 xmlSchemaPResCompAttrErr(ctxt,
10563 XML_SCHEMAP_SRC_RESOLVE,
10564 NULL, (xmlSchemaTypePtr) elem, NULL,
10565 "substitutionGroup", elem->substGroup, elem->substGroupNs,
10566 XML_SCHEMA_TYPE_ELEMENT, NULL);
10567 } else {
10568 xmlSchemaRefFixupCallback(substHead, ctxt, NULL, NULL, NULL);
10569 /*
10570 * (type definition)...otherwise the {type definition} of the
10571 * element declaration ·resolved· to by the ·actual value· of
10572 * the substitutionGroup [attribute], if present
10573 */
10574 if (elem->subtypes == NULL)
10575 elem->subtypes = substHead->subtypes;
10576 }
10577 }
10578 if ((elem->subtypes == NULL) && (elem->namedType == NULL) &&
10579 (elem->substGroup == NULL))
10580 elem->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
10581 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010582}
10583
William M. Bracke7091952004-05-11 15:09:58 +000010584/**
10585 * xmlSchemaParseListRefFixup:
10586 * @type: the schema type definition
10587 * @ctxt: the schema parser context
10588 *
10589 * Fixup of the itemType reference of the list type.
10590 */
Daniel Veillard377e1a92004-04-16 16:30:05 +000010591static void
William M. Bracke7091952004-05-11 15:09:58 +000010592xmlSchemaParseListRefFixup(xmlSchemaTypePtr type, xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010593{
Daniel Veillardc0826a72004-08-10 14:17:33 +000010594
Daniel Veillard01fa6152004-06-29 17:04:39 +000010595 if (((type->base == NULL) &&
10596 (type->subtypes == NULL)) ||
10597 ((type->base != NULL) &&
10598 (type->subtypes != NULL))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010599 /*
10600 * src-list-itemType-or-simpleType
10601 * Either the itemType [attribute] or the <simpleType> [child] of
10602 * the <list> element must be present, but not both.
Daniel Veillard01fa6152004-06-29 17:04:39 +000010603 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000010604 /*
10605 * TODO: Move this to the parse function.
10606 */
10607 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010608 XML_SCHEMAP_SRC_LIST_ITEMTYPE_OR_SIMPLETYPE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010609 NULL, type, type->node,
10610 "The attribute 'itemType' and the <simpleType> child "
10611 "are mutually exclusive", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010612 } else if (type->base!= NULL) {
10613 type->subtypes = xmlSchemaGetType(ctxt->schema, type->base, type->baseNs);
10614 if (type->subtypes == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010615 xmlSchemaPResCompAttrErr(ctxt,
10616 XML_SCHEMAP_SRC_RESOLVE,
10617 NULL, type, type->node,
10618 "itemType", type->base, type->baseNs,
10619 XML_SCHEMA_TYPE_SIMPLE, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010620 }
10621 }
10622 if ((type->subtypes != NULL) &&
10623 (type->subtypes->contentType == XML_SCHEMA_CONTENT_UNKNOWN))
10624 xmlSchemaTypeFixup(type->subtypes, ctxt, NULL);
William M. Bracke7091952004-05-11 15:09:58 +000010625}
10626
10627/**
10628 * xmlSchemaParseUnionRefCheck:
10629 * @typeDecl: the schema type definition
10630 * @ctxt: the schema parser context
10631 *
Daniel Veillard01fa6152004-06-29 17:04:39 +000010632 * Checks and builds the memberTypes of the union type.
10633 * Returns -1 in case of an internal error, 0 otherwise.
William M. Bracke7091952004-05-11 15:09:58 +000010634 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010635static int
William M. Bracke7091952004-05-11 15:09:58 +000010636xmlSchemaParseUnionRefCheck(xmlSchemaTypePtr type,
Daniel Veillard377e1a92004-04-16 16:30:05 +000010637 xmlSchemaParserCtxtPtr ctxt)
10638{
Daniel Veillardc0826a72004-08-10 14:17:33 +000010639
Daniel Veillard01fa6152004-06-29 17:04:39 +000010640 xmlSchemaTypeLinkPtr link, lastLink = NULL, prevLink, subLink, newLink;
10641 xmlSchemaTypePtr memberType, ctxtType;
Daniel Veillard377e1a92004-04-16 16:30:05 +000010642
Daniel Veillard01fa6152004-06-29 17:04:39 +000010643 /* 1 If the <union> alternative is chosen, then [Definition:]
10644 * define the explicit members as the type definitions ·resolved·
10645 * to by the items in the ·actual value· of the memberTypes [attribute],
10646 * if any, followed by the type definitions corresponding to the
10647 * <simpleType>s among the [children] of <union>, if any.
10648 */
Daniel Veillard377e1a92004-04-16 16:30:05 +000010649
Daniel Veillard01fa6152004-06-29 17:04:39 +000010650 if (type->type != XML_SCHEMA_TYPE_UNION)
10651 return (-1);
10652 if (ctxt->ctxtType == NULL) {
10653 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010654 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010655 "Internal error: xmlSchemaParseUnionRefCheck, no parent type "
10656 "available", NULL, NULL);
10657 return (-1);
10658 }
10659 /*
10660 * src-union-memberTypes-or-simpleTypes
10661 * Either the memberTypes [attribute] of the <union> element must
10662 * be non-empty or there must be at least one simpleType [child].
10663 */
10664 if ((type->base == NULL) &&
10665 (type->subtypes == NULL)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010666 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010667 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010668 NULL, NULL, type->node,
10669 "Either the attribute 'memberTypes' must be non-empty "
10670 "or there must be at least one <simpleType> child", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010671 }
10672
10673 ctxtType = ctxt->ctxtType;
10674 if (type->base != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010675 xmlAttrPtr attr;
10676 const xmlChar *cur, *end;
10677 xmlChar *tmp;
10678 const xmlChar *localName, *uri;
10679
10680 attr = xmlSchemaGetPropNode(type->node, "memberTypes");
Daniel Veillard01fa6152004-06-29 17:04:39 +000010681 cur = type->base;
10682 do {
10683 while (IS_BLANK_CH(*cur))
10684 cur++;
10685 end = cur;
10686 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
10687 end++;
10688 if (end == cur)
10689 break;
10690 tmp = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +000010691 xmlSchemaPValAttrNodeQNameValue(ctxt, ctxt->schema, NULL,
10692 NULL, attr, BAD_CAST tmp, &uri, NULL, &localName);
10693 memberType = xmlSchemaGetType(ctxt->schema, localName, uri);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010694 if (memberType == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010695 xmlSchemaPResCompAttrErr(ctxt,
10696 XML_SCHEMAP_UNKNOWN_MEMBER_TYPE,
10697 NULL, NULL, type->node, "memberTypes", localName, uri,
10698 XML_SCHEMA_TYPE_SIMPLE, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010699 } else {
10700 if (memberType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
10701 xmlSchemaTypeFixup(memberType, ctxt, NULL);
10702 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
10703 if (link == NULL) {
10704 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
10705 return (-1);
10706 }
10707 link->type = memberType;
10708 link->next = NULL;
10709 if (lastLink == NULL)
10710 ctxtType->memberTypes = link;
10711 else
10712 lastLink->next = link;
10713 lastLink = link;
10714 }
10715 xmlFree(tmp);
10716 cur = end;
10717 } while (*cur != 0);
10718 }
10719 /*
10720 * Add local simple types,
10721 */
10722 memberType = type->subtypes;
10723 while (memberType != NULL) {
10724 if (memberType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
10725 xmlSchemaTypeFixup(memberType, ctxt, NULL);
10726 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
10727 if (link == NULL) {
10728 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
10729 return (-1);
10730 }
10731 link->type = memberType;
10732 link->next = NULL;
10733 if (lastLink == NULL)
10734 ctxtType->memberTypes = link;
10735 else
10736 lastLink->next = link;
10737 lastLink = link;
10738 memberType = memberType->next;
10739 }
10740 /*
10741 * The actual value is then formed by replacing any union type
10742 * definition in the ·explicit members· with the members of their
10743 * {member type definitions}, in order.
10744 */
10745 link = ctxtType->memberTypes;
10746 while (link != NULL) {
10747 if (link->type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
10748 subLink = link->type->memberTypes;
10749 if (subLink != NULL) {
10750 link->type = subLink->type;
10751 if (subLink->next != NULL) {
10752 lastLink = link->next;
10753 subLink = subLink->next;
10754 prevLink = link;
10755 while (subLink != NULL) {
10756 newLink = (xmlSchemaTypeLinkPtr)
10757 xmlMalloc(sizeof(xmlSchemaTypeLink));
10758 if (newLink == NULL) {
10759 xmlSchemaPErrMemory(ctxt, "allocating a type link",
10760 NULL);
10761 return (-1);
10762 }
10763 newLink->type = memberType;
10764 prevLink->next = newLink;
10765 prevLink = newLink;
10766 newLink->next = lastLink;
10767
10768 subLink = subLink->next;
10769 }
10770 }
10771 }
10772 }
10773 link = link->next;
10774 }
10775
10776 return (0);
Daniel Veillard377e1a92004-04-16 16:30:05 +000010777}
10778
Daniel Veillard4255d502002-04-16 15:50:10 +000010779/**
Daniel Veillard3646d642004-06-02 19:19:14 +000010780 * xmlSchemaIsDerivedFromBuiltInType:
10781 * @ctxt: the schema parser context
10782 * @type: the type definition
10783 * @valType: the value type
10784 *
10785 *
10786 * Returns 1 if the type has the given value type, or
10787 * is derived from such a type.
10788 */
William M. Brack803812b2004-06-03 02:11:24 +000010789static int
Daniel Veillard3646d642004-06-02 19:19:14 +000010790xmlSchemaIsDerivedFromBuiltInType(xmlSchemaParserCtxtPtr ctxt,
10791 xmlSchemaTypePtr type, int valType)
10792{
10793 /* TODO: Check if this works in every case. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010794 if ((type->type == XML_SCHEMA_TYPE_BASIC) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000010795 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000010796 if (type->builtInType == valType)
Daniel Veillard3646d642004-06-02 19:19:14 +000010797 return(1);
10798 } else if (type->type == XML_SCHEMA_TYPE_ATTRIBUTE) {
10799 if (((xmlSchemaAttributePtr) type)->subtypes != NULL)
10800 return(xmlSchemaIsDerivedFromBuiltInType(ctxt,
10801 ((xmlSchemaAttributePtr) type)->subtypes, valType));
10802 } else if ((type->type == XML_SCHEMA_TYPE_RESTRICTION) ||
10803 (type->type == XML_SCHEMA_TYPE_EXTENSION)) {
10804 if (type->baseType != NULL)
10805 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->baseType,
10806 valType));
10807 } else if ((type->subtypes != NULL) &&
10808 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX) ||
10809 (type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
10810 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE) ||
10811 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
10812 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->subtypes,
10813 valType));
10814 }
10815
10816 return (0);
10817}
10818
10819/**
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000010820 * xmlSchemaGetPrimitiveType:
Daniel Veillard01fa6152004-06-29 17:04:39 +000010821 * @type: the simpleType definition
10822 *
10823 * Returns the primitive type of the given type or
10824 * NULL in case of error.
10825 */
10826static xmlSchemaTypePtr
10827xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
10828{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000010829
Daniel Veillard01fa6152004-06-29 17:04:39 +000010830 while (type != NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000010831 /*
10832 * Note that anySimpleType is actually not a primitive type
10833 * but we need that here.
10834 */
10835 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
10836 (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
Daniel Veillard01fa6152004-06-29 17:04:39 +000010837 return (type);
10838 type = type->baseType;
10839 }
10840
10841 return (NULL);
10842}
10843
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000010844#if 0
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000010845/**
10846 * xmlSchemaGetBuiltInTypeAncestor:
10847 * @type: the simpleType definition
10848 *
10849 * Returns the primitive type of the given type or
10850 * NULL in case of error.
10851 */
10852static xmlSchemaTypePtr
10853xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
10854{
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000010855 if ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
10856 (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION))
10857 return (0);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000010858 while (type != NULL) {
10859 if (type->type == XML_SCHEMA_TYPE_BASIC)
10860 return (type);
10861 type = type->baseType;
10862 }
10863
10864 return (NULL);
10865}
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000010866#endif
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000010867
Daniel Veillard01fa6152004-06-29 17:04:39 +000010868/**
Daniel Veillard3646d642004-06-02 19:19:14 +000010869 * xmlSchemaBuildAttributeUsesOwned:
10870 * @ctxt: the schema parser context
10871 * @type: the complex type definition
10872 * @cur: the attribute declaration list
10873 * @lastUse: the top of the attribute use list
10874 *
10875 * Builds the attribute uses list on the given complex type.
10876 * This one is supposed to be called by
10877 * xmlSchemaBuildAttributeValidation only.
10878 */
10879static int
10880xmlSchemaBuildAttributeUsesOwned(xmlSchemaParserCtxtPtr ctxt,
10881 xmlSchemaAttributePtr cur,
10882 xmlSchemaAttributeLinkPtr *uses,
10883 xmlSchemaAttributeLinkPtr *lastUse)
10884{
10885 xmlSchemaAttributeLinkPtr tmp;
10886 while (cur != NULL) {
10887 if (cur->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
10888 /*
10889 * W3C: "2 The {attribute uses} of the attribute groups ·resolved·
10890 * to by the ·actual value·s of the ref [attribute] of the
10891 * <attributeGroup> [children], if any."
10892 */
10893 if (xmlSchemaBuildAttributeUsesOwned(ctxt,
10894 ((xmlSchemaAttributeGroupPtr) cur)->attributes, uses,
10895 lastUse) == -1) {
10896 return (-1);
10897 }
10898 } else {
10899 /* W3C: "1 The set of attribute uses corresponding to the
10900 * <attribute> [children], if any."
10901 */
10902 tmp = (xmlSchemaAttributeLinkPtr)
10903 xmlMalloc(sizeof(xmlSchemaAttributeLink));
10904 if (tmp == NULL) {
10905 xmlSchemaPErrMemory(ctxt, "building attribute uses", NULL);
10906 return (-1);
10907 }
10908 tmp->attr = cur;
10909 tmp->next = NULL;
10910 if (*uses == NULL)
10911 *uses = tmp;
10912 else
10913 (*lastUse)->next = tmp;
10914 *lastUse = tmp;
10915 }
10916 cur = cur->next;
10917 }
10918 return (0);
10919}
10920
Daniel Veillard50355f02004-06-08 17:52:16 +000010921/**
10922 * xmlSchemaCloneWildcardNsConstraints:
10923 * @ctxt: the schema parser context
10924 * @dest: the destination wildcard
10925 * @source: the source wildcard
10926 *
10927 * Clones the namespace constraints of source
10928 * and assignes them to dest.
10929 * Returns -1 on internal error, 0 otherwise.
10930 */
Daniel Veillard3646d642004-06-02 19:19:14 +000010931static int
10932xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
10933 xmlSchemaWildcardPtr *dest,
10934 xmlSchemaWildcardPtr source)
10935{
10936 xmlSchemaWildcardNsPtr cur, tmp, last;
10937
10938 if ((source == NULL) || (*dest == NULL))
10939 return(-1);
10940 (*dest)->any = source->any;
10941 cur = source->nsSet;
10942 last = NULL;
10943 while (cur != NULL) {
10944 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
10945 if (tmp == NULL)
10946 return(-1);
10947 tmp->value = cur->value;
10948 if (last == NULL)
10949 (*dest)->nsSet = tmp;
10950 else
10951 last->next = tmp;
10952 last = tmp;
10953 cur = cur->next;
10954 }
10955 if ((*dest)->negNsSet != NULL)
10956 xmlSchemaFreeWildcardNsSet((*dest)->negNsSet);
10957 if (source->negNsSet != NULL) {
10958 (*dest)->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
10959 if ((*dest)->negNsSet == NULL)
10960 return(-1);
10961 (*dest)->negNsSet->value = source->negNsSet->value;
10962 } else
10963 (*dest)->negNsSet = NULL;
10964 return(0);
10965}
10966
Daniel Veillard50355f02004-06-08 17:52:16 +000010967/**
10968 * xmlSchemaUnionWildcards:
10969 * @ctxt: the schema parser context
10970 * @completeWild: the first wildcard
10971 * @curWild: the second wildcard
10972 *
10973 * Unions the namespace constraints of the given wildcards.
10974 * @completeWild will hold the resulting union.
10975 * Returns a positive error code on failure, -1 in case of an
10976 * internal error, 0 otherwise.
10977 */
Daniel Veillard3646d642004-06-02 19:19:14 +000010978static int
10979xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
10980 xmlSchemaWildcardPtr completeWild,
10981 xmlSchemaWildcardPtr curWild)
10982{
10983 xmlSchemaWildcardNsPtr cur, curB, tmp;
10984
10985 /*
10986 * 1 If O1 and O2 are the same value, then that value must be the
10987 * value.
10988 */
10989 if ((completeWild->any == curWild->any) &&
10990 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
10991 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
10992
10993 if ((completeWild->negNsSet == NULL) ||
10994 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
10995
10996 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000010997 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000010998
10999 /*
11000 * Check equality of sets.
11001 */
11002 cur = completeWild->nsSet;
11003 while (cur != NULL) {
11004 found = 0;
11005 curB = curWild->nsSet;
11006 while (curB != NULL) {
11007 if (cur->value == curB->value) {
11008 found = 1;
11009 break;
11010 }
11011 curB = curB->next;
11012 }
11013 if (!found)
11014 break;
11015 cur = cur->next;
11016 }
11017 if (found)
11018 return(0);
11019 } else
11020 return(0);
11021 }
11022 }
11023 /*
11024 * 2 If either O1 or O2 is any, then any must be the value
11025 */
Daniel Veillard50355f02004-06-08 17:52:16 +000011026 if (completeWild->any != curWild->any) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011027 if (completeWild->any == 0) {
11028 completeWild->any = 1;
11029 if (completeWild->nsSet != NULL) {
11030 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11031 completeWild->nsSet = NULL;
11032 }
11033 if (completeWild->negNsSet != NULL) {
11034 xmlFree(completeWild->negNsSet);
11035 completeWild->negNsSet = NULL;
11036 }
11037 }
Daniel Veillard50355f02004-06-08 17:52:16 +000011038 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000011039 }
11040 /*
11041 * 3 If both O1 and O2 are sets of (namespace names or ·absent·),
11042 * then the union of those sets must be the value.
11043 */
11044 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
11045 int found;
11046 xmlSchemaWildcardNsPtr start;
11047
11048 cur = curWild->nsSet;
11049 start = completeWild->nsSet;
11050 while (cur != NULL) {
11051 found = 0;
11052 curB = start;
11053 while (curB != NULL) {
11054 if (cur->value == curB->value) {
11055 found = 1;
11056 break;
11057 }
11058 curB = curB->next;
11059 }
11060 if (!found) {
11061 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
11062 if (tmp == NULL)
11063 return (-1);
11064 tmp->value = cur->value;
11065 tmp->next = completeWild->nsSet;
11066 completeWild->nsSet = tmp;
11067 }
11068 cur = cur->next;
11069 }
11070
11071 return(0);
11072 }
11073 /*
11074 * 4 If the two are negations of different values (namespace names
11075 * or ·absent·), then a pair of not and ·absent· must be the value.
11076 */
11077 if ((completeWild->negNsSet != NULL) &&
11078 (curWild->negNsSet != NULL) &&
11079 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
11080 completeWild->negNsSet->value = NULL;
Daniel Veillard50355f02004-06-08 17:52:16 +000011081
11082 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +000011083 }
11084 /*
11085 * 5.
11086 */
11087 if (((completeWild->negNsSet != NULL) &&
11088 (completeWild->negNsSet->value != NULL) &&
11089 (curWild->nsSet != NULL)) ||
11090 ((curWild->negNsSet != NULL) &&
11091 (curWild->negNsSet->value != NULL) &&
11092 (completeWild->nsSet != NULL))) {
11093
11094 int nsFound, absentFound = 0;
11095
11096 if (completeWild->nsSet != NULL) {
11097 cur = completeWild->nsSet;
11098 curB = curWild->negNsSet;
11099 } else {
11100 cur = curWild->nsSet;
11101 curB = completeWild->negNsSet;
11102 }
11103 nsFound = 0;
11104 while (cur != NULL) {
11105 if (cur->value == NULL)
11106 absentFound = 1;
11107 else if (cur->value == curB->value)
11108 nsFound = 1;
11109 if (nsFound && absentFound)
11110 break;
11111 cur = cur->next;
11112 }
11113
11114 if (nsFound && absentFound) {
11115 /*
11116 * 5.1 If the set S includes both the negated namespace
11117 * name and ·absent·, then any must be the value.
11118 */
11119 completeWild->any = 1;
11120 if (completeWild->nsSet != NULL) {
11121 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11122 completeWild->nsSet = NULL;
11123 }
11124 if (completeWild->negNsSet != NULL) {
11125 xmlFree(completeWild->negNsSet);
11126 completeWild->negNsSet = NULL;
11127 }
11128 } else if (nsFound && (!absentFound)) {
11129 /*
11130 * 5.2 If the set S includes the negated namespace name
11131 * but not ·absent·, then a pair of not and ·absent· must
11132 * be the value.
11133 */
11134 if (completeWild->nsSet != NULL) {
11135 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11136 completeWild->nsSet = NULL;
11137 }
11138 if (completeWild->negNsSet == NULL) {
11139 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
11140 if (completeWild->negNsSet == NULL)
11141 return (-1);
11142 }
11143 completeWild->negNsSet->value = NULL;
11144 } else if ((!nsFound) && absentFound) {
11145 /*
11146 * 5.3 If the set S includes ·absent· but not the negated
11147 * namespace name, then the union is not expressible.
11148 */
11149 xmlSchemaPErr(ctxt, completeWild->node,
11150 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011151 "The union of the wilcard is not expressible.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +000011152 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000011153 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +000011154 } else if ((!nsFound) && (!absentFound)) {
11155 /*
11156 * 5.4 If the set S does not include either the negated namespace
11157 * name or ·absent·, then whichever of O1 or O2 is a pair of not
11158 * and a namespace name must be the value.
11159 */
11160 if (completeWild->negNsSet == NULL) {
11161 if (completeWild->nsSet != NULL) {
11162 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11163 completeWild->nsSet = NULL;
11164 }
11165 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
11166 if (completeWild->negNsSet == NULL)
11167 return (-1);
11168 completeWild->negNsSet->value = curWild->negNsSet->value;
11169 }
11170 }
11171 return (0);
11172 }
11173 /*
11174 * 6.
11175 */
11176 if (((completeWild->negNsSet != NULL) &&
11177 (completeWild->negNsSet->value == NULL) &&
11178 (curWild->nsSet != NULL)) ||
11179 ((curWild->negNsSet != NULL) &&
11180 (curWild->negNsSet->value == NULL) &&
11181 (completeWild->nsSet != NULL))) {
11182
11183 if (completeWild->nsSet != NULL) {
11184 cur = completeWild->nsSet;
11185 } else {
11186 cur = curWild->nsSet;
11187 }
11188 while (cur != NULL) {
11189 if (cur->value == NULL) {
11190 /*
11191 * 6.1 If the set S includes ·absent·, then any must be the
11192 * value.
11193 */
11194 completeWild->any = 1;
11195 if (completeWild->nsSet != NULL) {
11196 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11197 completeWild->nsSet = NULL;
11198 }
11199 if (completeWild->negNsSet != NULL) {
11200 xmlFree(completeWild->negNsSet);
11201 completeWild->negNsSet = NULL;
11202 }
11203 return (0);
11204 }
11205 cur = cur->next;
11206 }
11207 if (completeWild->negNsSet == NULL) {
11208 /*
11209 * 6.2 If the set S does not include ·absent·, then a pair of not
11210 * and ·absent· must be the value.
11211 */
11212 if (completeWild->nsSet != NULL) {
11213 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11214 completeWild->nsSet = NULL;
11215 }
11216 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
11217 if (completeWild->negNsSet == NULL)
11218 return (-1);
11219 completeWild->negNsSet->value = NULL;
11220 }
11221 return (0);
11222 }
11223 return (0);
11224
11225}
11226
Daniel Veillard50355f02004-06-08 17:52:16 +000011227/**
11228 * xmlSchemaIntersectWildcards:
11229 * @ctxt: the schema parser context
11230 * @completeWild: the first wildcard
11231 * @curWild: the second wildcard
11232 *
11233 * Intersects the namespace constraints of the given wildcards.
11234 * @completeWild will hold the resulting intersection.
11235 * Returns a positive error code on failure, -1 in case of an
11236 * internal error, 0 otherwise.
11237 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011238static int
11239xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
11240 xmlSchemaWildcardPtr completeWild,
11241 xmlSchemaWildcardPtr curWild)
11242{
William M. Brack803812b2004-06-03 02:11:24 +000011243 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000011244
11245 /*
11246 * 1 If O1 and O2 are the same value, then that value must be the
11247 * value.
11248 */
11249 if ((completeWild->any == curWild->any) &&
11250 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
11251 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
11252
11253 if ((completeWild->negNsSet == NULL) ||
11254 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
11255
11256 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000011257 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000011258
11259 /*
11260 * Check equality of sets.
11261 */
11262 cur = completeWild->nsSet;
11263 while (cur != NULL) {
11264 found = 0;
11265 curB = curWild->nsSet;
11266 while (curB != NULL) {
11267 if (cur->value == curB->value) {
11268 found = 1;
11269 break;
11270 }
11271 curB = curB->next;
11272 }
11273 if (!found)
11274 break;
11275 cur = cur->next;
11276 }
11277 if (found)
11278 return(0);
11279 } else
11280 return(0);
11281 }
11282 }
11283 /*
11284 * 2 If either O1 or O2 is any, then the other must be the value.
11285 */
11286 if ((completeWild->any != curWild->any) && (completeWild->any)) {
11287 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
11288 return(-1);
11289 return(0);
11290 }
11291 /*
11292 * 3 If either O1 or O2 is a pair of not and a value (a namespace
11293 * name or ·absent·) and the other is a set of (namespace names or
11294 * ·absent·), then that set, minus the negated value if it was in
11295 * the set, minus ·absent· if it was in the set, must be the value.
11296 */
11297 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
11298 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
11299 const xmlChar *neg;
11300
11301 if (completeWild->nsSet == NULL) {
11302 neg = completeWild->negNsSet->value;
11303 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
11304 return(-1);
11305 } else
11306 neg = curWild->negNsSet->value;
11307 /*
11308 * Remove absent and negated.
11309 */
11310 prev = NULL;
11311 cur = completeWild->nsSet;
11312 while (cur != NULL) {
11313 if (cur->value == NULL) {
11314 if (prev == NULL)
11315 completeWild->nsSet = cur->next;
11316 else
11317 prev->next = cur->next;
11318 xmlFree(cur);
11319 break;
11320 }
11321 prev = cur;
11322 cur = cur->next;
11323 }
11324 if (neg != NULL) {
11325 prev = NULL;
11326 cur = completeWild->nsSet;
11327 while (cur != NULL) {
11328 if (cur->value == neg) {
11329 if (prev == NULL)
11330 completeWild->nsSet = cur->next;
11331 else
11332 prev->next = cur->next;
11333 xmlFree(cur);
11334 break;
11335 }
11336 prev = cur;
11337 cur = cur->next;
11338 }
11339 }
11340
11341 return(0);
11342 }
11343 /*
11344 * 4 If both O1 and O2 are sets of (namespace names or ·absent·),
11345 * then the intersection of those sets must be the value.
11346 */
11347 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
11348 int found;
11349
11350 cur = completeWild->nsSet;
11351 prev = NULL;
11352 while (cur != NULL) {
11353 found = 0;
11354 curB = curWild->nsSet;
11355 while (curB != NULL) {
11356 if (cur->value == curB->value) {
11357 found = 1;
11358 break;
11359 }
11360 curB = curB->next;
11361 }
11362 if (!found) {
11363 if (prev == NULL)
11364 completeWild->nsSet = cur->next;
11365 else
11366 prev->next = cur->next;
11367 tmp = cur->next;
11368 xmlFree(cur);
11369 cur = tmp;
11370 continue;
11371 }
11372 prev = cur;
11373 cur = cur->next;
11374 }
11375
11376 return(0);
11377 }
11378 /* 5 If the two are negations of different namespace names,
11379 * then the intersection is not expressible
11380 */
11381 if ((completeWild->negNsSet != NULL) &&
11382 (curWild->negNsSet != NULL) &&
11383 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
11384 (completeWild->negNsSet->value != NULL) &&
11385 (curWild->negNsSet->value != NULL)) {
11386
11387 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011388 "The intersection of the wilcard is not expressible.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +000011389 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000011390 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +000011391 }
11392 /*
11393 * 6 If the one is a negation of a namespace name and the other
11394 * is a negation of ·absent·, then the one which is the negation
11395 * of a namespace name must be the value.
11396 */
11397 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
11398 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
11399 (completeWild->negNsSet->value == NULL)) {
11400 completeWild->negNsSet->value = curWild->negNsSet->value;
11401 }
11402 return(0);
11403}
11404
Daniel Veillard50355f02004-06-08 17:52:16 +000011405/**
11406 * xmlSchemaIsWildcardNsConstraintSubset:
11407 * @ctxt: the schema parser context
11408 * @wildA: the first wildcard
11409 * @wildB: the second wildcard
11410 *
11411 * Returns 1 if the namespace constraint of @wildA is an intensional
11412 * subset of @wildB, 0 otherwise.
11413 */
11414static int
Daniel Veillardc0826a72004-08-10 14:17:33 +000011415xmlSchemaIsWildcardNsConstraintSubset(xmlSchemaWildcardPtr wildA,
11416 xmlSchemaWildcardPtr wildB)
Daniel Veillard50355f02004-06-08 17:52:16 +000011417{
Daniel Veillard3646d642004-06-02 19:19:14 +000011418
Daniel Veillard50355f02004-06-08 17:52:16 +000011419 /*
11420 * Schema Component Constraint: Wildcard Subset
11421 */
11422 /*
11423 * 1 super must be any.
11424 */
11425 if (wildB->any)
11426 return (1);
11427 /*
11428 * 2.1 sub must be a pair of not and a namespace name or ·absent·.
11429 * 2.2 super must be a pair of not and the same value.
11430 */
11431 if ((wildA->negNsSet != NULL) &&
11432 (wildB->negNsSet != NULL) &&
11433 (wildA->negNsSet->value == wildA->negNsSet->value))
11434 return (1);
11435 /*
11436 * 3.1 sub must be a set whose members are either namespace names or ·absent·.
11437 */
11438 if (wildA->nsSet != NULL) {
11439 /*
11440 * 3.2.1 super must be the same set or a superset thereof.
11441 */
11442 if (wildB->nsSet != NULL) {
11443 xmlSchemaWildcardNsPtr cur, curB;
11444 int found = 0;
11445
11446 cur = wildA->nsSet;
11447 while (cur != NULL) {
11448 found = 0;
11449 curB = wildB->nsSet;
11450 while (curB != NULL) {
11451 if (cur->value == curB->value) {
11452 found = 1;
11453 break;
11454 }
11455 curB = curB->next;
11456 }
11457 if (!found)
11458 return (0);
11459 cur = cur->next;
11460 }
11461 if (found)
11462 return (1);
11463 } else if (wildB->negNsSet != NULL) {
11464 xmlSchemaWildcardNsPtr cur;
11465 /*
11466 * 3.2.2 super must be a pair of not and a namespace name or
11467 * ·absent· and that value must not be in sub's set.
11468 */
11469 cur = wildA->nsSet;
11470 while (cur != NULL) {
11471 if (cur->value == wildB->negNsSet->value)
11472 return (0);
11473 cur = cur->next;
11474 }
11475 return (1);
11476 }
11477 }
11478 return (0);
11479}
11480
11481/**
11482 * xmlSchemaBuildCompleteAttributeWildcard:
11483 * @ctxt: the schema parser context
11484 * @attrs: the attribute list
11485 * @completeWild: the resulting complete wildcard
11486 *
11487 * Returns -1 in case of an internal error, 0 otherwise.
11488 */
11489static int
11490xmlSchemaBuildCompleteAttributeWildcard(xmlSchemaParserCtxtPtr ctxt,
11491 xmlSchemaAttributePtr attrs,
11492 xmlSchemaWildcardPtr *completeWild)
Daniel Veillard3646d642004-06-02 19:19:14 +000011493{
11494 while (attrs != NULL) {
11495 if (attrs->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
11496 xmlSchemaAttributeGroupPtr group;
11497
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011498 group = (xmlSchemaAttributeGroupPtr) attrs;
11499 /*
11500 * Handle attribute group references.
11501 */
11502 if (group->ref != NULL) {
11503 if (group->refItem == NULL) {
11504 /*
11505 * TODO: Should we raise a warning here?
11506 */
11507 /*
11508 * The referenced attribute group definition could not
11509 * be resolved beforehand, so skip.
11510 */
11511 attrs = attrs->next;
11512 continue;
11513 } else
11514 group = group->refItem;
11515 }
11516 /*
11517 * For every attribute group definition, an intersected wildcard
11518 * will be created (assumed that a wildcard exists on the
11519 * particular attr. gr. def. or on any contained attr. gr. def
11520 * at all).
11521 * The flag XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED ensures
11522 * that the intersection will be performed only once.
11523 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011524 if ((group->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
11525 if (group->attributes != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000011526 if (xmlSchemaBuildCompleteAttributeWildcard(ctxt,
11527 group->attributes, &group->attributeWildcard) == -1)
11528 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000011529 }
11530 group->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
11531 }
11532 if (group->attributeWildcard != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000011533 if (*completeWild == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011534 /*
11535 * Copy the first encountered wildcard as context, except for the annotation.
11536 */
Daniel Veillard50355f02004-06-08 17:52:16 +000011537 *completeWild = xmlSchemaAddWildcard(ctxt);
11538 (*completeWild)->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
11539 if (xmlSchemaCloneWildcardNsConstraints(ctxt,
11540 completeWild, group->attributeWildcard) == -1)
11541 return (-1);
11542 (*completeWild)->processContents = group->attributeWildcard->processContents;
Daniel Veillard3646d642004-06-02 19:19:14 +000011543 /*
11544 * Although the complete wildcard might not correspond to any
11545 * node in the schema, we will save this context node.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011546 * TODO: Hmm, is this sane?
Daniel Veillard3646d642004-06-02 19:19:14 +000011547 */
Daniel Veillard50355f02004-06-08 17:52:16 +000011548 (*completeWild)->node = group->attributeWildcard->node;
11549
11550 } else if (xmlSchemaIntersectWildcards(ctxt, *completeWild, group->attributeWildcard) == -1) {
11551 xmlSchemaFreeWildcard(*completeWild);
11552 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000011553 }
11554 }
11555 }
11556 attrs = attrs->next;
11557 }
11558
Daniel Veillard50355f02004-06-08 17:52:16 +000011559 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000011560}
11561
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011562static int
11563xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributePtr item,
11564 int *fixed,
11565 const xmlChar **value,
11566 xmlSchemaValPtr *val)
11567{
11568 *fixed = 0;
11569 *value = NULL;
11570 if (val != 0)
11571 *val = NULL;
11572
11573 if (item->defValue == NULL)
11574 item = item->refDecl;
11575
11576 if (item == NULL)
11577 return (0);
11578
11579 if (item->defValue != NULL) {
11580 *value = item->defValue;
11581 if (val != 0)
11582 *val = item->defVal;
11583 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
11584 *fixed = 1;
11585 return (1);
11586 }
11587 return (0);
11588}
Daniel Veillard3646d642004-06-02 19:19:14 +000011589/**
11590 * xmlSchemaMatchesWildcardNs:
11591 * @wild: the wildcard
11592 * @ns: the namespace
11593 *
11594 *
11595 * Returns 1 if the given namespace matches the wildcard,
11596 * 0 otherwise.
11597 */
11598static int
11599xmlSchemaMatchesWildcardNs(xmlSchemaWildcardPtr wild, const xmlChar* ns)
11600{
11601 if (wild == NULL)
11602 return(0);
11603
11604 if (wild->any)
11605 return(1);
11606 else if (wild->nsSet != NULL) {
11607 xmlSchemaWildcardNsPtr cur;
11608
11609 cur = wild->nsSet;
11610 while (cur != NULL) {
11611 if (xmlStrEqual(cur->value, ns))
11612 return(1);
11613 cur = cur->next;
11614 }
11615 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
11616 (!xmlStrEqual(wild->negNsSet->value, ns)))
11617 return(1);
11618
11619 return(0);
11620}
11621
11622/**
11623 * xmlSchemaBuildAttributeValidation:
11624 * @ctxt: the schema parser context
11625 * @type: the complex type definition
11626 *
11627 *
11628 * Builds the wildcard and the attribute uses on the given complex type.
11629 * Returns -1 if an internal error occurs, 0 otherwise.
11630 */
11631static int
11632xmlSchemaBuildAttributeValidation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaTypePtr type)
11633{
11634 xmlSchemaTypePtr baseType = NULL;
11635 xmlSchemaAttributeLinkPtr cur, base, tmp, id = NULL, prev = NULL, uses = NULL,
William M. Brack803812b2004-06-03 02:11:24 +000011636 lastUse = NULL, lastBaseUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000011637 xmlSchemaAttributePtr attrs;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011638 xmlSchemaTypePtr anyType;
Daniel Veillard50355f02004-06-08 17:52:16 +000011639 int baseIsAnyType = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011640 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000011641 int err = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000011642
Daniel Veillard01fa6152004-06-29 17:04:39 +000011643 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Daniel Veillard3646d642004-06-02 19:19:14 +000011644 /*
11645 * Complex Type Definition with complex content Schema Component.
11646 *
11647 * Attribute uses.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011648 * TODO: Add checks for absent referenced attribute declarations and
11649 * simple types.
Daniel Veillard3646d642004-06-02 19:19:14 +000011650 */
11651 if (type->attributeUses != NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011652 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011653 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillard3646d642004-06-02 19:19:14 +000011654 "attribute uses already builded.\n",
11655 NULL, NULL);
11656 return (-1);
11657 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011658 if (type->baseType == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011659 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011660 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011661 "complex type '%s' has no base type.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011662 type->name, NULL);
11663 return (-1);
11664 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011665 baseType = type->baseType;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011666 if (baseType == anyType)
11667 baseIsAnyType = 1;
11668 /*
11669 * Inherit the attribute uses of the base type.
11670 */
11671 /*
11672 * NOTE: It is allowed to "extend" the anyType complex type.
11673 */
11674 if (!baseIsAnyType) {
11675 if (baseType != NULL) {
11676 for (cur = baseType->attributeUses; cur != NULL; cur = cur->next) {
11677 tmp = (xmlSchemaAttributeLinkPtr)
11678 xmlMalloc(sizeof(xmlSchemaAttributeLink));
11679 if (tmp == NULL) {
11680 xmlSchemaPErrMemory(ctxt,
11681 "building attribute uses of complexType", NULL);
11682 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000011683 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011684 tmp->attr = cur->attr;
11685 tmp->next = NULL;
11686 if (type->attributeUses == NULL) {
11687 type->attributeUses = tmp;
11688 } else
11689 lastBaseUse->next = tmp;
11690 lastBaseUse = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000011691 }
11692 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011693 }
11694 if ((type->subtypes != NULL) &&
11695 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
11696 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011697 /*
11698 * type --> (<simpleContent>|<complexContent>)
11699 * --> (<restriction>|<extension>) --> attributes
11700 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011701 attrs = type->subtypes->subtypes->attributes;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011702 } else {
11703 /* Short hand form of the complexType. */
11704 attrs = type->attributes;
11705 }
11706 /*
11707 * Handle attribute wildcards.
11708 */
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000011709 err = xmlSchemaBuildCompleteAttributeWildcard(ctxt,
11710 attrs, &type->attributeWildcard);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011711 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011712 * NOTE: During the parse time, the wildcard is created on the complexType
11713 * directly, if encountered in a <restriction> or <extension> element.
Daniel Veillard01fa6152004-06-29 17:04:39 +000011714 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011715 if (err == -1) {
11716 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
11717 "Internal error: xmlSchemaBuildAttributeValidation: "
11718 "failed to build an intersected attribute wildcard.\n",
11719 NULL, NULL);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000011720 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011721 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011722
11723 if ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
11724 ((baseIsAnyType) ||
11725 ((baseType != NULL) &&
11726 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
11727 (baseType->attributeWildcard != NULL)))) {
11728 if (type->attributeWildcard != NULL) {
11729 /*
11730 * Union the complete wildcard with the base wildcard.
11731 */
11732 if (xmlSchemaUnionWildcards(ctxt, type->attributeWildcard,
11733 baseType->attributeWildcard) == -1)
11734 return (-1);
11735 } else {
11736 /*
11737 * Just inherit the wildcard.
11738 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011739 /*
11740 * NOTE: This is the only case where an attribute
11741 * wildcard is shared.
11742 */
11743 if (type->flags & XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD)
11744 type->flags ^= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011745 type->attributeWildcard = baseType->attributeWildcard;
Daniel Veillard50355f02004-06-08 17:52:16 +000011746 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011747 }
11748
11749 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
11750 if (type->attributeWildcard != NULL) {
11751 /*
11752 * Derivation Valid (Restriction, Complex)
11753 * 4.1 The {base type definition} must also have one.
11754 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011755 if (baseType->attributeWildcard == NULL) {
11756 xmlSchemaPCustomErr(ctxt,
11757 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
11758 NULL, type, NULL,
11759 "The type has an attribute wildcard, "
11760 "but the base type %s does not have one",
11761 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11762 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011763 return (1);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011764 } else if (xmlSchemaIsWildcardNsConstraintSubset(
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011765 type->attributeWildcard, baseType->attributeWildcard) == 0) {
11766 /* 4.2 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011767 xmlSchemaPCustomErr(ctxt,
11768 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
11769 NULL, type, NULL,
11770 "The attribute wildcard is not a valid "
11771 "subset of the wildcard in the base type %s",
11772 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11773 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011774 return (1);
11775 }
11776 /* 4.3 Unless the {base type definition} is the ·ur-type
11777 * definition·, the complex type definition's {attribute
11778 * wildcard}'s {process contents} must be identical to or
11779 * stronger than the {base type definition}'s {attribute
11780 * wildcard}'s {process contents}, where strict is stronger
11781 * than lax is stronger than skip.
11782 */
11783 if ((type->baseType != anyType) &&
11784 (type->attributeWildcard->processContents <
11785 baseType->attributeWildcard->processContents)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011786 xmlSchemaPCustomErr(ctxt,
11787 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
11788 NULL, type, NULL,
11789 "The 'process contents' of the attribute wildcard is weaker than "
11790 "the one in the base type %s",
11791 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11792 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011793 return (1);
11794 }
11795 }
11796 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
11797 /*
11798 * Derivation Valid (Extension)
11799 * At this point the type and the base have both, either
11800 * no wildcard or a wildcard.
11801 */
11802 if ((baseType->attributeWildcard != NULL) &&
11803 (baseType->attributeWildcard != type->attributeWildcard)) {
11804 /* 1.3 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011805 if (xmlSchemaIsWildcardNsConstraintSubset(
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011806 baseType->attributeWildcard, type->attributeWildcard) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011807 xmlSchemaPCustomErr(ctxt,
11808 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
11809 NULL, type, NULL,
11810 "The attribute wildcard is not a valid "
11811 "superset of the one in the base type %s",
11812 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11813 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011814 return (1);
11815 }
11816 }
11817 }
11818
Daniel Veillard3646d642004-06-02 19:19:14 +000011819 /*
11820 * Gather attribute uses defined by this type.
11821 */
11822 if (attrs != NULL) {
11823 if (xmlSchemaBuildAttributeUsesOwned(ctxt, attrs,
11824 &uses, &lastUse) == -1) {
11825 return (-1);
11826 }
11827 }
11828 /* 3.4.6 -> Complex Type Definition Properties Correct 4.
11829 * "Two distinct attribute declarations in the {attribute uses} must
11830 * not have identical {name}s and {target namespace}s."
11831 *
11832 * For "extension" this is done further down.
11833 */
11834 if ((uses != NULL) && ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
11835 cur = uses;
11836 while (cur != NULL) {
11837 tmp = cur->next;
11838 while (tmp != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011839 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
11840 xmlSchemaGetAttrName(tmp->attr))) &&
11841 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
11842 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
11843
11844 xmlSchemaPAttrUseErr(ctxt,
11845 XML_SCHEMAP_CT_PROPS_CORRECT_4,
11846 NULL, type, NULL, cur->attr,
11847 "Duplicate attribute use %s specified",
11848 xmlSchemaFormatNsUriLocal(&str,
11849 xmlSchemaGetAttrTargetNsURI(tmp->attr),
11850 xmlSchemaGetAttrName(tmp->attr))
11851 );
11852 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000011853 break;
11854 }
11855 tmp = tmp->next;
11856 }
11857 cur = cur->next;
11858 }
11859 }
11860 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
11861 /*
11862 * Derive by restriction.
11863 */
11864 if (baseIsAnyType) {
11865 type->attributeUses = uses;
11866 } else {
11867 int found;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011868 const xmlChar *bEffValue;
11869 int effFixed;
Daniel Veillard3646d642004-06-02 19:19:14 +000011870
11871 cur = uses;
11872 while (cur != NULL) {
11873 found = 0;
11874 base = type->attributeUses;
11875 while (base != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011876 if (xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
11877 xmlSchemaGetAttrName(base->attr)) &&
11878 xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
11879 xmlSchemaGetAttrTargetNsURI(base->attr))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011880
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011881 found = 1;
11882
Daniel Veillard3646d642004-06-02 19:19:14 +000011883 if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
11884 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
11885 /*
11886 * derivation-ok-restriction 2.1.1
Daniel Veillardc0826a72004-08-10 14:17:33 +000011887 */
11888 xmlSchemaPAttrUseErr(ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000011889 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011890 NULL, type, NULL, cur->attr,
11891 "The 'optional' use is inconsistent with a matching "
11892 "'required' use of the base type", NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000011893 } else if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
11894 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
11895 /*
11896 * derivation-ok-restriction 3
11897 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011898 xmlSchemaPCustomErr(ctxt,
11899 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
11900 NULL, type, NULL,
11901 "A matching attribute use for the 'required' "
11902 "attribute use %s of the base type is missing",
11903 xmlSchemaFormatNsUriLocal(&str,
11904 xmlSchemaGetAttrTargetNsURI(base->attr),
11905 xmlSchemaGetAttrName(base->attr)));
11906 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000011907 } else {
11908 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011909 * 2.1.3 [Definition:] Let the effective value
11910 * constraint of an attribute use be its {value
11911 * constraint}, if present, otherwise its {attribute
11912 * declaration}'s {value constraint} .
11913 */
11914 xmlSchemaGetEffectiveValueConstraint(base->attr, &effFixed,
11915 &bEffValue, 0);
11916 /*
11917 * 2.1.3 ... one of the following must be true
11918 *
11919 * 2.1.3.1 B's ·effective value constraint· is
11920 * ·absent· or default.
11921 */
11922 if ((bEffValue != NULL) &&
11923 (effFixed == 1)) {
11924 const xmlChar *rEffValue = NULL;
11925
11926 xmlSchemaGetEffectiveValueConstraint(base->attr, &effFixed,
11927 &rEffValue, 0);
11928 /*
11929 * 2.1.3.2 R's ·effective value constraint· is
11930 * fixed with the same string as B's.
11931 */
11932 if ((effFixed == 0) ||
11933 (! xmlStrEqual(rEffValue, bEffValue))) {
11934 xmlSchemaPAttrUseErr(ctxt,
11935 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
11936 NULL, type, NULL, cur->attr,
11937 "The effective value constraint of the "
11938 "attribute use is inconsistent with "
11939 "its correspondent of the base type",
11940 NULL);
11941 }
11942 }
11943 /*
11944 * TODO: derivation-ok-restriction 2.1.2 ({type definition} must be validly derived)
11945 */
11946 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000011947 * Override the attribute use.
11948 */
11949 base->attr = cur->attr;
11950 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011951
Daniel Veillard3646d642004-06-02 19:19:14 +000011952 break;
11953 }
11954 base = base->next;
11955 }
11956
11957 if (!found) {
11958 if (cur->attr->occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
11959 /*
11960 * derivation-ok-restriction 2.2
11961 */
11962 if ((type->attributeWildcard != NULL) &&
11963 xmlSchemaMatchesWildcardNs(type->attributeWildcard,
11964 cur->attr->targetNamespace))
11965 found = 1;
11966
11967 if (!found) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011968 xmlSchemaPAttrUseErr(ctxt,
11969 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
11970 NULL, type, NULL, cur->attr,
11971 "Neither a matching attribute use, "
11972 "nor a matching wildcard in the base type does exist",
11973 NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000011974 } else {
11975 /*
11976 * Add the attribute use.
11977 *
11978 * Note that this may lead to funny derivation error reports, if
11979 * multiple equal attribute uses exist; but this is not
11980 * allowed anyway, and it will be reported beforehand.
11981 */
11982 tmp = cur;
11983 if (prev != NULL)
11984 prev->next = cur->next;
11985 else
11986 uses = cur->next;
11987 cur = cur->next;
11988 if (type->attributeUses == NULL) {
11989 type->attributeUses = tmp;
11990 } else
11991 lastBaseUse->next = tmp;
11992 lastBaseUse = tmp;
11993
11994 continue;
11995 }
11996 }
11997 }
11998 prev = cur;
11999 cur = cur->next;
12000 }
12001 if (uses != NULL)
12002 xmlSchemaFreeAttributeUseList(uses);
12003 }
12004 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
12005 /*
12006 * The spec allows only appending, and not other kinds of extensions.
12007 *
12008 * This ensures: Schema Component Constraint: Derivation Valid (Extension) : 1.2
12009 */
12010 if (uses != NULL) {
12011 if (type->attributeUses == NULL) {
12012 type->attributeUses = uses;
12013 } else
12014 lastBaseUse->next = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000012015 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012016 } else {
12017 /*
Daniel Veillard50355f02004-06-08 17:52:16 +000012018 * Derive implicitely from the ur-type.
12019 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012020 type->attributeUses = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000012021 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012022 /*
12023 * 3.4.6 -> Complex Type Definition Properties Correct
12024 */
12025 if (type->attributeUses != NULL) {
12026 cur = type->attributeUses;
12027 prev = NULL;
12028 while (cur != NULL) {
12029 /*
12030 * 4. Two distinct attribute declarations in the {attribute uses} must
12031 * not have identical {name}s and {target namespace}s.
Daniel Veillard50355f02004-06-08 17:52:16 +000012032 *
Daniel Veillard3646d642004-06-02 19:19:14 +000012033 * Note that this was already done for "restriction" and types derived from
12034 * the ur-type.
Daniel Veillard50355f02004-06-08 17:52:16 +000012035 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012036 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
12037 tmp = cur->next;
12038 while (tmp != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012039 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
12040 xmlSchemaGetAttrName(tmp->attr))) &&
12041 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
12042 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012043
Daniel Veillardc0826a72004-08-10 14:17:33 +000012044 xmlSchemaPAttrUseErr(ctxt,
12045 XML_SCHEMAP_CT_PROPS_CORRECT_4,
12046 NULL, type, NULL, tmp->attr,
12047 "Duplicate attribute use specified", NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000012048 break;
12049 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012050 tmp = tmp->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000012051 }
12052 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012053 /*
12054 * 5. Two distinct attribute declarations in the {attribute uses} must
12055 * not have {type definition}s which are or are derived from ID.
12056 */
12057 if ((cur->attr->subtypes != NULL) &&
Daniel Veillard01fa6152004-06-29 17:04:39 +000012058 (xmlSchemaIsDerivedFromBuiltInType(ctxt, (xmlSchemaTypePtr) cur->attr, XML_SCHEMAS_ID))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012059 if (id != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012060 xmlSchemaPAttrUseErr(ctxt,
12061 XML_SCHEMAP_CT_PROPS_CORRECT_5,
12062 NULL, type, NULL, cur->attr,
12063 "There must not exist more than one attribute use, "
12064 "declared of type 'ID' or derived from it",
12065 NULL);
12066 FREE_AND_NULL(str)
Daniel Veillard50355f02004-06-08 17:52:16 +000012067 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012068 id = cur;
12069 }
12070 /*
12071 * Remove "prohibited" attribute uses. The reason this is done at this late
12072 * stage is to be able to catch dublicate attribute uses. So we had to keep
12073 * prohibited uses in the list as well.
12074 */
12075 if (cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
12076 tmp = cur;
12077 if (prev == NULL)
12078 type->attributeUses = cur->next;
12079 else
12080 prev->next = cur->next;
12081 cur = cur->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000012082 xmlFree(tmp);
Daniel Veillard3646d642004-06-02 19:19:14 +000012083 } else {
12084 prev = cur;
12085 cur = cur->next;
12086 }
12087 }
12088 }
12089 /*
12090 * TODO: This check should be removed if we are 100% sure of
12091 * the base type attribute uses already being built.
12092 */
12093 if ((baseType != NULL) && (!baseIsAnyType) &&
12094 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
12095 (baseType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012096 xmlSchemaPErr(ctxt, baseType->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012097 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012098 "attribute uses not builded on base type '%s'.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +000012099 baseType->name, NULL);
12100 }
12101 return (0);
12102}
12103
12104/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000012105 * xmlSchemaTypeFinalContains:
12106 * @schema: the schema
12107 * @type: the type definition
12108 * @final: the final
12109 *
12110 * Evaluates if a type definition contains the given "final".
12111 * This does take "finalDefault" into account as well.
12112 *
12113 * Returns 1 if the type does containt the given "final",
12114 * 0 otherwise.
12115 */
12116static int
12117xmlSchemaTypeFinalContains(xmlSchemaPtr schema, xmlSchemaTypePtr type, int final)
12118{
12119 int tfinal = final, tflags = type->flags;
12120
12121 if (type == NULL)
12122 return (0);
12123 if (type->flags & XML_SCHEMAS_TYPE_FINAL_DEFAULT) {
12124 switch (final) {
12125 case XML_SCHEMAS_TYPE_FINAL_RESTRICTION:
12126 tfinal = XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
12127 break;
12128 case XML_SCHEMAS_TYPE_FINAL_EXTENSION:
12129 tfinal = XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
12130 break;
12131 case XML_SCHEMAS_TYPE_FINAL_LIST:
12132 tfinal = XML_SCHEMAS_FINAL_DEFAULT_LIST;
12133 break;
12134 case XML_SCHEMAS_TYPE_FINAL_UNION:
12135 tfinal = XML_SCHEMAS_FINAL_DEFAULT_UNION;
12136 break;
12137 }
12138 tflags = schema->flags;
12139 }
12140 if (tflags & tfinal)
12141 return (1);
12142 else
12143 return (0);
12144
12145}
12146
12147/**
12148 * xmlSchemaGetUnionSimpleTypeMemberTypes:
12149 * @type: the Union Simple Type
12150 *
12151 * Returns a list of member types of @type if existing,
12152 * returns NULL otherwise.
12153 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012154static xmlSchemaTypeLinkPtr
Daniel Veillard01fa6152004-06-29 17:04:39 +000012155xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
12156{
12157 while (type != NULL) {
12158 if (type->memberTypes != NULL)
12159 return (type->memberTypes);
12160 else
12161 type = type->baseType;
12162 }
12163 return (NULL);
12164}
12165
12166/**
12167 * xmlSchemaGetListSimpleTypeItemType:
12168 * @type: the simple type definition
12169 *
12170 * Returns the item type definition of the list simple type.
12171 */
12172static xmlSchemaTypePtr
12173xmlSchemaGetListSimpleTypeItemType(xmlSchemaTypePtr type)
12174{
12175 if ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)
12176 return (NULL);
12177 /*
12178 * Note: In libxml2, the built-in types do not reflect
12179 * the datatype hierarchy (yet?) - we have to treat them
12180 * in a special way.
12181 */
12182 if (type->type == XML_SCHEMA_TYPE_BASIC)
12183 return (xmlSchemaGetBuiltInListSimpleTypeItemType(type));
12184 if (type->subtypes->type == XML_SCHEMA_TYPE_LIST)
12185 /* 1 If the <list> alternative is chosen, then the type
12186 * definition ·resolved· to by the ·actual value· of the
12187 * itemType [attribute] of <list>, if present, otherwise
12188 * the type definition corresponding to the <simpleType>
12189 * among the [children] of <list>.
12190 */
12191 return (type->subtypes->subtypes);
12192 else {
12193 /* 2 If the <restriction> option is chosen, then the
12194 * {item type definition} of the {base type definition}.
12195 */
12196 return (xmlSchemaGetListSimpleTypeItemType(type->baseType));
12197 }
12198}
12199
12200/**
12201 * xmlSchemaCheckCOSSTDerivedOK:
12202 * @type: the derived simple type definition
12203 * @baseType: the base type definition
12204 *
12205 * Checks wheter @type can be validly
12206 * derived from @baseType.
12207 *
12208 * Returns 0 on success, an positive error code otherwise.
12209 */
12210static int
12211xmlSchemaCheckCOSSTDerivedOK(xmlSchemaPtr schema,
12212 xmlSchemaTypePtr type,
12213 xmlSchemaTypePtr baseType,
12214 int subset)
12215{
12216 /*
12217 * Schema Component Constraint: Type Derivation OK (Simple)
12218 *
12219 *
12220 * 1 They are the same type definition.
12221 * TODO: The identy check might have to be more complex than this.
12222 */
12223 if (type == baseType)
12224 return (0);
12225 /*
12226 * 2.1 restriction is not in the subset, or in the {final}
12227 * of its own {base type definition};
12228 */
12229 if ((subset & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) ||
12230 (xmlSchemaTypeFinalContains(schema,
12231 type->baseType, XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
12232 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
12233 }
12234 /* 2.2 */
12235 if (type->baseType == baseType) {
12236 /*
12237 * 2.2.1 D's ·base type definition· is B.
12238 */
12239 return (0);
12240 }
12241 /*
12242 * 2.2.2 D's ·base type definition· is not the ·ur-type definition·
12243 * and is validly derived from B given the subset, as defined by this
12244 * constraint.
12245 */
12246 if ((type->baseType != xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE)) &&
12247 (xmlSchemaCheckCOSSTDerivedOK(schema, type->baseType, baseType, subset) == 0)) {
12248 return (0);
12249 }
12250 /*
12251 * 2.2.3 D's {variety} is list or union and B is the ·simple ur-type
12252 * definition·.
12253 */
12254 if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
12255 (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)) &&
12256 (baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE))) {
12257 return (0);
12258 }
12259 /*
12260 * 2.2.4 B's {variety} is union and D is validly derived from a type
12261 * definition in B's {member type definitions} given the subset, as
12262 * defined by this constraint.
12263 *
12264 * NOTE: This seems not to involve built-in types, since there is no
12265 * built-in Union Simple Type.
12266 */
12267 if (baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
12268 xmlSchemaTypeLinkPtr cur;
12269
12270 cur = baseType->memberTypes;
12271 while (cur != NULL) {
12272 if (xmlSchemaCheckCOSSTDerivedOK(schema, type,
12273 cur->type, subset) == 0)
12274 return (0);
12275 cur = cur->next;
12276 }
12277 }
12278
12279 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
12280}
12281
12282
12283/**
12284 * xmlSchemaCheckSTPropsCorrect:
12285 * @ctxt: the schema parser context
12286 * @type: the simple type definition
12287 *
12288 * Checks st-props-correct.
12289 *
12290 * Returns 0 if the properties are correct,
12291 * if not, a positive error code and -1 on internal
12292 * errors.
12293 */
12294static int
12295xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
12296 xmlSchemaTypePtr type)
12297{
12298 xmlSchemaTypePtr baseType = type->baseType, anySimpleType,
12299 anyType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012300 xmlChar *str = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012301
Daniel Veillardc0826a72004-08-10 14:17:33 +000012302 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012303 /*
12304 * Schema Component Constraint: Simple Type Definition Properties Correct
12305 *
12306 * NOTE: This is somehow redundant, since we actually built a simple type
12307 * to have all the needed information; this acts as an self test.
12308 */
12309 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
12310 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
12311 /*
12312 * TODO: 1 The values of the properties of a simple type definition must be as
12313 * described in the property tableau in Datatype definition, modulo the
12314 * impact of Missing Sub-components (§5.3).
12315 */
12316 /* Base type: If the datatype has been ·derived· by ·restriction·
12317 * then the Simple Type Definition component from which it is ·derived·,
12318 * otherwise the Simple Type Definition for anySimpleType (§4.1.6).
12319 */
12320 if (baseType == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012321 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012322 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012323 NULL, type, NULL,
12324 "No base type existent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012325 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
12326 }
12327 if ((baseType->type != XML_SCHEMA_TYPE_SIMPLE) &&
12328 ((baseType->type != XML_SCHEMA_TYPE_BASIC) ||
12329 (baseType == anyType))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012330 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012331 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012332 NULL, type, NULL,
12333 "The base type %s is not a simple type",
12334 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
12335 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012336 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
12337 }
12338 if ((baseType != anySimpleType) &&
12339 (type->subtypes->type != XML_SCHEMA_TYPE_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012340 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012341 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012342 NULL, type, NULL,
12343 "A type, derived by list or union, must have"
12344 "the simple ur-type definition as base type, not %s",
12345 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
12346 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012347 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
12348 }
12349 /*
12350 * Variety: One of {atomic, list, union}.
12351 */
12352 if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
12353 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) &&
12354 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012355 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012356 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012357 NULL, type, NULL,
12358 "The variety is absent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012359 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
12360 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000012361 /* TODO: Finish this. Hmm, is this finished? */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012362
12363 /*
12364 * 2 All simple type definitions must be derived ultimately from the ·simple
12365 * ur-type definition (so· circular definitions are disallowed). That is, it
12366 * must be possible to reach a built-in primitive datatype or the ·simple
12367 * ur-type definition· by repeatedly following the {base type definition}.
12368 */
12369 baseType = type->baseType;
12370 while ((baseType != NULL) && (baseType->type != XML_SCHEMA_TYPE_BASIC)) {
12371 if (baseType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
12372 xmlSchemaTypeFixup(baseType, ctxt, NULL);
12373 if (baseType == anySimpleType)
12374 break;
12375 else if (baseType == type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012376 xmlSchemaPCustomErr(ctxt,
12377 XML_SCHEMAP_ST_PROPS_CORRECT_2,
12378 NULL, type, NULL,
12379 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012380 return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
12381 }
12382 baseType = baseType->baseType;
12383 }
12384 /*
12385 * 3 The {final} of the {base type definition} must not contain restriction.
12386 */
12387 if (xmlSchemaTypeFinalContains(ctxt->schema, baseType,
12388 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012389 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012390 XML_SCHEMAP_ST_PROPS_CORRECT_3,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012391 NULL, type, NULL,
12392 "The 'final' of its base type %s must not contain "
12393 "'restriction'",
12394 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
12395 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012396 return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
12397 }
12398 return (0);
12399}
12400
12401/**
12402 * xmlSchemaCheckDerivationValidSimpleRestriction:
12403 * @ctxt: the schema parser context
12404 * @type: the simple type definition
12405 *
12406 * Checks if the given @type (simpleType) is derived
12407 * validly by restriction.
12408 *
12409 * Returns -1 on internal errors, 0 if the type is validly derived,
12410 * a positive error code otherwise.
12411 */
12412static int
12413xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012414 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012415{
Daniel Veillardc0826a72004-08-10 14:17:33 +000012416 xmlChar *str = NULL;
12417
12418 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012419
12420 if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
12421 xmlSchemaPErr(ctxt, type->node,
12422 XML_ERR_INTERNAL_ERROR,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012423 "xmlSchemaCheckDerivationValidSimpleRestriction: The given "
12424 "type '%s' is not a user-derived simpleType.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012425 type->name, NULL);
12426 return (-1);
12427 }
12428
12429 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
12430 xmlSchemaTypePtr primitive;
12431 /*
12432 * 1.1 The {base type definition} must be an atomic simple
12433 * type definition or a built-in primitive datatype.
12434 */
12435 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012436 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012437 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012438 NULL, type, NULL,
12439 "The base type %s is not an atomic simple type",
12440 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
12441 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012442 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
12443 }
12444 /* 1.2 The {final} of the {base type definition} must not contain
12445 * restriction.
12446 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000012447 /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012448 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
12449 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012450 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012451 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012452 NULL, type, NULL,
12453 "The final of its base type %s must not contain 'restriction'",
12454 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
12455 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012456 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
12457 }
12458
12459 /*
12460 * 1.3.1 DF must be an allowed constraining facet for the {primitive
12461 * type definition}, as specified in the appropriate subsection of 3.2
12462 * Primitive datatypes.
12463 */
12464 if (type->facets != NULL) {
12465 xmlSchemaFacetPtr facet;
12466 int ok = 1;
12467
12468 primitive = xmlSchemaGetPrimitiveType(type);
12469 if (primitive == NULL) {
12470 xmlSchemaPErr(ctxt, type->node,
12471 XML_ERR_INTERNAL_ERROR,
12472 "xmlSchemaCheckDerivationValidSimpleRestriction: failed "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012473 "to get primitive type of type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012474 type->name, NULL);
12475 return (-1);
12476 }
12477 facet = type->facets;
12478 do {
12479 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012480 ok = 0;
12481 xmlSchemaPIllegalFacetAtomicErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012482 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012483 NULL, type, primitive, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012484 }
12485 facet = facet->next;
12486 } while (facet != NULL);
12487 if (ok == 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +000012488 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012489 }
12490 /*
12491 * TODO: 1.3.2 (facet derivation)
12492 */
12493 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
12494 xmlSchemaTypePtr itemType = NULL;
12495
12496 itemType = xmlSchemaGetListSimpleTypeItemType(type);
12497 if (itemType == NULL) {
12498 xmlSchemaPErr(ctxt, type->node,
12499 XML_ERR_INTERNAL_ERROR,
12500 "Internal error: xmlSchemaCheckDerivationValidSimpleRestriction: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012501 "failed to evaluate the item type of type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012502 type->name, NULL);
12503 return (-1);
12504 }
12505 /*
12506 * 2.1 The {item type definition} must have a {variety} of atomic or
12507 * union (in which case all the {member type definitions}
12508 * must be atomic).
12509 */
12510 if (((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
12511 ((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012512 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012513 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012514 NULL, type, NULL,
12515 "The item type %s must have a variety of atomic or union",
12516 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1));
12517 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012518 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
12519 } else if (itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
12520 xmlSchemaTypeLinkPtr member;
12521
12522 member = itemType->memberTypes;
12523 while (member != NULL) {
12524 if ((member->type->flags &
12525 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012526 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012527 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012528 NULL, type, NULL,
12529 "The item type is a union type, but the "
12530 "member type %s of this item type is not atomic",
12531 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
12532 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012533 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
12534 }
12535 member = member->next;
12536 }
12537 }
12538
12539 if (type->baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE)) {
12540 xmlSchemaFacetPtr facet;
12541 /*
12542 * This is the case if we have: <simpleType><list ..
12543 */
12544 /*
12545 * 2.3.1
12546 * 2.3.1.1 The {final} of the {item type definition} must not
12547 * contain list.
12548 */
12549 if (xmlSchemaTypeFinalContains(ctxt->schema,
12550 itemType, XML_SCHEMAS_TYPE_FINAL_LIST)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012551 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012552 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012553 NULL, type, NULL,
12554 "The final of its item type %s must not contain 'list'",
12555 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1));
12556 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012557 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
12558 }
12559 /*
12560 * 2.3.1.2 The {facets} must only contain the whiteSpace
12561 * facet component.
12562 */
12563 if (type->facets != NULL) {
12564 facet = type->facets;
12565 do {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012566 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
12567 xmlSchemaPIllegalFacetListUnionErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012568 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012569 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012570 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
12571 }
12572 facet = facet->next;
12573 } while (facet != NULL);
12574 }
12575 /*
12576 * TODO: Datatypes states:
12577 * A ·list· datatype can be ·derived· from an ·atomic· datatype
12578 * whose ·lexical space· allows space (such as string or anyURI)or
12579 * a ·union· datatype any of whose {member type definitions}'s
12580 * ·lexical space· allows space.
12581 */
12582 } else {
12583 /*
12584 * This is the case if we have: <simpleType><restriction ...
12585 */
12586 /*
12587 * 2.3.2
12588 * 2.3.2.1 The {base type definition} must have a {variety} of list.
12589 */
12590 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012591 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012592 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012593 NULL, type, NULL,
12594 "The base type %s must be a list type",
12595 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
12596 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012597 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
12598 }
12599 /*
12600 * 2.3.2.2 The {final} of the {base type definition} must not
12601 * contain restriction.
12602 */
12603 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
12604 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012605 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012606 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012607 NULL, type, NULL,
12608 "The final of the base type %s must not contain 'restriction'",
12609 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
12610 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012611 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
12612 }
12613 /*
12614 * 2.3.2.3 The {item type definition} must be validly derived
12615 * from the {base type definition}'s {item type definition} given
12616 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6).
12617 */
12618 {
12619 xmlSchemaTypePtr baseItemType;
12620
12621 baseItemType = xmlSchemaGetListSimpleTypeItemType(type->baseType);
12622 if (baseItemType == NULL) {
12623 xmlSchemaPErr(ctxt, type->node,
12624 XML_ERR_INTERNAL_ERROR,
12625 "xmlSchemaCheckDerivationValidSimpleRestriction: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012626 "List simple type '%s': Failed to "
12627 "evaluate the item type of its base type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012628 type->name, type->baseType->name);
12629 return (-1);
12630 }
12631 if ((itemType != baseItemType) &&
12632 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema, itemType,
12633 baseItemType, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012634 xmlChar *strBIT = NULL, *strBT = NULL;
12635 xmlSchemaPCustomErrExt(ctxt,
12636 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
12637 NULL, type, NULL,
12638 "The item type %s is not validly derived from the "
12639 "item type %s of the base type %s",
12640 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1),
12641 xmlSchemaFormatItemForReport(&strBIT, NULL, baseItemType, NULL, 1),
12642 xmlSchemaFormatItemForReport(&strBT, NULL, type->baseType, NULL, 1));
12643
12644 FREE_AND_NULL(str)
12645 FREE_AND_NULL(strBIT)
12646 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012647 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
12648 }
12649 }
12650
12651 if (type->facets != NULL) {
12652 xmlSchemaFacetPtr facet;
12653 int ok = 1;
12654 /*
12655 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
12656 * and enumeration facet components are allowed among the {facets}.
12657 */
12658 facet = type->facets;
12659 do {
12660 switch (facet->type) {
12661 case XML_SCHEMA_FACET_LENGTH:
12662 case XML_SCHEMA_FACET_MINLENGTH:
12663 case XML_SCHEMA_FACET_MAXLENGTH:
12664 case XML_SCHEMA_FACET_WHITESPACE:
12665 /*
12666 * TODO: 2.5.1.2 List datatypes
12667 * The value of ·whiteSpace· is fixed to the value collapse.
12668 */
12669 case XML_SCHEMA_FACET_PATTERN:
12670 case XML_SCHEMA_FACET_ENUMERATION:
12671 break;
12672 default: {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012673 xmlSchemaPIllegalFacetListUnionErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012674 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012675 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012676 /*
12677 * We could return, but it's nicer to report all
12678 * invalid facets.
12679 */
12680 ok = 0;
12681 }
12682 }
12683 facet = facet->next;
12684 } while (facet != NULL);
12685 if (ok == 0)
12686 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
12687 /*
12688 * TODO: 2.3.2.5 For each facet in the {facets} (call this DF), if there
12689 * is a facet of the same kind in the {facets} of the {base type
12690 * definition} (call this BF),then the DF's {value} must be a valid
12691 * restriction of BF's {value} as defined in [XML Schemas: Datatypes].
12692 */
12693 }
12694
12695
12696 }
12697 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
12698 /*
12699 * 3.1 The {member type definitions} must all have {variety} of
12700 * atomic or list.
12701 */
12702 xmlSchemaTypeLinkPtr member;
12703
12704 member = type->memberTypes;
12705 while (member != NULL) {
12706 if (((member->type->flags &
12707 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
12708 ((member->type->flags &
12709 XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012710 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012711 XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012712 NULL, type, NULL,
12713 "The member type %s is neither an atomic, nor a list type",
12714 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
12715 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012716 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
12717 }
12718 member = member->next;
12719 }
12720 /*
12721 * 3.3.1 If the {base type definition} is the ·simple ur-type
12722 * definition·
12723 */
12724 if (type->baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE)) {
12725 /*
12726 * 3.3.1.1 All of the {member type definitions} must have a
12727 * {final} which does not contain union.
12728 */
12729 member = type->memberTypes;
12730 while (member != NULL) {
12731 if (xmlSchemaTypeFinalContains(ctxt->schema, member->type,
12732 XML_SCHEMAS_TYPE_FINAL_UNION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012733 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012734 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012735 NULL, type, NULL,
12736 "The final of member type %s contains 'union'",
12737 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
12738 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012739 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
12740 }
12741 member = member->next;
12742 }
12743 /*
12744 * 3.3.1.2 The {facets} must be empty.
12745 */
12746 if (type->facetSet != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012747 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012748 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012749 NULL, type, NULL,
12750 "No facets allowed", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012751 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
12752 }
12753 } else {
12754 /*
12755 * 3.3.2.1 The {base type definition} must have a {variety} of union.
12756 */
12757 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012758 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012759 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012760 NULL, type, NULL,
12761 "The base type %s is not a union type",
12762 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
12763 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012764 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
12765 }
12766 /*
12767 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
12768 */
12769 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
12770 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012771 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012772 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012773 NULL, type, NULL,
12774 "The final of its base type %s must not contain 'restriction'",
12775 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
12776 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012777 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
12778 }
12779 /*
12780 * 3.3.2.3 The {member type definitions}, in order, must be validly
12781 * derived from the corresponding type definitions in the {base
12782 * type definition}'s {member type definitions} given the empty set,
12783 * as defined in Type Derivation OK (Simple) (§3.14.6).
12784 */
12785 {
12786 xmlSchemaTypeLinkPtr baseMember;
12787
12788 /*
12789 * OPTIMIZE: if the type is restricting, it has no local defined
12790 * member types and inherits the member types of the base type;
12791 * thus a check for equality can be skipped.
12792 */
12793 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000012794 * Even worse: I cannot see a scenario where a restricting
Daniel Veillard01fa6152004-06-29 17:04:39 +000012795 * union simple type can have other member types as the member
12796 * types of it's base type. This check seems not necessary with
12797 * respect to the derivation process in libxml2.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000012798 * But necessary if constructing types with an API.
Daniel Veillard01fa6152004-06-29 17:04:39 +000012799 */
12800 if (type->memberTypes != NULL) {
12801 member = type->memberTypes;
12802 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
12803 if ((member == NULL) && (baseMember != NULL)) {
12804 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012805 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012806 "Internal error: "
12807 "xmlSchemaCheckDerivationValidSimpleRestriction "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012808 "(3.3.2.3), union simple type '%s', unequal number "
Daniel Veillard01fa6152004-06-29 17:04:39 +000012809 "of member types in the base type\n",
12810 type->name, NULL);
12811 }
12812 while (member != NULL) {
12813 if (baseMember == NULL) {
12814 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012815 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012816 "Internal error: "
12817 "xmlSchemaCheckDerivationValidSimpleRestriction "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012818 "(3.3.2.3), union simple type '%s', unequal number "
12819 "of member types in the base type.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012820 type->name, NULL);
12821 }
12822 if ((member->type != baseMember->type) &&
12823 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema,
12824 member->type, baseMember->type, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012825 xmlChar *strBMT = NULL, *strBT = NULL;
12826
12827 xmlSchemaPCustomErrExt(ctxt,
12828 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
12829 NULL, type, NULL,
12830 "The member type %s is not validly derived from its "
12831 "corresponding member type %s of the base type %s",
12832 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1),
12833 xmlSchemaFormatItemForReport(&strBMT, NULL, baseMember->type, NULL, 1),
12834 xmlSchemaFormatItemForReport(&strBT, NULL, type->baseType, NULL, 1));
12835 FREE_AND_NULL(str)
12836 FREE_AND_NULL(strBMT)
12837 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012838 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
12839 }
12840 member = member->next;
12841 baseMember = baseMember->next;
12842 }
12843 }
12844 }
12845 /*
12846 * 3.3.2.4 Only pattern and enumeration facet components are
12847 * allowed among the {facets}.
12848 */
12849 if (type->facets != NULL) {
12850 xmlSchemaFacetPtr facet;
12851 int ok = 1;
12852
12853 facet = type->facets;
12854 do {
12855 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
12856 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012857 xmlSchemaPIllegalFacetListUnionErr(ctxt,
12858 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
12859 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012860 ok = 0;
12861 }
12862 facet = facet->next;
12863 } while (facet != NULL);
12864 if (ok == 0)
12865 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
12866
12867 }
12868 /*
12869 * TODO: 3.3.2.5 (facet derivation)
12870 */
12871 }
12872 }
12873
12874 return (0);
12875}
12876
12877/**
12878 * xmlSchemaCheckSRCSimpleType:
12879 * @ctxt: the schema parser context
12880 * @type: the simple type definition
12881 *
12882 * Checks crc-simple-type constraints.
12883 *
12884 * Returns 0 if the constraints are satisfied,
12885 * if not a positive error code and -1 on internal
12886 * errors.
12887 */
12888static int
12889xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
12890 xmlSchemaTypePtr type)
12891{
12892 /*
12893 * NOTE: src-simple-type 2-4 are redundant, since the checks
12894 * were are done for the corresponding <restriction>, <list> and <union>
12895 * elements, but W3C wants a <simpleType> error as well, so it gets one.
12896 * Maby this can be skipped in the future, if we get sure it's not needed.
12897 */
12898 if (type->subtypes == NULL) {
12899 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012900 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012901 "Internal error: xmlSchemaCheckSRCSimpleType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012902 "no subtype on simple type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012903 type->name, NULL);
12904 return (-1);
12905 }
12906 /*
12907 * src-simple-type.1 The corresponding simple type definition, if any,
12908 * must satisfy the conditions set out in Constraints on Simple Type
12909 * Definition Schema Components (§3.14.6).
12910 */
12911 if ((xmlSchemaCheckSTPropsCorrect(ctxt, type) != 0) ||
12912 (xmlSchemaCheckCOSSTRestricts(ctxt, type) != 0)) {
12913 /*
12914 * TODO: Removed this, since it got annoying to get an
12915 * extra error report, if anything failed until now.
12916 * Enable this if needed.
12917 */
12918 /*
12919 xmlSchemaPErr(ctxt, type->node,
12920 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012921 "Simple type '%s' does not satisfy the constraints "
Daniel Veillard01fa6152004-06-29 17:04:39 +000012922 "on simple type definitions.\n",
12923 type->name, NULL);
12924 */
12925 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_1);
12926 }
12927
12928 if (type->subtypes->type == XML_SCHEMA_TYPE_RESTRICTION) {
12929 /*
12930 * src-simple-type.2 If the <restriction> alternative is chosen,
12931 * either it must have a base [attribute] or a <simpleType> among its
12932 * [children], but not both.
12933 */
William M. Brack2f2a6632004-08-20 23:09:47 +000012934 /*
12935 * XML_SCHEMAP_SRC_SIMPLE_TYPE_2
12936 * NOTE: This was removed, since this will be already handled
12937 * in the parse function for <restriction>.
12938 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012939 } else if (type->subtypes->type == XML_SCHEMA_TYPE_LIST) {
12940 /* src-simple-type.3 If the <list> alternative is chosen, either it must have
12941 * an itemType [attribute] or a <simpleType> among its [children],
12942 * but not both.
12943 * NOTE: baseType is set to the local simple type definiton,
12944 * if existent, at parse time. This is a hack and not nice.
12945 */
William M. Brack2f2a6632004-08-20 23:09:47 +000012946 /*
12947 * TODO: Remove this, and add the check to the parse function of <list>.
12948 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012949 if (((type->subtypes->base == NULL) &&
12950 (type->baseType == NULL)) ||
12951 ((type->subtypes->base != NULL) &&
12952 (type->subtypes->baseType != NULL))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012953 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012954 XML_SCHEMAP_SRC_SIMPLE_TYPE_3,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012955 NULL, type, NULL,
12956 "Either the attribute 'itemType' or the <simpleType> child "
12957 "must be present on the <list> child ", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012958 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_3);
12959 }
12960
12961
12962 } else if (type->subtypes->type == XML_SCHEMA_TYPE_UNION) {
12963 xmlSchemaTypeLinkPtr member;
12964 xmlSchemaTypePtr ancestor, anySimpleType;
12965
12966 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
12967
12968 /* src-simple-type.4 Circular union type definition is disallowed. That is, if
12969 * the <union> alternative is chosen, there must not be any entries
12970 * in the memberTypes [attribute] at any depth which resolve to the
12971 * component corresponding to the <simpleType>.
12972 */
12973 member = type->memberTypes;
12974 while (member != NULL) {
12975 ancestor = member->type;
12976 while ((ancestor != NULL) && (ancestor->type != XML_SCHEMA_TYPE_BASIC)) {
12977 if (ancestor->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
12978 xmlSchemaTypeFixup(ancestor, ctxt, NULL);
12979 if (ancestor == anySimpleType)
12980 break;
12981 else if (ancestor == type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012982 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012983 XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012984 NULL, type, NULL,
12985 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012986 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
12987 } else if (ancestor->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
12988 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000012989 * TODO, FIXME: Although a list simple type must not have a union ST
Daniel Veillard01fa6152004-06-29 17:04:39 +000012990 * type as item type, which in turn has a list ST as member
12991 * type, we will assume this here as well, since this check
12992 * was not yet performed.
12993 */
12994
12995 }
12996 ancestor = ancestor->baseType;
12997 }
12998 member = member->next;
12999 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013000 }
13001
13002 return (0);
13003}
13004
William M. Brack2f2a6632004-08-20 23:09:47 +000013005#if 0 /* Not yet used code for CT schema validation */
13006static int
13007xmlSchemaCheckCVCSimpleType(xmlSchemaValidCtxtPtr ctxt,
13008 const xmlChar * value,
13009 xmlSchemaTypePtr type,
13010 int fireErrors)
13011{
13012 int ret;
13013 /*
13014 * 3.14.4 Simple Type Definition Validation Rules
13015 * Validation Rule: String Valid
13016 */
13017 /*
13018 * 1 It is schema-valid with respect to that definition as defined
13019 * by Datatype Valid in [XML Schemas: Datatypes].
13020 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013021 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type, value,
13022 fireErrors, 1, 1, 1);
William M. Brack2f2a6632004-08-20 23:09:47 +000013023 return (ret);
13024 /*
13025 * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
13026 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6), then
13027 * the string must be a ·declared entity name·.
13028 */
13029 /*
13030 * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
13031 * given the empty set, as defined in Type Derivation OK (Simple) (§3.14.6),
13032 * then every whitespace-delimited substring of the string must be a ·declared
13033 * entity name·.
13034 */
13035 /*
13036 * 2.3 otherwise no further condition applies.
13037 */
13038
13039 return (0);
13040}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013041#endif
13042
William M. Brack2f2a6632004-08-20 23:09:47 +000013043
13044static int
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013045xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
13046{
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000013047 if (vctxt->pctxt == NULL) {
13048 if (vctxt->schema != NULL)
13049 vctxt->pctxt = xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
13050 else
13051 vctxt->pctxt = xmlSchemaNewParserCtxt("*");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013052 if (vctxt->pctxt == NULL) {
13053 xmlSchemaVErr(vctxt, NULL,
13054 XML_SCHEMAV_INTERNAL,
13055 "Internal error: xmlSchemaCreatePCtxtOnVCtxt, "
13056 "failed to create a temp. parser context.\n",
William M. Brack2f2a6632004-08-20 23:09:47 +000013057 NULL, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013058 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013059 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013060 /* TODO: Pass user data. */
13061 xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error, vctxt->warning, NULL);
13062 }
13063 return (0);
13064}
13065
13066static int
13067xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
13068{
13069 if (ctxt->vctxt == NULL) {
13070 ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
13071 if (ctxt->vctxt == NULL) {
13072 xmlSchemaPErr(ctxt, NULL,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013073 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013074 "Internal error: xmlSchemaCreatePCtxtOnVCtxt, "
13075 "failed to create a temp. validation context.\n",
13076 NULL, NULL);
13077 return (-1);
13078 }
13079 /* TODO: Pass user data. */
13080 xmlSchemaSetValidErrors(ctxt->vctxt, ctxt->error, ctxt->warning, NULL);
13081 }
13082 return (0);
13083}
13084
13085/**
13086 * xmlSchemaCheckCOSValidDefault:
13087 * @ctxt: the schema parser context
13088 * @type: the simple type definition
13089 * @value: the default value
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000013090 * @val: the precomputed value to be returned
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013091 * @node: an optional node (the holder of the value)
13092 *
13093 * Checks the "cos-valid-default" constraints.
13094 *
13095 * Returns 0 if the constraints are satisfied,
13096 * if not, a positive error code and -1 on internal
13097 * errors.
13098 */
13099static int
13100xmlSchemaCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
13101 xmlSchemaValidCtxtPtr vctxt,
13102 xmlSchemaTypePtr type,
13103 const xmlChar *value,
13104 xmlNodePtr node)
13105{
13106 int ret = 0;
13107
13108 /*
13109 * cos-valid-default:
13110 * Schema Component Constraint: Element Default Valid (Immediate)
13111 * For a string to be a valid default with respect to a type
13112 * definition the appropriate case among the following must be true:
13113 */
13114 /*
13115 * NOTE: This has to work without a given node (the holder of the
13116 * value), since it should work on the component, i.e. an underlying
13117 * DOM must not be mandatory.
13118 */
13119 if ((pctxt == NULL) || (vctxt == NULL)) {
13120 xmlSchemaPErr(pctxt, node,
13121 XML_SCHEMAP_INTERNAL,
13122 "Internal error: xmlSchemaCheckCOSValidDefault, "
13123 "bad arguments: the parser and/or validation context is "
13124 "missing.\n",
13125 NULL, NULL);
13126 return (-1);
13127 }
13128 if IS_COMPLEX_TYPE(type) {
William M. Brack2f2a6632004-08-20 23:09:47 +000013129 /*
13130 * Complex type.
13131 *
13132 * 2.1 its {content type} must be a simple type definition or mixed.
13133 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013134 /*
13135 * TODO: Adjust this when the content type will be computed
13136 * correctly.
13137 */
13138 if ((type->contentType != XML_SCHEMA_CONTENT_SIMPLE) &&
13139 (type->contentType != XML_SCHEMA_CONTENT_BASIC) &&
13140 (type->contentType != XML_SCHEMA_CONTENT_MIXED)) {
13141 xmlSchemaPSimpleTypeErr(pctxt,
13142 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
13143 NULL, NULL, node,
13144 type, NULL, NULL,
13145 "If the type of a constraint value is complex, its content "
13146 "type must be mixed or a simple type",
13147 NULL, NULL);
13148 return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
13149 }
13150 if (type->contentType == XML_SCHEMA_CONTENT_MIXED) {
William M. Brack2f2a6632004-08-20 23:09:47 +000013151 /*
13152 * 2.2.2 If the {content type} is mixed, then the {content type}'s
13153 * particle must be ·emptiable· as defined by Particle Emptiable
13154 * (§3.9.6).
13155 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013156
William M. Brack2f2a6632004-08-20 23:09:47 +000013157 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013158 * URGENT TODO: Implement this.
William M. Brack2f2a6632004-08-20 23:09:47 +000013159 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013160 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000013161 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013162 }
13163 /*
13164 * 1 If the type definition is a simple type definition, then the string
13165 * must be ·valid· with respect to that definition as defined by String
13166 * Valid (§3.14.4).
13167 *
13168 * AND
13169 *
13170 * 2.2.1 If the {content type} is a simple type definition, then the
13171 * string must be ·valid· with respect to that simple type definition
13172 * as defined by String Valid (§3.14.4).
13173 */
13174 vctxt->node = node;
13175 vctxt->cur = NULL;
13176 ret = xmlSchemaValidateSimpleTypeValue(vctxt, type, value, 1, 1, 1, 0);
13177 /* ret = xmlSchemaCheckCVCSimpleType(vctxt, elemDecl->value, typeDef, 0); */
13178 if (ret < 0) {
13179 xmlSchemaPErr(pctxt, node,
13180 /* NOTNICE: error code: This function will be used during
13181 * schema construction and xsi:type validation.
13182 */
13183 XML_SCHEMAP_INTERNAL,
13184 "Internal error: xmlSchemaCheckCOSValidDefault, "
13185 "while validating a value constaint value.\n",
13186 NULL, NULL);
13187
13188 }
13189 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +000013190}
13191
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013192#if 0 /* Not yet used code for CT schema validation */
William M. Brack2f2a6632004-08-20 23:09:47 +000013193/**
13194 * xmlSchemaGetSTContentOfCT:
13195 * @ctxt: the schema parser context
13196 * @type: the complex type definition
13197 *
13198 *
13199 * Returns the corresponding simple type for the content of
13200 * the complex type.
13201 */
13202static xmlSchemaTypePtr
13203xmlSchemaGetSTContentOfCT(xmlSchemaParserCtxtPtr ctxt,
13204 xmlSchemaTypePtr type)
13205{
13206 xmlSchemaTypePtr orig = type, anyType;
13207
13208 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
13209 while ((type != NULL) && (type != anyType) &&
13210 (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
13211 if (type->type == XML_SCHEMA_TYPE_SIMPLE)
13212 return(type);
13213 type = type->baseType;
13214 }
13215 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013216 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000013217 NULL, orig, NULL,
13218 "Internal error: xmlSchemaGetSTContentTypeOfCT, "
13219 "no simple type for the content of complex type '%s' could be "
13220 "computed", orig->name);
13221 return (NULL);
13222}
13223
13224
William M. Brack2f2a6632004-08-20 23:09:47 +000013225
William M. Brack2f2a6632004-08-20 23:09:47 +000013226
13227/**
13228 * xmlSchemaCheckCOSCTExtends:
13229 * @ctxt: the schema parser context
13230 * @type: the complex type definition
13231 *
13232 * Schema Component Constraint: Derivation Valid (Extension)
13233 *
13234 * Returns 0 if the constraints are satisfied, a positive
13235 * error code if not and -1 if an internal error occured.
13236 */
13237static int
13238xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
13239 xmlSchemaTypePtr type)
13240{
13241 xmlSchemaTypePtr base;
13242 /*
13243 * 1 If the {base type definition} is a complex type definition,
13244 * then all of the following must be true:
13245 */
13246 base = type->baseType;
13247 if (base == NULL) {
13248 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013249 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000013250 NULL, type, NULL,
13251 "Internal error: xmlSchemaCheckCOSCTExtends, "
13252 "the complex type '%s' has no base type", type->name);
13253 return (-1);
13254 }
13255 if (base->type == XML_SCHEMA_TYPE_COMPLEX) {
13256 /*
13257 * 1.1 The {final} of the {base type definition} must not
13258 * contain extension.
13259 */
13260 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
13261 xmlSchemaPCustomErr(ctxt,
13262 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
13263 NULL, type, NULL,
13264 "The 'final' of the base type definition "
13265 "contains extension", NULL);
13266 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
13267 }
13268 /*
13269 * 1.2 Its {attribute uses} must be a subset of the {attribute uses}
13270 * of the complex type definition itself, that is, for every attribute
13271 * use in the {attribute uses} of the {base type definition}, there
13272 * must be an attribute use in the {attribute uses} of the complex
13273 * type definition itself whose {attribute declaration} has the same
13274 * {name}, {target namespace} and {type definition} as its attribute
13275 * declaration
13276 *
13277 * NOTE: This will be already satisfied by the way the attribute uses
13278 * are extended in xmlSchemaBuildAttributeValidation; thus this check
13279 * is not needed.
13280 */
13281
13282 /*
13283 * 1.3 If it has an {attribute wildcard}, the complex type definition
13284 * must also have one, and the base type definition's {attribute
13285 * wildcard}'s {namespace constraint} must be a subset of the complex
13286 * type definition's {attribute wildcard}'s {namespace constraint},
13287 * as defined by Wildcard Subset (§3.10.6).
13288 *
13289 * This is already checked in xmlSchemaBuildAttributeValidation; thus
13290 * this check is not needed.
13291 */
13292
13293 /*
13294 * 1.4 One of the following must be true:
13295 *
13296 * 1.4.1 The {content type} of the {base type definition} and the
13297 * {content type} of the complex type definition itself must be the same
13298 * simple type definition
13299 */
13300
13301
13302
13303 } else {
13304 /*
13305 * 2 If the {base type definition} is a simple type definition,
13306 * then all of the following must be true:
13307 */
13308 /*
13309 * 2.1 The {content type} must be the same simple type definition.
13310 */
13311 /*
13312 * 2.2 The {final} of the {base type definition} must not contain
13313 * extension
13314 */
13315 }
13316
13317}
13318
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013319static int
13320xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
13321 xmlSchemaTypePtr type)
13322{
13323 xmlSchemaTypePtr base, content;
13324 int OK = 0;
13325
13326 /*
13327 * TODO: Adjust the error codes here, as I used
13328 * XML_SCHEMAP_SRC_CT_1 only yet.
13329 */
13330 /*
13331 * Schema Representation Constraint:
13332 * Complex Type Definition Representation OK
13333 */
13334 base = type->baseType;
13335 if (base == NULL) {
13336 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL, NULL, type, NULL,
13337 "Internal error: xmlSchemaCheckSRCCT, '%s', no base type",
13338 type->name);
13339 return (-1);
13340 }
13341
13342 if (type->subtypes != NULL) {
13343 if (type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
13344 if IS_COMPLEX_TYPE(base) {
13345 /*
13346 * 1 If the <complexContent> alternative is chosen, the type definition
13347 * ·resolved· to by the ·actual value· of the base [attribute]
13348 * must be a complex type definition;
13349 */
13350 xmlSchemaPCustomErr(ctxt,
13351 XML_SCHEMAP_SRC_CT_1,
13352 NULL, type, NULL,
13353 "The base type is not a complex type", NULL);
13354 return (XML_SCHEMAP_SRC_CT_1);
13355 }
13356 } else if (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
13357
13358 if IS_SIMPLE_TYPE(base) {
13359 if (type->flags &
13360 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
13361 /*
13362 * 2.1.3 only if the <extension> alternative is also
13363 * chosen, a simple type definition.
13364 */
13365 /* TODO: Change error code to ..._SRC_CT_2_1_3. */
13366 xmlSchemaPCustomErr(ctxt,
13367 XML_SCHEMAP_SRC_CT_1,
13368 NULL, type, NULL,
13369 "A complex type (simple content) cannot restrict "
13370 "an other simple type",
13371 NULL);
13372 return (XML_SCHEMAP_SRC_CT_1);
13373 }
13374 OK = 1;
13375
13376 } else { /* if IS_SIMPLE_TYPE(base) */
Daniel Veillardbc69d4f2005-03-17 10:04:46 +000013377 if (base->contentType == XML_SCHEMA_CONTENT_MIXED) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013378 /*
13379 * 2.1.2 only if the <restriction> alternative is also
13380 * chosen, a complex type definition whose {content type}
13381 * is mixed and a particle emptyable.
13382 */
13383 /*
13384 * FIXME TODO: Check for *empiable particle* is missing.
13385 */
13386 if ((type->flags &
13387 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) == 0) {
13388 xmlSchemaPCustomErr(ctxt,
13389 XML_SCHEMAP_SRC_CT_1,
13390 NULL, type, NULL,
13391 "A complex type (simple content) cannot "
13392 "extend an other complex type which has a "
13393 "content type of: 'mixed' and emptiable particle",
13394 NULL);
13395 return (XML_SCHEMAP_SRC_CT_1);
13396 }
13397 /*
13398 * NOTE: This will be fired as well, if the base type
13399 * is *'anyType'*.
13400 * NOTE: type->subtypes->subtypes will be the
13401 * <restriction> item.
13402 */
13403 if (type->subtypes->subtypes == NULL) {
13404 /* Yes, this is paranoid programming. */
13405 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
13406 NULL, type, NULL,
13407 "Internal error: xmlSchemaCheckSRCCT, "
13408 "'%s', <simpleContent> has no <restriction>",
13409 type->name);
13410 return (-1);
13411 }
13412 /*
13413 * 2.2 If clause 2.1.2 above is satisfied, then there
13414 * must be a <simpleType> among the [children] of
13415 * <restriction>.
13416 */
13417 if (type->subtypes->subtypes->type !=
13418 XML_SCHEMA_TYPE_SIMPLE) {
13419 /* TODO: Change error code to ..._SRC_CT_2_2. */
13420 xmlSchemaPCustomErr(ctxt,
13421 XML_SCHEMAP_SRC_CT_1,
13422 NULL, type, NULL,
13423 "A <simpleType> is expected among the children "
13424 "of <restriction>", NULL);
13425 return (XML_SCHEMAP_SRC_CT_1);
13426 }
13427 OK = 1;
Daniel Veillardbc69d4f2005-03-17 10:04:46 +000013428 } else { /* if (base->contentType == XML_SCHEMA_CONTENT_MIXED)*/
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013429 /*
13430 * 2.1.1 a complex type definition whose {content type} is a
13431 * simple type definition;
13432 */
13433 if (base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) {
13434 xmlSchemaPCustomErr(ctxt,
13435 XML_SCHEMAP_SRC_CT_1,
13436 NULL, type, NULL,
13437 "A complex type (simple content) cannot "
13438 "be derived from the complex type '%s'",
13439 base->name);
13440 return (XML_SCHEMAP_SRC_CT_1);
13441 }
13442 content = base->contentTypeDef;
13443 if (content == NULL) {
13444 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
13445 NULL, type, NULL,
13446 "Internal error: xmlSchemaCheckSRCCT, "
13447 "'%s', base type has no content type",
13448 type->name);
13449 return (-1);
13450 }
13451 if (content->type != XML_SCHEMA_TYPE_SIMPLE) {
13452 xmlSchemaPCustomErr(ctxt,
13453 XML_SCHEMAP_SRC_CT_1,
13454 NULL, type, NULL,
13455 "A complex type (simple content) cannot "
13456 "be derived from the complex type '%s'",
13457 base->name);
13458 return (XML_SCHEMAP_SRC_CT_1);
13459 }
13460 }
13461 }
13462 }
13463 }
13464 /*
13465 * TODO: 3 The corresponding complex type definition component must
13466 * satisfy the conditions set out in Constraints on Complex Type
13467 * Definition Schema Components (§3.4.6);
13468 *
13469 * TODO: 4 If clause 2.2.1 or clause 2.2.2 in the correspondence specification
13470 * above for {attribute wildcard} is satisfied, the intensional
13471 * intersection must be expressible, as defined in Attribute Wildcard
13472 * Intersection (§3.10.6).
13473 */
13474
13475}
William M. Brack2f2a6632004-08-20 23:09:47 +000013476#endif
13477
Daniel Veillard01fa6152004-06-29 17:04:39 +000013478/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013479 * xmlSchemaGroupDefFixup:
13480 * @typeDecl: the schema model group definition
13481 * @ctxt: the schema parser context
13482 *
13483 * Fixes model group definitions.
13484 */
13485static void
13486xmlSchemaGroupDefFixup(xmlSchemaTypePtr group,
13487 xmlSchemaParserCtxtPtr ctxt,
13488 const xmlChar * name ATTRIBUTE_UNUSED)
13489{
13490 group->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
13491 if ((group->ref != NULL) && (group->subtypes == NULL)) {
13492 xmlSchemaTypePtr groupDef;
13493 /*
13494 * Resolve the reference.
13495 */
13496 groupDef = xmlSchemaGetGroup(ctxt->schema, group->ref,
13497 group->refNs);
13498 if (groupDef == NULL) {
13499 xmlSchemaPResCompAttrErr(ctxt,
13500 XML_SCHEMAP_SRC_RESOLVE,
13501 NULL, group, NULL,
13502 "ref", group->ref, group->refNs,
13503 XML_SCHEMA_TYPE_GROUP, NULL);
13504 return;
13505 }
13506 group->subtypes = groupDef;
13507 }
13508}
13509
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013510#if 0 /* Enable when the content type will be computed. */
13511static int
13512xmlSchemaComputeContentType(xmlSchemaParserCtxtPtr ctxt,
13513 xmlSchemaTypePtr type)
13514{
13515 xmlSchemaTypePtr base, res = NULL;
13516
13517 base = type->baseType;
13518 if (base == NULL) {
13519 xmlSchemaPCustomErr(ctxt,
13520 XML_SCHEMAP_INTERNAL,
13521 NULL, type, NULL,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000013522 "Internal error: xmlSchemaComputeContentType, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013523 "the complex type '%s' has no base type", type->name);
13524 return (-1);
13525 }
13526 if (IS_ANYTYPE(base) || (type->subtypes->type ==
13527 XML_SCHEMA_TYPE_COMPLEX_CONTENT)) {
13528 xmlSchemaTypePtr start;
13529 /*
13530 * Effective 'mixed'.
13531 */
13532 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
13533 type->contentType = XML_SCHEMA_CONTENT_MIXED;
13534 /*
13535 * Effective content.
13536 */
13537 if (IS_ANYTYPE(base))
13538 start = type;
13539 else
13540 start = type->subtypes;
13541
13542 } else { /* if XML_SCHEMA_TYPE_COMPLEX_CONTENT */
13543 xmlSchemaTypePtr baseContentItem;
13544
13545 /*
13546 * Complex type with simple content.
13547 */
13548 if IS_COMPLEX_TYPE(base) {
13549 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
13550 /*
13551 * Summary: a complex type (simple content) can *restrict*
13552 * a complex type with the following content type:
13553 * 1. 'mixed' and an emptiable particle
13554 * 2. simple type
13555 */
13556 if (base->contentType == XML_SCHEMA_CONTENT_MIXED) {
13557 /*
13558 * 2 if the {content type} of the base type is mixed and a
13559 * particle which is ·emptiable·,
13560 * [...]
13561 * then starting from the simple type definition
13562 * corresponding to the <simpleType> among the [children]
13563 * of <restriction> (**which must be present**)
13564 *
13565 * FIXME TODO: Handle "emptiable particle".
13566 */
13567 res = type->subtypes->subtypes;
13568 if (res == NULL) {
13569 xmlSchemaPCustomErr(ctxt,
13570 XML_SCHEMAP_INTERNAL,
13571 NULL, type, NULL,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000013572 "Internal error: xmlSchemaComputeContentType, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013573 "CT '%s' (restricting): <simpleContent> has no "
13574 "<restriction>",
13575 type->name);
13576 return (-1);
13577 }
13578
13579 res->subtypes;
13580 if (res == NULL) {
13581 xmlSchemaPCustomErr(ctxt,
13582 XML_SCHEMAP_INTERNAL,
13583 NULL, type, NULL,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000013584 "Internal error: xmlSchemaComputeContentType, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013585 "CT '%s' (restricting): <restriction> has no "
13586 "mandatory <simpleType>",
13587 type->name);
13588 return (-1);
13589 }
13590 } else {
13591 baseContentItem = base->contentTypeDef;
13592 if (baseContentItem == NULL) {
13593 xmlSchemaPCustomErr(ctxt,
13594 XML_SCHEMAP_INTERNAL,
13595 NULL, type, NULL,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000013596 "Internal error: xmlSchemaComputeContentType, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013597 "CT '%s' (restricting), the base type has no "
13598 "content type", type->name);
13599 return (-1);
13600 }
13601 if IS_SIMPLE_TYPE(baseContentItem) {
13602 /*
13603 * 1 If the base type is a complex type whose own
13604 * {content type} is a simple type and the <restriction>
13605 * alternative is chosen
13606 */
13607 /* type->subtypes->subtypes will be the restriction item.*/
13608 res = type->subtypes->subtypes;
13609 if (res == NULL) {
13610 xmlSchemaPCustomErr(ctxt,
13611 XML_SCHEMAP_INTERNAL,
13612 NULL, type, NULL,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000013613 "Internal error: xmlSchemaComputeContentType, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013614 "CT '%s' (restricting): <simpleType> has no "
13615 "<restriction>", type->name);
13616 return (-1);
13617 }
13618 /*
13619 * 1.1 the simple type definition corresponding to the
13620 * <simpleType> among the [children] of <restriction>if
13621 * there is one;
13622 */
13623 res = res->subtypes;
13624 if (res == NULL) {
13625 /*
13626 * 1.2 otherwise the {content type}
13627 * of the base type .
13628 */
13629 res = baseContentItem;
13630 }
13631 }
13632 }
13633 /*
13634 * SPECIAL TODO: If *restricting* the spec wants us to
13635 * create an *additional* simple type which restricts the
13636 * located simple type; we won't do this yet, and look how
13637 * far we get with it.
13638 */
13639 } else { /* if XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION */
13640 /*
13641 * Summary: a complex type (simple content) can *extend*
13642 * only a complex base with a simple type as content.
13643 */
13644 /*
13645 * 3 If the type definition ·resolved· to by the ·actual
13646 * value· of the base [attribute] is a complex type
13647 * definition (whose own {content type} *must be* a simple
13648 * type definition, see below) and the *<extension>*
13649 * alternative is chosen, then the {content type} of that
13650 * complex type definition;
13651 */
13652 res = base->contentTypeDef;
13653 if (res == NULL) {
13654 xmlSchemaPCustomErr(ctxt,
13655 XML_SCHEMAP_INTERNAL,
13656 NULL, type, NULL,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000013657 "Internal error: xmlSchemaComputeContentType, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013658 "CT '%s' (extending), the base type has no content "
13659 "type", type->name);
13660 return (-1);
13661 }
13662 if (! IS_SIMPLE_TYPE(res)) {
13663 xmlSchemaPCustomErr(ctxt,
13664 XML_SCHEMAP_INTERNAL,
13665 NULL, type, NULL,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000013666 "Internal error: xmlSchemaComputeContentType, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013667 "CT '%s' (extending), the content type of the "
13668 "base is not a simple type", type->name);
13669 return (-1);
13670 }
13671 }
13672 } else /* if IS_COMPLEX_TYPE(base) */
13673 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
13674 /*
13675 * 4 otherwise (the type definition ·resolved· to by the
13676 * ·actual value· of the base [attribute] is a simple type
13677 * definition and the <extension> alternative is chosen),
13678 * then that simple type definition.
13679 */
13680 res = base;
13681 }
13682 type->contentTypeDef = res;
13683 if (res == NULL) {
13684 xmlSchemaPCustomErr(ctxt,
13685 XML_SCHEMAP_INTERNAL,
13686 NULL, type, NULL,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000013687 "Internal error: xmlSchemaComputeContentType, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013688 "'%s', the content type could not be determined",
13689 type->name);
13690 return (-1);
13691 }
13692
13693 }
13694
13695}
13696#endif
13697
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013698/**
Daniel Veillard4255d502002-04-16 15:50:10 +000013699 * xmlSchemaTypeFixup:
13700 * @typeDecl: the schema type definition
13701 * @ctxt: the schema parser context
13702 *
13703 * Fixes the content model of the type.
13704 */
13705static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013706xmlSchemaTypeFixup(xmlSchemaTypePtr item,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013707 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000013708{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013709 xmlSchemaTypePtr ctxtType;
13710
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013711 if (item == NULL)
Daniel Veillard82bbbd42003-05-11 20:16:09 +000013712 return;
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013713 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000013714 * Do not fixup built-in types.
13715 */
13716 if (item->type == XML_SCHEMA_TYPE_BASIC)
13717 return;
13718 /*
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013719 * Do not allow the following types to be typefixed, prior to
13720 * the corresponding simple/complex types.
13721 */
13722 if (ctxt->ctxtType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013723 switch (item->type) {
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013724 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
13725 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
13726 case XML_SCHEMA_TYPE_UNION:
13727 case XML_SCHEMA_TYPE_RESTRICTION:
13728 case XML_SCHEMA_TYPE_EXTENSION:
13729 return;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013730 default:
13731 break;
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013732 }
13733 }
Daniel Veillard4255d502002-04-16 15:50:10 +000013734 if (name == NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013735 name = item->name;
13736 if (item->contentType == XML_SCHEMA_CONTENT_UNKNOWN) {
13737 switch (item->type) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013738 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013739 if (item->subtypes != NULL) {
13740 if (item->subtypes->contentType ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013741 XML_SCHEMA_CONTENT_UNKNOWN) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013742 xmlSchemaTypeFixup(item->subtypes, ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013743 NULL);
13744 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013745 item->contentType =
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013746 XML_SCHEMA_CONTENT_SIMPLE;
13747 /* item->subtypes->contentType; */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013748 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013749 break;
13750 }
13751 case XML_SCHEMA_TYPE_RESTRICTION:{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013752 xmlSchemaTypePtr base = NULL;
13753
13754 ctxt->ctxtType->flags |=
13755 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013756 if (item->baseType != NULL)
13757 base = item->baseType;
13758 else if (item->base != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013759 base =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013760 xmlSchemaGetType(ctxt->schema, item->base,
13761 item->baseNs);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013762 if (base == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013763 xmlSchemaPResCompAttrErr(ctxt,
13764 XML_SCHEMAP_SRC_RESOLVE,
William M. Brack2f2a6632004-08-20 23:09:47 +000013765 NULL, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013766 (xmlNodePtr) xmlSchemaGetPropNode(item->node, "base"),
13767 "base", item->base, item->baseNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013768 XML_SCHEMA_TYPE_BASIC, "type definition");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013769 } else if (base->contentType ==
Daniel Veillard3646d642004-06-02 19:19:14 +000013770 XML_SCHEMA_CONTENT_UNKNOWN) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013771 xmlSchemaTypeFixup(base, ctxt, NULL);
13772 }
William M. Brack2f2a6632004-08-20 23:09:47 +000013773 }
13774 ctxt->ctxtType->baseType = base;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013775 if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX) {
13776 /*
13777 * ComplexType restriction.
William M. Brack2f2a6632004-08-20 23:09:47 +000013778 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013779 /*
13780 * Content type.
13781 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013782 if (item->subtypes == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013783 /* 1.1.1 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013784 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
13785 else if ((item->subtypes->subtypes == NULL) &&
13786 ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013787 XML_SCHEMA_TYPE_ALL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013788 || (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013789 XML_SCHEMA_TYPE_SEQUENCE)))
13790 /* 1.1.2 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013791 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
13792 else if ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013793 XML_SCHEMA_TYPE_CHOICE)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013794 && (item->subtypes->subtypes == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +000013795 /* 1.1.3 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013796 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013797 else {
13798 /* 1.2 and 2.X are applied at the other layer */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013799 item->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000013800 XML_SCHEMA_CONTENT_ELEMENTS;
13801 }
13802 } else {
13803 /*
13804 * SimpleType restriction.
13805 */
William M. Brack2f2a6632004-08-20 23:09:47 +000013806 /* TODO: Nothing? */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013807 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013808 break;
13809 }
13810 case XML_SCHEMA_TYPE_EXTENSION:{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013811 xmlSchemaTypePtr base = NULL;
13812 xmlSchemaContentType explicitContentType;
13813
13814 /*
13815 * An extension does exist on a complexType only.
13816 */
13817 ctxt->ctxtType->flags |=
13818 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013819 if (item->recurse) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013820 /* TODO: The word "recursive" should be changed to "circular" here. */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013821 xmlSchemaPCustomErr(ctxt,
13822 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013823 NULL, item, item->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013824 "This item is circular", NULL);
Daniel Veillard2582a332004-04-18 19:49:46 +000013825 return;
13826 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013827 if (item->base != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013828 base =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013829 xmlSchemaGetType(ctxt->schema, item->base,
13830 item->baseNs);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013831 if (base == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013832 xmlSchemaPResCompAttrErr(ctxt,
13833 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013834 NULL, item, item->node,
13835 "base", item->base, item->baseNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013836 XML_SCHEMA_TYPE_BASIC, "type definition");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013837 } else if (base->contentType ==
13838 XML_SCHEMA_CONTENT_UNKNOWN) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013839 item->recurse = 1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013840 xmlSchemaTypeFixup(base, ctxt, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013841 item->recurse = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013842 }
13843 /*
13844 * The type definition ·resolved· to by the ·actual
13845 * value· of the base [attribute]
13846 */
13847 ctxt->ctxtType->baseType = base;
13848 /*
13849 * TODO: This one is still needed for computation of
13850 * the content model by xmlSchemaBuildAContentModel.
13851 * Try to get rid of it.
13852 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013853 item->baseType = base;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013854 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013855 if ((item->subtypes != NULL) &&
13856 (item->subtypes->contentType == XML_SCHEMA_CONTENT_UNKNOWN))
13857 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013858
13859 explicitContentType = XML_SCHEMA_CONTENT_ELEMENTS;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013860 if (item->subtypes == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013861 /* 1.1.1 */
13862 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013863 else if ((item->subtypes->subtypes == NULL) &&
13864 ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013865 XML_SCHEMA_TYPE_ALL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013866 || (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013867 XML_SCHEMA_TYPE_SEQUENCE)))
13868 /* 1.1.2 */
13869 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013870 else if ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013871 XML_SCHEMA_TYPE_CHOICE)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013872 && (item->subtypes->subtypes == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +000013873 /* 1.1.3 */
13874 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
13875 if (base != NULL) {
13876 /* It will be reported later, if the base is missing. */
13877 if (explicitContentType == XML_SCHEMA_CONTENT_EMPTY) {
13878 /* 2.1 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013879 item->contentType = base->contentType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013880 } else if (base->contentType ==
13881 XML_SCHEMA_CONTENT_EMPTY) {
13882 /* 2.2 imbitable ! */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013883 item->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000013884 XML_SCHEMA_CONTENT_ELEMENTS;
13885 } else {
13886 /* 2.3 imbitable pareil ! */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013887 item->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000013888 XML_SCHEMA_CONTENT_ELEMENTS;
13889 }
13890 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013891 break;
13892 }
13893 case XML_SCHEMA_TYPE_COMPLEX:{
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013894 ctxtType = ctxt->ctxtType;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013895 ctxt->ctxtType = item;
13896 /*
13897 * Start with an empty content-type type.
13898 */
13899 if (item->subtypes == NULL)
13900 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
13901
13902 if ((item->subtypes == NULL) ||
13903 ((item->subtypes->type !=
Daniel Veillard01fa6152004-06-29 17:04:39 +000013904 XML_SCHEMA_TYPE_SIMPLE_CONTENT) &&
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013905 (item->subtypes->type !=
Daniel Veillard01fa6152004-06-29 17:04:39 +000013906 XML_SCHEMA_TYPE_COMPLEX_CONTENT))) {
13907 /*
13908 * This case is understood as shorthand for complex
13909 * content restricting the ur-type definition, and
13910 * the details of the mappings should be modified as
13911 * necessary.
13912 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013913 item->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
13914 item->flags |=
Daniel Veillard01fa6152004-06-29 17:04:39 +000013915 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013916 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013917 * Assume that we inherit the content-type type
13918 * from 'anyType', which is 'mixed' and a particle
13919 * emptiable.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013920 */
13921 item->contentType = item->baseType->contentType;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013922 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013923 /*
13924 * Fixup the sub components.
13925 */
13926 if ((item->subtypes != NULL) &&
13927 (item->subtypes->contentType ==
13928 XML_SCHEMA_CONTENT_UNKNOWN)) {
13929 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013930 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013931 if (item->flags & XML_SCHEMAS_TYPE_MIXED) {
13932 item->contentType = XML_SCHEMA_CONTENT_MIXED;
13933 } else if (item->subtypes != NULL) {
13934 /*
13935 * Use the content-type type of the model groups
13936 * defined, if 'mixed' is not set. If 'mixed' is set
13937 * it will expand the content-type by allowing character
13938 * content to appear.
13939 */
13940 item->contentType =
13941 item->subtypes->contentType;
13942 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013943
13944 /*
13945 * Some optimization for validation:
13946 * If there are no facets beside the "whitespace" facet,
13947 * then a value needs not to checked against against a
13948 * facet, thus no computed value is needed.
13949 * TODO URGENT: This is just a workaround, we need to
13950 * introduce the correct usage of contentType to store the
13951 * facets in!
13952 */
Daniel Veillardd3210bc2005-01-28 17:56:39 +000013953 if ((item->baseType != NULL) &&
13954 (item->baseType->flags &
13955 XML_SCHEMAS_TYPE_FACETSNEEDVALUE))
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013956 item->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
13957 else {
13958 xmlSchemaFacetLinkPtr cur;
13959
13960 for (cur = item->facetSet; cur != NULL;
13961 cur = cur->next) {
13962 if (cur->facet->type != XML_SCHEMA_FACET_WHITESPACE) {
13963 item->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
13964 break;
13965 }
13966 }
13967 }
13968
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013969 xmlSchemaBuildAttributeValidation(ctxt, item);
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000013970 xmlSchemaCheckDefaults(item, ctxt, item->name);
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013971 ctxt->ctxtType = ctxtType;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013972 break;
13973 }
13974 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013975 if (item->subtypes == NULL) {
13976 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
13977 if (item->flags & XML_SCHEMAS_TYPE_MIXED)
13978 item->contentType =
Daniel Veillard1aefc862004-03-04 11:40:48 +000013979 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013980 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013981 if (item->flags & XML_SCHEMAS_TYPE_MIXED) {
13982 item->contentType =
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013983 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillard3646d642004-06-02 19:19:14 +000013984 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013985 xmlSchemaTypeFixup(item->subtypes, ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013986 NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013987 if (item->subtypes != NULL)
13988 item->contentType =
13989 item->subtypes->contentType;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013990 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013991 /*
13992 * Removed due to implementation of the build of attribute uses.
13993 */
13994 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013995 if (item->attributes == NULL)
13996 item->attributes =
13997 item->subtypes->attributes;
Daniel Veillard3646d642004-06-02 19:19:14 +000013998 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013999 }
14000 break;
14001 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014002 case XML_SCHEMA_TYPE_SIMPLE:
14003 /*
14004 * Simple Type Definition Schema Component
14005 *
14006 */
Daniel Veillard4e5d6652004-06-29 21:01:12 +000014007 ctxtType = ctxt->ctxtType;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014008 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
14009 if (item->subtypes->contentType ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000014010 XML_SCHEMA_CONTENT_UNKNOWN) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014011 ctxt->ctxtType = item;
14012 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014013 }
14014 /* Fixup base type */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014015 if ((item->baseType != NULL) &&
14016 (item->baseType->contentType ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000014017 XML_SCHEMA_CONTENT_UNKNOWN)) {
14018 /* OPTIMIZE: Actually this one will never by hit, since
14019 * the base type is already type-fixed in <restriction>.
14020 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014021 ctxt->ctxtType = item;
14022 xmlSchemaTypeFixup(item->baseType, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014023 }
14024 /* Base type:
14025 * 2 If the <list> or <union> alternative is chosen,
14026 * then the ·simple ur-type definition·.
14027 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014028 if (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000014029 XML_SCHEMA_TYPE_LIST) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014030 item->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
14031 item->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
14032 } else if (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000014033 XML_SCHEMA_TYPE_UNION) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014034 item->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
14035 item->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
14036 } else if (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000014037 XML_SCHEMA_TYPE_RESTRICTION) {
14038 xmlSchemaFacetLinkPtr facet, cur, last = NULL;
14039
14040 /*
14041 * Variety
14042 * If the <restriction> alternative is chosen, then the
14043 * {variety} of the {base type definition}.
14044 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014045 if (item->baseType != NULL) {
14046 if (item->baseType->flags &
Daniel Veillard01fa6152004-06-29 17:04:39 +000014047 XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014048 item->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
14049 else if (item->baseType->flags &
Daniel Veillard01fa6152004-06-29 17:04:39 +000014050 XML_SCHEMAS_TYPE_VARIETY_LIST)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014051 item->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
14052 else if (item->baseType->flags &
Daniel Veillard01fa6152004-06-29 17:04:39 +000014053 XML_SCHEMAS_TYPE_VARIETY_UNION)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014054 item->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014055 /*
14056 * Schema Component Constraint: Simple Type Restriction
14057 * (Facets)
14058 * NOTE: Satisfaction of 1 and 2 arise from the fixup
14059 * applied beforehand.
14060 *
14061 * 3 The {facets} of R are the union of S and the {facets}
14062 * of B, eliminating duplicates. To eliminate duplicates,
14063 * when a facet of the same kind occurs in both S and the
14064 * {facets} of B, the one in the {facets} of B is not
14065 * included, with the exception of enumeration and pattern
14066 * facets, for which multiple occurrences with distinct values
14067 * are allowed.
14068 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014069 if (item->baseType->facetSet != NULL) {
14070 last = item->facetSet;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014071 if (last != NULL)
14072 while (last->next != NULL)
14073 last = last->next;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000014074 cur = item->baseType->facetSet;
14075 for (; cur != NULL; cur = cur->next) {
14076 /*
14077 * Base patterns won't be add here:
14078 * they are ORed in a type and
14079 * ANDed in derived types. This will
14080 * happed at validation level by
14081 * walking the base axis of the type.
14082 */
14083 if (cur->facet->type ==
14084 XML_SCHEMA_FACET_PATTERN)
14085 continue;
14086 facet = NULL;
14087 if ((item->facetSet != NULL) &&
14088 /* REMOVED: a check for
14089 * XML_SCHEMA_FACET_PATTERN was already
14090 * performed above.
14091
14092 * (cur->facet->type !=
14093 * XML_SCHEMA_FACET_PATTERN) &&
Daniel Veillard01fa6152004-06-29 17:04:39 +000014094 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000014095 (cur->facet->type !=
14096 XML_SCHEMA_FACET_ENUMERATION)) {
14097 facet = item->facetSet;
14098 do {
14099 if (cur->facet->type ==
14100 facet->facet->type)
14101 break;
14102 facet = facet->next;
14103 } while (facet != NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014104 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000014105 if (facet == NULL) {
14106 facet = (xmlSchemaFacetLinkPtr)
14107 xmlMalloc(sizeof(xmlSchemaFacetLink));
14108 if (facet == NULL) {
14109 xmlSchemaPErrMemory(ctxt,
14110 "fixing simpleType", NULL);
14111 return;
14112 }
14113 /*
14114 * The facets are not copied but referenced
14115 * via the facet link.
14116 */
14117 facet->facet = cur->facet;
14118 facet->next = NULL;
14119 if (last == NULL)
14120 item->facetSet = facet;
14121 else
14122 last->next = facet;
14123 last = facet;
14124 }
14125 }
14126 }
14127 /*
14128 * Some optimization for validation:
14129 * If there are no facets beside the "whitespace" facet,
14130 * then a value needs not to checked against against a
14131 * facet, thus no computed value is needed.
14132 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000014133 if (item->baseType->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000014134 item->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
14135 else {
14136 for (cur = item->facetSet; cur != NULL;
14137 cur = cur->next) {
14138 if (cur->facet->type != XML_SCHEMA_FACET_WHITESPACE) {
14139 item->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
14140 break;
14141 }
14142 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014143 }
14144 }
14145 }
14146 /*
14147 * Check constraints.
14148 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014149 xmlSchemaCheckSRCSimpleType(ctxt, item);
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000014150 xmlSchemaCheckDefaults(item, ctxt, item->name);
Daniel Veillard4e5d6652004-06-29 21:01:12 +000014151 ctxt->ctxtType = ctxtType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014152 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014153 case XML_SCHEMA_TYPE_SEQUENCE:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014154 case XML_SCHEMA_TYPE_ALL:
14155 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014156 item->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014157 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014158 case XML_SCHEMA_TYPE_GROUP:
14159 /*
14160 * TODO: Handling was moved to xmlSchemaGroupDefFixup.
14161 */
14162 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014163 case XML_SCHEMA_TYPE_LIST:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014164 xmlSchemaParseListRefFixup(item, ctxt);
14165 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014166 break;
14167 case XML_SCHEMA_TYPE_UNION:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014168 xmlSchemaParseUnionRefCheck(item, ctxt);
14169 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014170 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014171 case XML_SCHEMA_TYPE_BASIC:
14172 case XML_SCHEMA_TYPE_ANY:
14173 case XML_SCHEMA_TYPE_FACET:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014174 case XML_SCHEMA_TYPE_UR:
14175 case XML_SCHEMA_TYPE_ELEMENT:
14176 case XML_SCHEMA_TYPE_ATTRIBUTE:
14177 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
William M. Brack29aa7722004-05-12 00:27:56 +000014178 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014179 case XML_SCHEMA_TYPE_NOTATION:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014180 case XML_SCHEMA_FACET_MININCLUSIVE:
14181 case XML_SCHEMA_FACET_MINEXCLUSIVE:
14182 case XML_SCHEMA_FACET_MAXINCLUSIVE:
14183 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
14184 case XML_SCHEMA_FACET_TOTALDIGITS:
14185 case XML_SCHEMA_FACET_FRACTIONDIGITS:
14186 case XML_SCHEMA_FACET_PATTERN:
14187 case XML_SCHEMA_FACET_ENUMERATION:
14188 case XML_SCHEMA_FACET_WHITESPACE:
14189 case XML_SCHEMA_FACET_LENGTH:
14190 case XML_SCHEMA_FACET_MAXLENGTH:
14191 case XML_SCHEMA_FACET_MINLENGTH:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014192 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
14193 if (item->subtypes != NULL)
14194 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014195 break;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000014196 case XML_SCHEMA_TYPE_IDC_UNIQUE:
14197 case XML_SCHEMA_TYPE_IDC_KEY:
14198 case XML_SCHEMA_TYPE_IDC_KEYREF:
14199 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014200 }
14201 }
Daniel Veillard8651f532002-04-17 09:06:27 +000014202#ifdef DEBUG_TYPE
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014203 if (item->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014204 xmlGenericError(xmlGenericErrorContext,
14205 "Type of %s : %s:%d :", name,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014206 item->node->doc->URL,
14207 xmlGetLineNo(item->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +000014208 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014209 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000014210 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014211 switch (item->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014212 case XML_SCHEMA_CONTENT_SIMPLE:
14213 xmlGenericError(xmlGenericErrorContext, "simple\n");
14214 break;
14215 case XML_SCHEMA_CONTENT_ELEMENTS:
14216 xmlGenericError(xmlGenericErrorContext, "elements\n");
14217 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000014218 case XML_SCHEMA_CONTENT_UNKNOWN:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014219 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
14220 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000014221 case XML_SCHEMA_CONTENT_EMPTY:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014222 xmlGenericError(xmlGenericErrorContext, "empty\n");
14223 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000014224 case XML_SCHEMA_CONTENT_MIXED:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014225 xmlGenericError(xmlGenericErrorContext, "mixed\n");
14226 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014227 /* Removed, since not used. */
14228 /*
Daniel Veillard8651f532002-04-17 09:06:27 +000014229 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014230 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
14231 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014232 */
Daniel Veillard8651f532002-04-17 09:06:27 +000014233 case XML_SCHEMA_CONTENT_BASIC:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014234 xmlGenericError(xmlGenericErrorContext, "basic\n");
14235 break;
14236 default:
14237 xmlGenericError(xmlGenericErrorContext,
14238 "not registered !!!\n");
14239 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000014240 }
14241#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000014242}
14243
14244/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000014245 * xmlSchemaCheckFacet:
14246 * @facet: the facet
14247 * @typeDecl: the schema type definition
14248 * @ctxt: the schema parser context or NULL
14249 * @name: name of the type
14250 *
14251 * Checks the default values types, especially for facets
14252 *
14253 * Returns 0 if okay or -1 in cae of error
14254 */
14255int
14256xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014257 xmlSchemaTypePtr typeDecl,
14258 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000014259{
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +000014260 xmlSchemaTypePtr nonNegativeIntegerType = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014261 int ret = 0, reuseValCtxt = 0;
14262
Daniel Veillardce682bc2004-11-05 17:22:25 +000014263 if ((facet == NULL) || (typeDecl == NULL))
14264 return(-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014265 /*
14266 * TODO: will the parser context be given if used from
14267 * the relaxNG module?
14268 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000014269
14270 if (nonNegativeIntegerType == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014271 nonNegativeIntegerType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000014272 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000014273 }
14274 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014275 case XML_SCHEMA_FACET_MININCLUSIVE:
14276 case XML_SCHEMA_FACET_MINEXCLUSIVE:
14277 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardf4b05d02004-07-05 13:10:37 +000014278 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
14279 case XML_SCHEMA_FACET_ENUMERATION: {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014280 /*
14281 * Okay we need to validate the value
14282 * at that point.
14283 */
14284 xmlSchemaValidCtxtPtr vctxt;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014285 xmlSchemaTypePtr base;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000014286
14287 /* 4.3.5.5 Constraints on enumeration Schema Components
14288 * Schema Component Constraint: enumeration valid restriction
14289 * It is an ·error· if any member of {value} is not in the
14290 * ·value space· of {base type definition}.
14291 *
14292 * minInclusive, maxInclusive, minExclusive, maxExclusive:
14293 * The value ·must· be in the
14294 * ·value space· of the ·base type·.
14295 */
14296 /*
14297 * This function is intended to deliver a compiled value
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000014298 * on the facet. In this implementation of XML Schemata the
14299 * type holding a facet, won't be a built-in type.
14300 * Thus to ensure that other API
Daniel Veillardf4b05d02004-07-05 13:10:37 +000014301 * calls (relaxng) do work, if the given type is a built-in
14302 * type, we will assume that the given built-in type *is
14303 * already* the base type.
14304 */
14305 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
14306 base = typeDecl->baseType;
14307 if (base == NULL) {
14308 xmlSchemaPErr(ctxt, typeDecl->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014309 XML_SCHEMAP_INTERNAL,
Daniel Veillardf4b05d02004-07-05 13:10:37 +000014310 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000014311 "the type '%s' has no base type.\n",
Daniel Veillardf4b05d02004-07-05 13:10:37 +000014312 typeDecl->name, NULL);
14313 return (-1);
14314 }
14315 } else
14316 base = typeDecl;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014317 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014318 * This avoids perseverative creation of the
14319 * validation context if a parser context is
14320 * used.
Daniel Veillard01fa6152004-06-29 17:04:39 +000014321 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014322 if (ctxt != NULL) {
14323 reuseValCtxt = 1;
14324 if (ctxt->vctxt == NULL) {
14325 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
14326 return (-1);
14327 }
14328 vctxt = ctxt->vctxt;
14329 } else {
14330 vctxt = xmlSchemaNewValidCtxt(NULL);
14331 if (vctxt == NULL) {
14332 xmlSchemaPErr(ctxt, typeDecl->node,
14333 XML_SCHEMAP_INTERNAL,
14334 "Internal error: xmlSchemaCheckFacet, "
14335 "creating a new validation context.\n",
14336 NULL, NULL);
14337 return (-1);
14338 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014339 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014340
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014341 vctxt->node = facet->node;
14342 vctxt->cur = NULL;
14343 /*
14344 * NOTE: This call does not check the content nodes,
14345 * since they are not available:
14346 * facet->node is just the node holding the facet
14347 * definition, *not* the attribute holding the *value*
14348 * of the facet.
14349 */
14350 ret = xmlSchemaValidateSimpleTypeValue(vctxt, base,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000014351 facet->value, 0, 1, 1, 0);
Daniel Veillardf4b05d02004-07-05 13:10:37 +000014352 if (ret > 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014353 /* error code */
14354 if (ctxt != NULL) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000014355 xmlChar *str = NULL;
14356
14357 xmlSchemaPCustomErrExt(ctxt,
14358 XML_SCHEMAP_INVALID_FACET_VALUE,
14359 NULL, (xmlSchemaTypePtr) facet, facet->node,
14360 "The value '%s' of the facet does not validate "
14361 "against the base type '%s'",
14362 facet->value,
14363 xmlSchemaFormatQName(&str,
14364 base->targetNamespace, base->name), NULL);
14365 FREE_AND_NULL(str)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014366 }
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000014367 /* xmlSchemaFacetTypeToString(facet->type), */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014368 ret = -1;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000014369 } else if (ret < 0) {
14370 xmlSchemaPErrExt(ctxt, facet->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014371 XML_SCHEMAP_INTERNAL,
Daniel Veillardf4b05d02004-07-05 13:10:37 +000014372 NULL, NULL, NULL,
14373 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000014374 "failed to validate the value '%s' name of the "
14375 "facet '%s' against the base type '%s'.\n",
Daniel Veillardf4b05d02004-07-05 13:10:37 +000014376 facet->value,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014377 xmlSchemaFacetTypeToString(facet->type),
Daniel Veillardf4b05d02004-07-05 13:10:37 +000014378 base->name, NULL, NULL);
14379 ret = -1;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000014380 } else {
14381 if (vctxt->value != NULL) {
14382 facet->val = vctxt->value;
14383 vctxt->value = NULL;
14384 } else {
14385 xmlChar *str;
14386 /*
14387 * Ensure computed values even for type string.
14388 * TODO OPTIMIZE MEMORY: The value will be hold twice,
14389 * by the facet->value and by the computed value.
14390 */
14391 str = xmlStrdup(facet->value);
14392 if (xmlSchemaPostCreateVal(vctxt, typeDecl,
14393 BAD_CAST str, &(facet->val)) == -1) {
14394 FREE_AND_NULL(str)
14395 xmlSchemaPErr(ctxt, typeDecl->node,
14396 XML_SCHEMAP_INTERNAL,
14397 "Internal error: xmlSchemaCheckFacet, "
14398 "post-creating a computed value.\n",
14399 NULL, NULL);
14400 /* Note that we don't return a failure yet.*/
14401 }
14402 }
14403 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014404 if (reuseValCtxt == 0)
14405 xmlSchemaFreeValidCtxt(vctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014406 break;
14407 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014408 case XML_SCHEMA_FACET_PATTERN:
14409 facet->regexp = xmlRegexpCompile(facet->value);
14410 if (facet->regexp == NULL) {
14411 xmlSchemaPErr(ctxt, typeDecl->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014412 XML_SCHEMAP_REGEXP_INVALID,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014413 "Type definition '%s': The value '%s' of the "
14414 "facet 'pattern' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000014415 name, facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014416 ret = -1;
14417 }
14418 break;
14419 case XML_SCHEMA_FACET_TOTALDIGITS:
14420 case XML_SCHEMA_FACET_FRACTIONDIGITS:
14421 case XML_SCHEMA_FACET_LENGTH:
14422 case XML_SCHEMA_FACET_MAXLENGTH:
14423 case XML_SCHEMA_FACET_MINLENGTH:{
14424 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000014425
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014426 tmp =
14427 xmlSchemaValidatePredefinedType(nonNegativeIntegerType,
14428 facet->value,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +000014429 &(facet->val));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014430 if (tmp != 0) {
14431 /* error code */
14432 if (ctxt != NULL) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000014433 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014434 XML_SCHEMAP_INVALID_FACET_VALUE,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000014435 NULL, (xmlSchemaTypePtr) facet, facet->node,
14436 "The value '%s' of the facet is not a valid "
14437 "nonNegativeInteger", facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014438 }
14439 ret = -1;
14440 }
14441 break;
14442 }
14443 case XML_SCHEMA_FACET_WHITESPACE:{
14444 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
14445 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
14446 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
14447 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
14448 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
14449 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
14450 } else {
14451 if (ctxt != NULL) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000014452 /* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */
14453 xmlSchemaPCustomErr(ctxt,
14454 XML_SCHEMAP_INVALID_FACET_VALUE,
14455 NULL, (xmlSchemaTypePtr) facet, facet->node,
14456 "The value '%s' of the facet is not a valid",
14457 facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014458 }
14459 ret = -1;
14460 }
14461 }
14462 default:
14463 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000014464 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014465 return (ret);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000014466}
14467
14468/**
Daniel Veillard4255d502002-04-16 15:50:10 +000014469 * xmlSchemaCheckDefaults:
14470 * @typeDecl: the schema type definition
14471 * @ctxt: the schema parser context
14472 *
14473 * Checks the default values types, especially for facets
14474 */
14475static void
14476xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014477 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000014478{
Daniel Veillard4255d502002-04-16 15:50:10 +000014479 if (name == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014480 name = typeDecl->name;
14481 /*
14482 * NOTE: It is intended to use the facets list, instead
14483 * of facetSet.
14484 */
14485 if (typeDecl->facets != NULL) {
14486 xmlSchemaFacetPtr facet = typeDecl->facets;
14487
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014488 /*
14489 * Temporarily assign the "schema" to the validation context
14490 * of the parser context. This is needed for NOTATION validation.
14491 */
14492 if (ctxt->vctxt == NULL) {
14493 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
14494 return;
14495 }
14496 ctxt->vctxt->schema = ctxt->schema;
14497
Daniel Veillard01fa6152004-06-29 17:04:39 +000014498 while (facet != NULL) {
14499 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
14500 facet = facet->next;
14501 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014502
14503 ctxt->vctxt->schema = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014504 }
Daniel Veillard4255d502002-04-16 15:50:10 +000014505}
14506
14507/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014508 * xmlSchemaGetCircModelGrDefRef:
14509 * @ctxtGr: the searched model group
14510 * @list: the list of model groups to be processed
14511 *
14512 * This one is intended to be used by
14513 * xmlSchemaCheckGroupDefCircular only.
14514 *
14515 * Returns the circular model group definition reference, otherwise NULL.
14516 */
14517static xmlSchemaTypePtr
14518xmlSchemaGetCircModelGrDefRef(xmlSchemaTypePtr ctxtGrDef,
14519 xmlSchemaTypePtr gr)
14520{
14521 xmlSchemaTypePtr circ = NULL;
14522 int marked;
14523 /*
14524 * We will search for an model group reference which
14525 * references the context model group definition.
14526 */
14527 while (gr != NULL) {
14528 if (((gr->type == XML_SCHEMA_TYPE_GROUP) ||
14529 (gr->type == XML_SCHEMA_TYPE_ALL) ||
14530 (gr->type == XML_SCHEMA_TYPE_SEQUENCE) ||
14531 (gr->type == XML_SCHEMA_TYPE_CHOICE)) &&
14532 (gr->subtypes != NULL)) {
14533 marked = 0;
14534 if ((gr->type == XML_SCHEMA_TYPE_GROUP) &&
14535 (gr->ref != NULL)) {
14536 if (gr->subtypes == ctxtGrDef)
14537 return (gr);
14538 else if (gr->subtypes->flags &
14539 XML_SCHEMAS_TYPE_MARKED) {
14540 gr = gr->next;
14541 continue;
14542 } else {
14543 /*
14544 * Mark to avoid infinite recursion on
14545 * circular references not yet examined.
14546 */
14547 gr->subtypes->flags |= XML_SCHEMAS_TYPE_MARKED;
14548 marked = 1;
14549 }
14550 if (gr->subtypes->subtypes != NULL)
14551 circ = xmlSchemaGetCircModelGrDefRef(ctxtGrDef,
14552 gr->subtypes->subtypes);
14553 /*
14554 * Unmark the visited model group definition.
14555 */
14556 if (marked)
14557 gr->subtypes->flags ^= XML_SCHEMAS_TYPE_MARKED;
14558 if (circ != NULL)
14559 return (circ);
14560 } else {
14561 circ = xmlSchemaGetCircModelGrDefRef(ctxtGrDef,
14562 (xmlSchemaTypePtr) gr->subtypes);
14563 if (circ != NULL)
14564 return (circ);
14565 }
14566
14567 }
14568 gr = gr->next;
14569 }
14570 return (NULL);
14571}
14572
14573/**
14574 * xmlSchemaCheckGroupDefCircular:
14575 * attrGr: the model group definition
14576 * @ctxt: the parser context
14577 * @name: the name
14578 *
14579 * Checks for circular references to model group definitions.
14580 */
14581static void
14582xmlSchemaCheckGroupDefCircular(xmlSchemaTypePtr modelGrDef,
14583 xmlSchemaParserCtxtPtr ctxt,
14584 const xmlChar * name ATTRIBUTE_UNUSED)
14585{
14586 /*
14587 * Schema Component Constraint: Model Group Correct
14588 * 2 Circular groups are disallowed. That is, within the {particles}
14589 * of a group there must not be at any depth a particle whose {term}
14590 * is the group itself.
14591 */
14592 /*
14593 * NOTE: "gr->subtypes" holds the referenced group.
14594 */
14595 if ((modelGrDef->type != XML_SCHEMA_TYPE_GROUP) ||
14596 ((modelGrDef->flags & XML_SCHEMAS_TYPE_GLOBAL) == 0) ||
14597 (modelGrDef->subtypes == NULL))
14598 return;
14599 else {
14600 xmlSchemaTypePtr circ;
14601
14602 circ = xmlSchemaGetCircModelGrDefRef(modelGrDef, modelGrDef->subtypes);
14603 if (circ != NULL) {
14604 /*
14605 * TODO: Report the referenced attr group as QName.
14606 */
14607 xmlSchemaPCustomErr(ctxt,
14608 XML_SCHEMAP_MG_PROPS_CORRECT_2,
14609 NULL, NULL, circ->node,
14610 "Circular reference to the model group definition '%s' "
14611 "defined", modelGrDef->name);
14612 /*
14613 * NOTE: We will cut the reference to avoid further
14614 * confusion of the processor.
14615 * TODO: SPEC: Does the spec define how to process here?
14616 */
14617 circ->subtypes = NULL;
14618 }
14619 }
14620}
14621
14622
14623/**
14624 * xmlSchemaGetCircAttrGrRef:
14625 * @ctxtGr: the searched attribute group
14626 * @attr: the current attribute list to be processed
14627 *
14628 * This one is intended to be used by
14629 * xmlSchemaCheckSRCAttributeGroupCircular only.
14630 *
14631 * Returns the circular attribute grou reference, otherwise NULL.
14632 */
14633static xmlSchemaAttributeGroupPtr
14634xmlSchemaGetCircAttrGrRef(xmlSchemaAttributeGroupPtr ctxtGr,
14635 xmlSchemaAttributePtr attr)
14636{
14637 xmlSchemaAttributeGroupPtr circ = NULL, gr;
14638 int marked;
14639 /*
14640 * We will search for an attribute group reference which
14641 * references the context attribute group.
14642 */
14643 while (attr != NULL) {
14644 marked = 0;
14645 if (attr->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
14646 gr = (xmlSchemaAttributeGroupPtr) attr;
14647 if (gr->refItem != NULL) {
14648 if (gr->refItem == ctxtGr)
14649 return (gr);
14650 else if (gr->refItem->flags &
14651 XML_SCHEMAS_ATTRGROUP_MARKED) {
14652 attr = attr->next;
14653 continue;
14654 } else {
14655 /*
14656 * Mark as visited to avoid infinite recursion on
14657 * circular references not yet examined.
14658 */
14659 gr->refItem->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
14660 marked = 1;
14661 }
14662 }
14663 if (gr->attributes != NULL)
14664 circ = xmlSchemaGetCircAttrGrRef(ctxtGr, gr->attributes);
14665 /*
14666 * Unmark the visited group's attributes.
14667 */
14668 if (marked)
14669 gr->refItem->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
14670 if (circ != NULL)
14671 return (circ);
14672 }
14673 attr = attr->next;
14674 }
14675 return (NULL);
14676}
14677
14678/**
14679 * xmlSchemaCheckSRCAttributeGroupCircular:
14680 * attrGr: the attribute group definition
14681 * @ctxt: the parser context
14682 * @name: the name
14683 *
14684 * Checks for circular references of attribute groups.
14685 */
14686static void
14687xmlSchemaCheckAttributeGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
14688 xmlSchemaParserCtxtPtr ctxt,
14689 const xmlChar * name ATTRIBUTE_UNUSED)
14690{
14691 /*
14692 * Schema Representation Constraint:
14693 * Attribute Group Definition Representation OK
14694 * 3 Circular group reference is disallowed outside <redefine>.
14695 * That is, unless this element information item's parent is
14696 * <redefine>, then among the [children], if any, there must
14697 * not be an <attributeGroup> with ref [attribute] which resolves
14698 * to the component corresponding to this <attributeGroup>. Indirect
14699 * circularity is also ruled out. That is, when QName resolution
14700 * (Schema Document) (§3.15.3) is applied to a ·QName· arising from
14701 * any <attributeGroup>s with a ref [attribute] among the [children],
14702 * it must not be the case that a ·QName· is encountered at any depth
14703 * which resolves to the component corresponding to this <attributeGroup>.
14704 */
14705 /*
14706 * Only global components can be referenced.
14707 */
14708 if (((attrGr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) == 0) ||
14709 (attrGr->attributes == NULL))
14710 return;
14711 else {
14712 xmlSchemaAttributeGroupPtr circ;
14713
14714 circ = xmlSchemaGetCircAttrGrRef(attrGr, attrGr->attributes);
14715 if (circ != NULL) {
14716 /*
14717 * TODO: Report the referenced attr group as QName.
14718 */
14719 xmlSchemaPCustomErr(ctxt,
14720 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
14721 NULL, NULL, circ->node,
14722 "Circular reference to the attribute group '%s' "
14723 "defined", attrGr->name);
14724 /*
14725 * NOTE: We will cut the reference to avoid further
14726 * confusion of the processor.
14727 * BADSPEC: The spec should define how to process in this case.
14728 */
14729 circ->attributes = NULL;
14730 circ->refItem = NULL;
14731 }
14732 }
14733}
14734
14735/**
Daniel Veillard13e04c62002-04-23 17:51:29 +000014736 * xmlSchemaAttrGrpFixup:
14737 * @attrgrpDecl: the schema attribute definition
14738 * @ctxt: the schema parser context
14739 * @name: the attribute name
14740 *
14741 * Fixes finish doing the computations on the attributes definitions
14742 */
14743static void
Daniel Veillard3646d642004-06-02 19:19:14 +000014744xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014745 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +000014746{
14747 if (name == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000014748 name = attrgrp->name;
14749 if (attrgrp->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014750 return;
Daniel Veillard3646d642004-06-02 19:19:14 +000014751 if (attrgrp->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014752 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +000014753
Daniel Veillardc0826a72004-08-10 14:17:33 +000014754 ref = xmlSchemaGetAttributeGroup(ctxt->schema, attrgrp->ref,
14755 attrgrp->refNs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014756 if (ref == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014757 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014758 XML_SCHEMAP_SRC_RESOLVE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014759 NULL, (xmlSchemaTypePtr) attrgrp, attrgrp->node,
14760 "ref", attrgrp->ref, attrgrp->refNs,
14761 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014762 return;
14763 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014764 attrgrp->refItem = ref;
14765 /*
14766 * Check for self reference!
14767 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014768 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000014769 attrgrp->attributes = ref->attributes;
14770 attrgrp->attributeWildcard = ref->attributeWildcard;
14771 }
Daniel Veillard13e04c62002-04-23 17:51:29 +000014772}
14773
14774/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014775 * xmlSchemaAttrCheckValConstr:
14776 * @item: an schema attribute declaration/use
14777 * @ctxt: a schema parser context
14778 * @name: the name of the attribute
14779 *
14780 * Validates the value constraints of an attribute declaration/use.
Daniel Veillard4255d502002-04-16 15:50:10 +000014781 *
14782 * Fixes finish doing the computations on the attributes definitions
14783 */
14784static void
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014785xmlSchemaCheckAttrValConstr(xmlSchemaAttributePtr item,
14786 xmlSchemaParserCtxtPtr ctxt,
14787 const xmlChar * name ATTRIBUTE_UNUSED)
14788{
14789
14790 /*
14791 * a-props-correct
14792 * Schema Component Constraint: Attribute Declaration Properties Correct
14793 *
14794 * 2 if there is a {value constraint}, the canonical lexical
14795 * representation of its value must be ·valid· with respect
14796 * to the {type definition} as defined in String Valid (§3.14.4).
14797 */
14798
14799 if (item->defValue != NULL) {
14800 int ret;
14801 xmlNodePtr node;
14802 xmlSchemaTypePtr type;
14803
14804 if (item->subtypes == NULL) {
14805 xmlSchemaPErr(ctxt, item->node,
14806 XML_SCHEMAP_INTERNAL,
14807 "Internal error: xmlSchemaCheckAttrValConstr, "
14808 "type is missing... skipping validation of "
14809 "value constraint", NULL, NULL);
14810 return;
14811 }
14812
14813 /*
14814 * TODO: Try to avoid creating a new context.
14815 * TODO: This all is not very performant.
14816 */
14817 type = item->subtypes;
14818 /*
14819 * Ensure there's validation context.
14820 */
14821 if (ctxt->vctxt == NULL) {
14822 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1) {
14823 xmlSchemaPErr(ctxt, item->node,
14824 XML_SCHEMAP_INTERNAL,
14825 "Internal error: xmlSchemaCheckAttrValConstr, "
14826 "creating a new validation context.\n",
14827 NULL, NULL);
14828 return;
14829 }
14830 }
14831
14832 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
14833 node = (xmlNodePtr) xmlHasProp(item->node, BAD_CAST "fixed");
14834 else
14835 node = (xmlNodePtr) xmlHasProp(item->node, BAD_CAST "default");
14836 ctxt->vctxt->node = node;
14837 ctxt->vctxt->cur = NULL;
14838 /*
14839 * NOTE: This call does not check the content nodes,
14840 * since they are not available:
14841 * facet->node is just the node holding the facet
14842 * definition, *not* the attribute holding the *value*
14843 * of the facet.
14844 */
14845 ret = xmlSchemaValidateSimpleTypeValue(ctxt->vctxt, type,
14846 item->defValue, 0, 1, 1, 0);
14847 if (ret == 0) {
14848 /*
14849 * Store the computed value.
14850 */
14851 item->defVal = ctxt->vctxt->value;
14852 ctxt->vctxt->value = NULL;
14853 } else if (ret > 0) {
14854 if (ctxt != NULL) {
14855 xmlSchemaPSimpleTypeErr(ctxt,
14856 XML_SCHEMAP_A_PROPS_CORRECT_2,
14857 NULL, NULL, node,
14858 type, NULL, item->defValue,
14859 NULL, NULL, NULL);
14860 }
14861 } else if (ret < 0) {
14862 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
14863 NULL, NULL, node,
14864 "Internal error: xmlSchemaAttrCheckValConstr, "
14865 "failed to validate the value constraint of the "
14866 "attribute decl/use against the type '%s'",
14867 type->name);
14868 }
14869 }
14870}
14871
14872#if 0 /* Not used yet. */
14873static int
14874xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
14875 xmlSchemaElementPtr edecl)
14876{
14877 /*
14878 * TODO: 1 The values of the properties of an element declaration must be as
14879 * described in the property tableau in The Element Declaration Schema
14880 * Component (§3.3.1), modulo the impact of Missing Sub-components (§5.3).
14881 */
14882 /*
14883 * 2 If there is a {value constraint}, the canonical lexical
14884 * representation of its value must be ·valid· with respect to the {type
14885 * definition} as defined in Element Default Valid (Immediate) (§3.3.6).
14886 *
14887 * NOTE: This is done in xmlSchemaCheckElemValConstr.
14888 */
14889 /*
14890 * 3 If there is a non-·absent· {substitution group affiliation},
14891 * then {scope} must be global.
14892 *
14893 * NOTE: This is done in xmlSchemaParseElement.
14894 * TODO: Move it to this layer here.
14895 */
14896 /*
14897 * TODO: 4 If there is a {substitution group affiliation}, the {type definition}
14898 * of the element declaration must be validly derived from the {type
14899 * definition} of the {substitution group affiliation}, given the value
14900 * of the {substitution group exclusions} of the {substitution group
14901 * affiliation}, as defined in Type Derivation OK (Complex) (§3.4.6)
14902 * (if the {type definition} is complex) or as defined in
14903 * Type Derivation OK (Simple) (§3.14.6) (if the {type definition} is
14904 * simple).
14905 */
14906 /*
14907 * TODO: 5 If the {type definition} or {type definition}'s {content type}
14908 * is or is derived from ID then there must not be a {value constraint}.
14909 * Note: The use of ID as a type definition for elements goes beyond
14910 * XML 1.0, and should be avoided if backwards compatibility is desired
14911 */
14912 /*
14913 * TODO: 6 Circular substitution groups are disallowed. That is, it must not
14914 * be possible to return to an element declaration by repeatedly following
14915 * the {substitution group affiliation} property.
14916 */
14917}
14918#endif
14919
14920/**
14921 * xmlSchemaCheckElemValConstr:
14922 * @item: an schema element declaration/particle
14923 * @ctxt: a schema parser context
14924 * @name: the name of the attribute
14925 *
14926 * Validates the value constraints of an element declaration.
14927 *
14928 * Fixes finish doing the computations on the element declarations.
14929 */
14930static void
14931xmlSchemaCheckElemValConstr(xmlSchemaElementPtr decl,
14932 xmlSchemaParserCtxtPtr ctxt,
14933 const xmlChar * name ATTRIBUTE_UNUSED)
14934{
14935 if (decl->value != NULL) {
14936 int ret;
14937 xmlNodePtr node = NULL;
14938 xmlSchemaTypePtr type;
14939
14940 /*
14941 * 2 If there is a {value constraint}, the canonical lexical
14942 * representation of its value must be ·valid· with respect to the {type
14943 * definition} as defined in Element Default Valid (Immediate) (§3.3.6).
14944 */
14945 if (decl->subtypes == NULL) {
14946 xmlSchemaPErr(ctxt, decl->node,
14947 XML_SCHEMAP_INTERNAL,
14948 "Internal error: xmlSchemaCheckElemValConstr, "
14949 "type is missing... skipping validation of "
14950 "the value constraint", NULL, NULL);
14951 return;
14952 }
14953 /*
14954 * Ensure there's a validation context.
14955 */
14956 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
14957 return;
14958
14959 type = decl->subtypes;
14960
14961 if (decl->node != NULL) {
14962 if (decl->flags & XML_SCHEMAS_ELEM_FIXED)
14963 node = (xmlNodePtr) xmlHasProp(decl->node, BAD_CAST "fixed");
14964 else
14965 node = (xmlNodePtr) xmlHasProp(decl->node, BAD_CAST "default");
14966 }
14967 ctxt->vctxt->node = node;
14968 ctxt->vctxt->cur = NULL;
14969 ret = xmlSchemaCheckCOSValidDefault(ctxt, ctxt->vctxt, type, decl->value,
14970 node);
14971 if (ret == 0) {
14972 /*
14973 * Consume the computed value.
14974 */
14975 decl->defVal = ctxt->vctxt->value;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000014976 ctxt->vctxt->value = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014977 } else if (ret < 0) {
14978 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
14979 NULL, NULL, node,
14980 "Internal error: xmlSchemaElemCheckValConstr, "
14981 "failed to validate the value constraint of the "
14982 "element declaration '%s'",
14983 decl->name);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000014984 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014985 }
14986}
14987
14988/**
14989 * xmlSchemaAttrFixup:
14990 * @item: an schema attribute declaration/use.
14991 * @ctxt: a schema parser context
14992 * @name: the name of the attribute
14993 *
14994 * Fixes finish doing the computations on attribute declarations/uses.
14995 */
14996static void
14997xmlSchemaAttrFixup(xmlSchemaAttributePtr item,
14998 xmlSchemaParserCtxtPtr ctxt,
14999 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000015000{
Daniel Veillardc0826a72004-08-10 14:17:33 +000015001 /*
15002 * TODO: If including this is done twice (!) for every attribute.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015003 * -> Hmm, check if this is still done.
Daniel Veillardc0826a72004-08-10 14:17:33 +000015004 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015005 /*
15006 * The simple type definition corresponding to the <simpleType> element
15007 * information item in the [children], if present, otherwise the simple
15008 * type definition ·resolved· to by the ·actual value· of the type
15009 * [attribute], if present, otherwise the ·simple ur-type definition·.
15010 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015011 if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
Daniel Veillardc0826a72004-08-10 14:17:33 +000015012 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015013 item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
15014 if (item->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015015 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015016 if (item->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015017 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000015018
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015019 type = xmlSchemaGetType(ctxt->schema, item->typeName,
15020 item->typeNs);
15021 if ((type == NULL) || (! IS_SIMPLE_TYPE(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015022 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015023 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015024 NULL, (xmlSchemaTypePtr) item, item->node,
15025 "type", item->typeName, item->typeNs,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015026 XML_SCHEMA_TYPE_SIMPLE, NULL);
15027 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015028 item->subtypes = type;
15029
15030 } else if (item->ref != NULL) {
15031 xmlSchemaAttributePtr decl;
Daniel Veillard4255d502002-04-16 15:50:10 +000015032
Daniel Veillardc0826a72004-08-10 14:17:33 +000015033 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015034 * We have an attribute use here; assign the referenced
15035 * attribute declaration.
15036 */
15037 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000015038 * TODO: Evaluate, what errors could occur if the declaration is not
15039 * found. It might be possible that the "typefixup" might crash if
15040 * no ref declaration was found.
15041 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015042 decl = xmlSchemaGetAttribute(ctxt->schema, item->ref, item->refNs);
15043 if (decl == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015044 xmlSchemaPResCompAttrErr(ctxt,
15045 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015046 NULL, (xmlSchemaTypePtr) item, item->node,
15047 "ref", item->ref, item->refNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015048 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015049 return;
15050 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015051 item->refDecl = decl;
15052 xmlSchemaAttrFixup(decl, ctxt, NULL);
15053
15054 item->subtypes = decl->subtypes;
15055 /*
15056 * Attribute Use Correct
15057 * au-props-correct.2: If the {attribute declaration} has a fixed
15058 * {value constraint}, then if the attribute use itself has a
15059 * {value constraint}, it must also be fixed and its value must match
15060 * that of the {attribute declaration}'s {value constraint}.
15061 */
15062 if ((decl->flags & XML_SCHEMAS_ATTR_FIXED) &&
15063 (item->defValue != NULL)) {
15064 if (((item->flags & XML_SCHEMAS_ATTR_FIXED) == 0) ||
15065 (!xmlStrEqual(item->defValue, decl->defValue))) {
15066 xmlSchemaPCustomErr(ctxt,
15067 XML_SCHEMAP_AU_PROPS_CORRECT_2,
15068 NULL, NULL, item->node,
15069 "The value constraint must be fixed "
15070 "and match the referenced attribute "
15071 "declarations's value constraint '%s'",
15072 decl->defValue);
15073 }
15074 /*
15075 * FUTURE: One should change the values of the attr. use
15076 * if ever validation should be attempted even if the
15077 * schema itself was not fully valid.
15078 */
15079 }
Daniel Veillard3646d642004-06-02 19:19:14 +000015080 } else {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015081 item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
15082 }
Daniel Veillard4255d502002-04-16 15:50:10 +000015083}
15084
15085/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015086 * xmlSchemaResolveIDCKeyRef:
15087 * @idc: the identity-constraint definition
15088 * @ctxt: the schema parser context
15089 * @name: the attribute name
15090 *
15091 * Resolve keyRef references to key/unique IDCs.
15092 */
15093static void
15094xmlSchemaResolveIDCKeyRef(xmlSchemaIDCPtr idc,
15095 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000015096 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015097{
15098 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
15099 return;
15100 if (idc->ref->name != NULL) {
15101 idc->ref->item = (xmlSchemaBasicItemPtr) xmlHashLookup2(
15102 ctxt->schema->idcDef,
15103 idc->ref->name,
15104 idc->ref->targetNamespace);
15105 if (idc->ref->item == NULL) {
15106 /*
15107 * TODO: It is actually not an error to fail to resolve.
15108 */
15109 xmlSchemaPResCompAttrErr(ctxt,
15110 XML_SCHEMAP_SRC_RESOLVE,
15111 NULL, (xmlSchemaTypePtr) idc, idc->node,
15112 "refer", idc->ref->name,
15113 idc->ref->targetNamespace,
15114 XML_SCHEMA_TYPE_IDC_KEYREF, NULL);
15115 return;
15116 }
15117 }
15118}
15119
15120/**
Daniel Veillard4255d502002-04-16 15:50:10 +000015121 * xmlSchemaParse:
15122 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000015123 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000015124 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +000015125 * XML Shema struture which can be used to validate instances.
15126 * *WARNING* this interface is highly subject to change
15127 *
15128 * Returns the internal XML Schema structure built from the resource or
15129 * NULL in case of error
15130 */
15131xmlSchemaPtr
15132xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
15133{
15134 xmlSchemaPtr ret = NULL;
15135 xmlDocPtr doc;
Daniel Veillardbd2904b2003-11-25 15:38:59 +000015136 xmlNodePtr root;
Daniel Veillarddda22c12004-01-24 08:31:30 +000015137 int preserve = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000015138
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015139 /*
15140 * This one is used if the schema to be parsed was specified via
15141 * the API; i.e. not automatically by the validated instance document.
15142 */
15143
Daniel Veillard4255d502002-04-16 15:50:10 +000015144 xmlSchemaInitTypes();
15145
Daniel Veillard6045c902002-10-09 21:13:59 +000015146 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +000015147 return (NULL);
15148
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000015149 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000015150 ctxt->counter = 0;
15151 ctxt->container = NULL;
15152
15153 /*
15154 * First step is to parse the input document into an DOM/Infoset
15155 */
Daniel Veillard6045c902002-10-09 21:13:59 +000015156 if (ctxt->URL != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000015157 doc = xmlReadFile((const char *) ctxt->URL, NULL,
15158 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015159 if (doc == NULL) {
15160 xmlSchemaPErr(ctxt, NULL,
15161 XML_SCHEMAP_FAILED_LOAD,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015162 "xmlSchemaParse: could not load '%s'.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015163 ctxt->URL, NULL);
15164 return (NULL);
15165 }
Daniel Veillard6045c902002-10-09 21:13:59 +000015166 } else if (ctxt->buffer != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000015167 doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
15168 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015169 if (doc == NULL) {
15170 xmlSchemaPErr(ctxt, NULL,
15171 XML_SCHEMAP_FAILED_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015172 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015173 NULL, NULL);
15174 return (NULL);
15175 }
15176 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard65765282004-01-08 16:59:30 +000015177 ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
Daniel Veillard9d751502003-10-29 13:21:47 +000015178 } else if (ctxt->doc != NULL) {
15179 doc = ctxt->doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000015180 preserve = 1;
Daniel Veillard6045c902002-10-09 21:13:59 +000015181 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015182 xmlSchemaPErr(ctxt, NULL,
15183 XML_SCHEMAP_NOTHING_TO_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015184 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015185 NULL, NULL);
15186 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000015187 }
15188
15189 /*
15190 * Then extract the root and Schema parse it
15191 */
15192 root = xmlDocGetRootElement(doc);
15193 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015194 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
15195 XML_SCHEMAP_NOROOT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015196 "The schema has no document element.\n", NULL, NULL);
Daniel Veillarddda22c12004-01-24 08:31:30 +000015197 if (!preserve) {
15198 xmlFreeDoc(doc);
15199 }
Daniel Veillard4255d502002-04-16 15:50:10 +000015200 return (NULL);
15201 }
15202
15203 /*
15204 * Remove all the blank text nodes
15205 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +000015206 xmlSchemaCleanupDoc(ctxt, root);
Daniel Veillard4255d502002-04-16 15:50:10 +000015207
15208 /*
15209 * Then do the parsing for good
15210 */
15211 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillard1d913862003-11-21 00:28:39 +000015212 if (ret == NULL) {
Daniel Veillarddda22c12004-01-24 08:31:30 +000015213 if (!preserve) {
15214 xmlFreeDoc(doc);
15215 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015216 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +000015217 }
Daniel Veillard4255d502002-04-16 15:50:10 +000015218 ret->doc = doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000015219 ret->preserve = preserve;
Daniel Veillard4255d502002-04-16 15:50:10 +000015220 ctxt->schema = ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015221 ctxt->ctxtType = NULL;
15222 ctxt->parentItem = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000015223 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +000015224 * Then fixup all attributes declarations
15225 */
15226 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
15227
15228 /*
15229 * Then fixup all attributes group declarations
15230 */
15231 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
15232 ctxt);
15233
15234 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015235 * Resolve identity-constraint keyRefs.
15236 */
15237 xmlHashScan(ret->idcDef, (xmlHashScanner) xmlSchemaResolveIDCKeyRef, ctxt);
15238
15239 /*
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015240 * Check attribute groups for circular references.
15241 */
15242 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner)
15243 xmlSchemaCheckAttributeGroupCircular, ctxt);
15244
15245 /*
15246 * Then fixup all model group definitions.
15247 */
15248 xmlHashScan(ret->groupDecl, (xmlHashScanner) xmlSchemaGroupDefFixup, ctxt);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015249
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015250 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000015251 * Then fix references of element declaration; apply constraints.
15252 */
15253 xmlHashScanFull(ret->elemDecl,
15254 (xmlHashScannerFull) xmlSchemaRefFixupCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000015255
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000015256 /*
15257 * We will stop here if the schema was not valid to avoid internal errors
15258 * on missing sub-components. This is not conforming to the spec, since it
15259 * allows missing components, but it might make further processing crash.
15260 * So see it as a very strict handling, which might be made more lax in the
15261 * future.
15262 */
15263 if (ctxt->nberrors != 0)
15264 goto exit;
15265 /*
15266 * Then fixup all types properties
15267 */
15268 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015269 /*
15270 * Check model groups defnitions for circular references.
15271 */
15272 xmlHashScan(ret->groupDecl, (xmlHashScanner)
15273 xmlSchemaCheckGroupDefCircular, ctxt);
15274
Daniel Veillard4255d502002-04-16 15:50:10 +000015275 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015276 * Then build the content model for all complex types
Daniel Veillard4255d502002-04-16 15:50:10 +000015277 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015278 xmlHashScan(ret->typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015279 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000015280
15281 /*
15282 * Then check the defaults part of the type like facets values
15283 */
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000015284 /* OLD: xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaCheckDefaults, ctxt); */
Daniel Veillard4255d502002-04-16 15:50:10 +000015285
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015286 /*
15287 * Validate the value constraint of attribute declarations/uses.
15288 */
15289 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaCheckAttrValConstr, ctxt);
15290
15291 /*
15292 * Validate the value constraint of element declarations.
15293 */
15294 xmlHashScan(ret->elemDecl, (xmlHashScanner) xmlSchemaCheckElemValConstr, ctxt);
15295
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000015296exit:
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000015297 if (ctxt->nberrors != 0) {
15298 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015299 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000015300 }
Daniel Veillard4255d502002-04-16 15:50:10 +000015301 return (ret);
15302}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015303
Daniel Veillard4255d502002-04-16 15:50:10 +000015304/**
Daniel Veillard01c13b52002-12-10 15:19:08 +000015305 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +000015306 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +000015307 * @err: the error callback
15308 * @warn: the warning callback
15309 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +000015310 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000015311 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000015312 */
15313void
15314xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015315 xmlSchemaValidityErrorFunc err,
15316 xmlSchemaValidityWarningFunc warn, void *ctx)
15317{
Daniel Veillard4255d502002-04-16 15:50:10 +000015318 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015319 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000015320 ctxt->error = err;
15321 ctxt->warning = warn;
15322 ctxt->userData = ctx;
15323}
15324
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000015325/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000015326 * xmlSchemaGetParserErrors:
15327 * @ctxt: a XMl-Schema parser context
15328 * @err: the error callback result
15329 * @warn: the warning callback result
15330 * @ctx: contextual data for the callbacks result
15331 *
15332 * Get the callback information used to handle errors for a parser context
15333 *
15334 * Returns -1 in case of failure, 0 otherwise
15335 */
15336int
15337xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
15338 xmlSchemaValidityErrorFunc * err,
15339 xmlSchemaValidityWarningFunc * warn, void **ctx)
15340{
15341 if (ctxt == NULL)
15342 return(-1);
15343 if (err != NULL)
15344 *err = ctxt->error;
15345 if (warn != NULL)
15346 *warn = ctxt->warning;
15347 if (ctx != NULL)
15348 *ctx = ctxt->userData;
15349 return(0);
15350}
15351
15352/**
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000015353 * xmlSchemaFacetTypeToString:
15354 * @type: the facet type
15355 *
15356 * Convert the xmlSchemaTypeType to a char string.
15357 *
15358 * Returns the char string representation of the facet type if the
15359 * type is a facet and an "Internal Error" string otherwise.
15360 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000015361static const xmlChar *
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000015362xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
15363{
15364 switch (type) {
15365 case XML_SCHEMA_FACET_PATTERN:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000015366 return (BAD_CAST "pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015367 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000015368 return (BAD_CAST "maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015369 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000015370 return (BAD_CAST "maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015371 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000015372 return (BAD_CAST "minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015373 case XML_SCHEMA_FACET_MININCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000015374 return (BAD_CAST "minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015375 case XML_SCHEMA_FACET_WHITESPACE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000015376 return (BAD_CAST "whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015377 case XML_SCHEMA_FACET_ENUMERATION:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000015378 return (BAD_CAST "enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015379 case XML_SCHEMA_FACET_LENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000015380 return (BAD_CAST "length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015381 case XML_SCHEMA_FACET_MAXLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000015382 return (BAD_CAST "maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015383 case XML_SCHEMA_FACET_MINLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000015384 return (BAD_CAST "minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015385 case XML_SCHEMA_FACET_TOTALDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000015386 return (BAD_CAST "totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015387 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000015388 return (BAD_CAST "fractionDigits");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000015389 default:
15390 break;
15391 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000015392 return (BAD_CAST "Internal Error");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000015393}
15394
Daniel Veillardc0826a72004-08-10 14:17:33 +000015395static int
15396xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
15397{
15398 xmlSchemaTypePtr anc;
15399
15400 /*
15401 * The normalization type can be changed only for types which are derived
15402 * from xsd:string.
15403 */
15404 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000015405 if (type->builtInType == XML_SCHEMAS_STRING)
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000015406 return(XML_SCHEMAS_FACET_PRESERVE);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000015407 else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000015408 return(XML_SCHEMAS_FACET_REPLACE);
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000015409 else if (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)
15410 /*
15411 * Note that we assume a whitespace of preserve for anySimpleType.
15412 */
15413 return(XML_SCHEMAS_FACET_PRESERVE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015414 else {
15415 /*
15416 * For all ·atomic· datatypes other than string (and types ·derived·
15417 * by ·restriction· from it) the value of whiteSpace is fixed to
15418 * collapse
15419 */
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000015420 return(XML_SCHEMAS_FACET_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015421 }
15422 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
15423 /*
15424 * For list types the facet "whiteSpace" is fixed to "collapse".
15425 */
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000015426 return (XML_SCHEMAS_FACET_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015427 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000015428 return (XML_SCHEMAS_FACET_UNKNOWN);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015429 } else if (type->facetSet != NULL) {
15430 xmlSchemaTypePtr anyST;
15431 xmlSchemaFacetLinkPtr lin;
15432
15433 /*
15434 * Atomic types.
15435 */
15436 anyST = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
15437 anc = type->baseType;
15438 do {
15439 /*
15440 * For all ·atomic· datatypes other than string (and types ·derived·
15441 * by ·restriction· from it) the value of whiteSpace is fixed to
15442 * collapse
15443 */
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000015444 if ((anc->builtInType == XML_SCHEMAS_STRING) ||
15445 (anc->builtInType == XML_SCHEMAS_NORMSTRING)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015446
15447 lin = type->facetSet;
15448 do {
15449 if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000015450 return(lin->facet->whitespace);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015451 break;
15452 }
15453 lin = lin->next;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000015454 } while (lin != NULL);
15455 if (anc->builtInType == XML_SCHEMAS_NORMSTRING)
15456 return (XML_SCHEMAS_FACET_REPLACE);
15457 else
15458 return (XML_SCHEMAS_FACET_PRESERVE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015459 }
15460 anc = anc->baseType;
15461 } while (anc != anyST);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000015462 return (XML_SCHEMAS_FACET_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015463 }
15464 return (-1);
15465}
15466
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000015467/**
Daniel Veillard377e1a92004-04-16 16:30:05 +000015468 * xmlSchemaValidateFacetsInternal:
15469 * @ctxt: a schema validation context
Daniel Veillardc0826a72004-08-10 14:17:33 +000015470 * @type: the type holding the facets
Daniel Veillard377e1a92004-04-16 16:30:05 +000015471 * @facets: the list of facets to check
15472 * @value: the lexical repr of the value to validate
15473 * @val: the precomputed value
William M. Bracke7091952004-05-11 15:09:58 +000015474 * @fireErrors: if 0, only internal errors will be fired;
15475 * otherwise all errors will be fired.
Daniel Veillard377e1a92004-04-16 16:30:05 +000015476 *
15477 * Check a value against all facet conditions
15478 *
15479 * Returns 0 if the element is schemas valid, a positive error code
15480 * number otherwise and -1 in case of internal or API error.
15481 */
15482static int
15483xmlSchemaValidateFacetsInternal(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015484 xmlSchemaTypePtr type,
15485 const xmlChar * value,
15486 unsigned long length,
15487 int fireErrors)
Daniel Veillard377e1a92004-04-16 16:30:05 +000015488{
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000015489 int ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015490 xmlNodePtr node;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000015491 xmlSchemaTypePtr biType; /* The build-in type. */
Daniel Veillardc0826a72004-08-10 14:17:33 +000015492 xmlSchemaTypePtr tmpType;
15493 xmlSchemaFacetLinkPtr facetLink;
Daniel Veillardc7e3cc42004-09-28 12:33:52 +000015494 int retFacet;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015495 xmlSchemaFacetPtr facet;
15496 unsigned long len = 0;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000015497 xmlSchemaWhitespaceValueType ws;
15498
15499 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
15500 xmlSchemaTypePtr tp;
15501 /*
15502 * TODO: Get rid of this case: the complex type still holds facets in some
15503 * cases.
15504 */
15505 tp = xmlSchemaGetSimpleContentType(type);
15506 ws = (xmlSchemaWhitespaceValueType) xmlSchemaGetWhiteSpaceFacetValue(tp);
15507 } else
15508 ws = (xmlSchemaWhitespaceValueType) xmlSchemaGetWhiteSpaceFacetValue(type);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000015509
Daniel Veillardc0826a72004-08-10 14:17:33 +000015510#ifdef DEBUG_UNION_VALIDATION
15511 printf("Facets of type: '%s'\n", (const char *) type->name);
15512 printf(" fireErrors: %d\n", fireErrors);
15513#endif
15514
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015515 node = ctxt->node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015516 /*
15517 * NOTE: Do not jump away, if the facetSet of the given type is
15518 * empty: until now, "pattern" facets of the *base types* need to
15519 * be checked as well.
15520 */
15521 biType = type->baseType;
15522 while ((biType != NULL) && (biType->type != XML_SCHEMA_TYPE_BASIC))
15523 biType = biType->baseType;
15524 if (biType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015525 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015526 "Internal error: xmlSchemaValidateFacetsInternal, "
15527 "the base type axis of the given type '%s' does not resolve to "
15528 "a built-in type.\n",
15529 type->name, NULL);
15530 return (-1);
15531 }
15532
15533 if (type->facetSet != NULL) {
15534 facetLink = type->facetSet;
15535 while (facetLink != NULL) {
15536 facet = facetLink->facet;
15537 /*
15538 * Skip the pattern "whiteSpace": it is used to
15539 * format the character content beforehand.
15540 */
15541 switch (facet->type) {
15542 case XML_SCHEMA_FACET_WHITESPACE:
15543 case XML_SCHEMA_FACET_PATTERN:
15544 case XML_SCHEMA_FACET_ENUMERATION:
15545 break;
15546 case XML_SCHEMA_FACET_LENGTH:
15547 case XML_SCHEMA_FACET_MINLENGTH:
15548 case XML_SCHEMA_FACET_MAXLENGTH:
15549 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
15550 ret = xmlSchemaValidateListSimpleTypeFacet(facet,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000015551 value, length, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015552 len = length;
15553 } else
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000015554 ret = xmlSchemaValidateLengthFacetWhtsp(facet,
15555 (xmlSchemaValType) biType->builtInType,
15556 value, ctxt->value, &len, ws);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015557 break;
15558 default:
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000015559 ret = xmlSchemaValidateFacetWhtsp(facet, ws,
15560 biType->builtInType, value, ctxt->value, ws);
15561 /*
15562 * ret = xmlSchemaValidateFacet(biType, facet, value,
15563 * ctxt->value);
15564 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015565 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000015566 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015567 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015568 "Internal error: xmlSchemaValidateFacetsInternal, "
15569 "validating facet of type '%s'.\n",
15570 type->name, NULL);
15571 break;
15572 } else if ((ret > 0) && (fireErrors)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015573 xmlSchemaVFacetErr(ctxt, ret, node, value, len,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015574 type, facet, NULL, NULL, NULL, NULL);
15575 }
15576
15577 facetLink = facetLink->next;
15578 }
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000015579
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000015580 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000015581 if (ret >= 0) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000015582 xmlSchemaWhitespaceValueType fws;
15583 /*
15584 * Process enumerations. Facet values are in the value space
15585 * of the defining type's base type. This seems to be a bug in the
15586 * XML Schema 1.0 spec. For use, the normalized value is only
15587 * significant for enumerations. We need to localize the base type for eatch
15588 * enumeration facet, thus walk the ancestor type axis.
15589 */
15590 tmpType = type;
15591 do {
15592 /*
15593 * Use the whitespace type of the base type.
15594 */
15595 if (tmpType->type == XML_SCHEMA_TYPE_COMPLEX)
15596 /* TODO: Get rid of this case. */
15597 fws = (xmlSchemaWhitespaceValueType)
15598 xmlSchemaGetWhiteSpaceFacetValue(
15599 xmlSchemaGetSimpleContentType(tmpType));
15600 else
15601 fws = (xmlSchemaWhitespaceValueType)
15602 xmlSchemaGetWhiteSpaceFacetValue(tmpType->baseType);
15603 retFacet = 0;
15604 for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
15605 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
15606 continue;
15607 retFacet = xmlSchemaValidateFacetWhtsp(facet, fws,
15608 biType->builtInType, value, ctxt->value, ws);
15609 if (retFacet == 0)
15610 break;
15611 else if (retFacet < 0) {
15612 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
15613 "Internal error: xmlSchemaValidateFacetsInternal, "
15614 "validating enumeration facet '%s' of type '%s'.\n",
15615 facet->value, tmpType->name);
15616 ret = -1;
15617 break;
15618 }
15619 }
15620 if (retFacet <= 0)
15621 break;
15622 if (tmpType->type == XML_SCHEMA_TYPE_COMPLEX)
15623 /* TODO: Get rid of this case. */
15624 tmpType = xmlSchemaGetSimpleContentType(tmpType);
15625 else
15626 tmpType = tmpType->baseType;
15627 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
15628 if (retFacet > 0) {
15629 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
15630 if (fireErrors) {
15631 xmlSchemaVFacetErr(ctxt, ret, node, value, 0, type, NULL,
15632 NULL, NULL, NULL, NULL);
15633 }
15634 }
15635 }
15636
15637 if (ret >= 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015638 /*
15639 * Process patters. Pattern facets are ORed at type level
15640 * and ANDed if derived. Walk the base type axis.
15641 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000015642 tmpType = type;
15643 facet = NULL;
15644 do {
15645 retFacet = 0;
15646 for (facetLink = tmpType->facetSet; facetLink != NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015647 facetLink = facetLink->next) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015648 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
15649 continue;
15650 retFacet = xmlSchemaValidateFacet(biType, facetLink->facet,
15651 value, ctxt->value);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015652 if (retFacet == 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +000015653 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015654 else if (retFacet < 0) {
15655 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
15656 "Internal error: xmlSchemaValidateFacetsInternal, "
15657 "validating 'pattern' facet '%s' of type '%s'.\n",
15658 facetLink->facet->value, tmpType->name);
15659 ret = -1;
15660 break;
15661 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +000015662 /* Save the last non-validating facet. */
15663 facet = facetLink->facet;
15664 }
15665 if (retFacet != 0)
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000015666 break;
15667 if (tmpType->type == XML_SCHEMA_TYPE_COMPLEX)
15668 /* TODO: Get rid of this case. */
15669 tmpType = xmlSchemaGetSimpleContentType(tmpType);
15670 else
15671 tmpType = tmpType->baseType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015672 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015673 if (retFacet > 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015674 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
15675 if (fireErrors) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015676 xmlSchemaVFacetErr(ctxt, ret, node, value, 0, type, facet,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015677 NULL, NULL, NULL, NULL);
15678 }
15679 }
15680 }
15681
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000015682 return (ret);
15683}
15684
Daniel Veillard4255d502002-04-16 15:50:10 +000015685/************************************************************************
15686 * *
15687 * Simple type validation *
15688 * *
15689 ************************************************************************/
Daniel Veillard377e1a92004-04-16 16:30:05 +000015690
Daniel Veillard4255d502002-04-16 15:50:10 +000015691
15692/************************************************************************
15693 * *
15694 * DOM Validation code *
15695 * *
15696 ************************************************************************/
15697
Daniel Veillard4255d502002-04-16 15:50:10 +000015698static int xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015699 xmlNodePtr elem,
Daniel Veillard3646d642004-06-02 19:19:14 +000015700 xmlSchemaTypePtr type);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015701static int xmlSchemaValidateElementByType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015702 xmlSchemaTypePtr type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000015703 int isNil,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015704 int valSimpleContent);
Daniel Veillard4255d502002-04-16 15:50:10 +000015705
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015706static void xmlSchemaBeginElement(xmlSchemaValidCtxtPtr vctxt);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000015707static int xmlSchemaEndElement(xmlSchemaValidCtxtPtr vctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015708
15709#ifdef ELEM_INFO_ENABLED
15710/**
15711 * xmlSchemaGetFreshElemInfo:
15712 * @vctxt: the schema validation context
15713 *
15714 * Creates/reuses and initializes the element info item for
15715 * the currect tree depth.
15716 *
15717 * Returns the element info item or NULL on API or internal errors.
15718 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000015719static xmlSchemaNodeInfoPtr
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000015720xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt,
15721 int depth)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015722{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000015723 xmlSchemaNodeInfoPtr info = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015724
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000015725 if (depth > vctxt->sizeElemInfos) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015726 xmlSchemaVErr(vctxt, NULL, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000015727 "Internal error: xmlSchemaGetFreshElemInfo, "
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015728 "an inconsistent depth encountered.\n",
15729 NULL, NULL);
15730 return (NULL);
15731 }
15732 if (vctxt->elemInfos == NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000015733 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
15734 xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015735 if (vctxt->elemInfos == NULL) {
15736 xmlSchemaVErrMemory(vctxt,
15737 "allocating the element info array", NULL);
15738 return (NULL);
15739 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000015740 memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015741 vctxt->sizeElemInfos = 10;
15742 } else if (vctxt->sizeElemInfos == vctxt->depth) {
15743 int i = vctxt->sizeElemInfos;
15744
15745 vctxt->sizeElemInfos *= 2;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000015746 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015747 xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000015748 sizeof(xmlSchemaNodeInfoPtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015749 if (vctxt->elemInfos == NULL) {
15750 xmlSchemaVErrMemory(vctxt,
15751 "re-allocating the element info array", NULL);
15752 return (NULL);
15753 }
15754 /*
15755 * We need the new memory to be NULLed.
15756 * TODO: Use memset instead?
15757 */
15758 for (; i < vctxt->sizeElemInfos; i++)
15759 vctxt->elemInfos[i] = NULL;
15760 } else
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000015761 info = vctxt->elemInfos[depth];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015762
15763 if (info == NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000015764 info = (xmlSchemaNodeInfoPtr)
15765 xmlMalloc(sizeof(xmlSchemaNodeInfo));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015766 if (info == NULL) {
15767 xmlSchemaVErrMemory(vctxt,
15768 "allocating an element info", NULL);
15769 return (NULL);
15770 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000015771 vctxt->elemInfos[depth] = info;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015772 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000015773 memset(info, 0, sizeof(xmlSchemaNodeInfo));
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000015774 info->depth = depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015775
15776 return (info);
15777}
15778#endif /* ELEM_INFO_ENABLED */
15779
Daniel Veillard3646d642004-06-02 19:19:14 +000015780
15781/**
15782 * xmlSchemaFreeAttrStates:
15783 * @state: a list of attribute states
15784 *
15785 * Free the given list of attribute states
15786 *
15787 */
15788static void
15789xmlSchemaFreeAttributeStates(xmlSchemaAttrStatePtr state)
15790{
15791 xmlSchemaAttrStatePtr tmp;
15792 while (state != NULL) {
15793 tmp = state;
15794 state = state->next;
15795 xmlFree(tmp);
15796 }
15797}
15798
Daniel Veillard4255d502002-04-16 15:50:10 +000015799/**
15800 * xmlSchemaRegisterAttributes:
15801 * @ctxt: a schema validation context
15802 * @attrs: a list of attributes
15803 *
15804 * Register the list of attributes as the set to be validated on that element
15805 *
15806 * Returns -1 in case of error, 0 otherwise
15807 */
15808static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015809xmlSchemaRegisterAttributes(xmlSchemaValidCtxtPtr ctxt, xmlAttrPtr attrs)
15810{
Daniel Veillard3646d642004-06-02 19:19:14 +000015811 xmlSchemaAttrStatePtr tmp;
15812
15813 ctxt->attr = NULL;
15814 ctxt->attrTop = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000015815 while (attrs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015816 if ((attrs->ns != NULL) &&
15817 (xmlStrEqual(attrs->ns->href, xmlSchemaInstanceNs))) {
15818 attrs = attrs->next;
15819 continue;
15820 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000015821 tmp = (xmlSchemaAttrStatePtr)
15822 xmlMalloc(sizeof(xmlSchemaAttrState));
15823 if (tmp == NULL) {
15824 xmlSchemaVErrMemory(ctxt, "registering attributes", NULL);
15825 return (-1);
15826 }
Daniel Veillard3646d642004-06-02 19:19:14 +000015827 tmp->attr = attrs;
15828 tmp->state = XML_SCHEMAS_ATTR_UNKNOWN;
15829 tmp->next = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015830 tmp->decl = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000015831 if (ctxt->attr == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015832 ctxt->attr = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000015833 else
15834 ctxt->attrTop->next = tmp;
15835 ctxt->attrTop = tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015836 attrs = attrs->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000015837 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015838 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000015839}
15840
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015841#if 0 /* Currently not used */
Daniel Veillard4255d502002-04-16 15:50:10 +000015842/**
Daniel Veillard4255d502002-04-16 15:50:10 +000015843 * xmlSchemaValidateCheckNodeList
15844 * @nodelist: the list of nodes
15845 *
15846 * Check the node list is only made of text nodes and entities pointing
15847 * to text nodes
15848 *
15849 * Returns 1 if true, 0 if false and -1 in case of error
15850 */
15851static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015852xmlSchemaValidateCheckNodeList(xmlNodePtr nodelist)
15853{
Daniel Veillard4255d502002-04-16 15:50:10 +000015854 while (nodelist != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015855 if (nodelist->type == XML_ENTITY_REF_NODE) {
15856 TODO /* implement recursion in the entity content */
15857 }
15858 if ((nodelist->type != XML_TEXT_NODE) &&
15859 (nodelist->type != XML_COMMENT_NODE) &&
15860 (nodelist->type != XML_PI_NODE) &&
William M. Bracke7091952004-05-11 15:09:58 +000015861 (nodelist->type != XML_CDATA_SECTION_NODE)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015862 return (0);
15863 }
15864 nodelist = nodelist->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000015865 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015866 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +000015867}
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015868#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000015869
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015870static void
15871xmlSchemaPostSchemaAssembleFixup(xmlSchemaParserCtxtPtr ctxt)
15872{
15873 int i, nbItems;
15874 xmlSchemaTypePtr item, *items;
15875
15876
15877 /*
15878 * During the Assemble of the schema ctxt->curItems has
15879 * been filled with the relevant new items. Fix those up.
15880 */
15881 nbItems = ctxt->assemble->nbItems;
15882 items = (xmlSchemaTypePtr *) ctxt->assemble->items;
15883
15884 for (i = 0; i < nbItems; i++) {
15885 item = items[i];
15886 switch (item->type) {
15887 case XML_SCHEMA_TYPE_ATTRIBUTE:
15888 xmlSchemaAttrFixup((xmlSchemaAttributePtr) item, ctxt, NULL);
15889 break;
15890 case XML_SCHEMA_TYPE_ELEMENT:
15891 xmlSchemaRefFixupCallback((xmlSchemaElementPtr) item, ctxt,
15892 NULL, NULL, NULL);
15893 break;
15894 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
15895 xmlSchemaAttrGrpFixup((xmlSchemaAttributeGroupPtr) item,
15896 ctxt, NULL);
15897 break;
15898 case XML_SCHEMA_TYPE_GROUP:
15899 xmlSchemaGroupDefFixup(item, ctxt, NULL);
15900 default:
15901 break;
15902 }
15903 }
15904 /*
15905 * Circularity checks.
15906 */
15907 for (i = 0; i < nbItems; i++) {
15908 item = items[i];
15909 switch (item->type) {
15910 case XML_SCHEMA_TYPE_GROUP:
15911 xmlSchemaCheckGroupDefCircular(item, ctxt, NULL);
15912 break;
15913 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
15914 xmlSchemaCheckAttributeGroupCircular(
15915 (xmlSchemaAttributeGroupPtr) item, ctxt, NULL);
15916 break;
15917 default:
15918 break;
15919 }
15920 }
15921 /*
15922 * Fixup for all other item.
15923 * TODO: Hmm, not sure if starting from complex/simple types,
15924 * all subsequent items will be reached.
15925 */
15926 for (i = 0; i < nbItems; i++) {
15927 item = items[i];
15928 switch (item->type) {
15929 case XML_SCHEMA_TYPE_SIMPLE:
15930 case XML_SCHEMA_TYPE_COMPLEX:
15931 xmlSchemaTypeFixup(item, ctxt, NULL);
15932 break;
15933 default:
15934 break;
15935 }
15936 }
15937 /*
15938 * Check facet values. Note that facets are
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000015939 * hold by simple type components only (and
15940 * by complex types in the current implementation).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015941 */
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000015942 /* OLD:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015943 for (i = 0; i < nbItems; i++) {
15944 item = items[i];
15945 switch (item->type) {
15946 case XML_SCHEMA_TYPE_SIMPLE:
15947 case XML_SCHEMA_TYPE_COMPLEX:
15948 xmlSchemaCheckDefaults(item, ctxt, NULL);
15949 break;
15950 default:
15951 break;
15952 }
15953 }
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000015954 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015955 /*
15956 * Build the content model for complex types.
15957 */
15958 for (i = 0; i < nbItems; i++) {
15959 item = items[i];
15960 switch (item->type) {
15961 case XML_SCHEMA_TYPE_COMPLEX:
15962 xmlSchemaBuildContentModel(item, ctxt, NULL);
15963 break;
15964 default:
15965 break;
15966 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015967 }
15968 /*
15969 * Validate value contraint values.
15970 */
15971 for (i = 0; i < nbItems; i++) {
15972 item = items[i];
15973 switch (item->type) {
15974 case XML_SCHEMA_TYPE_ATTRIBUTE:
15975 xmlSchemaCheckAttrValConstr((xmlSchemaAttributePtr) item, ctxt, NULL);
15976 break;
15977 case XML_SCHEMA_TYPE_ELEMENT:
15978 xmlSchemaCheckElemValConstr((xmlSchemaElementPtr) item, ctxt, NULL);
15979 break;
15980 default:
15981 break;
15982 }
15983 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015984}
15985
15986/**
15987 * xmlSchemaAssembleByLocation:
15988 * @pctxt: a schema parser context
15989 * @vctxt: a schema validation context
15990 * @schema: the existing schema
15991 * @node: the node that fired the assembling
15992 * @nsName: the namespace name of the new schema
15993 * @location: the location of the schema
15994 *
15995 * Expands an existing schema by an additional schema.
15996 *
15997 * Returns 0 if the new schema is correct, a positive error code
15998 * number otherwise and -1 in case of an internal or API error.
15999 */
16000static int
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016001xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
16002 xmlSchemaPtr schema,
16003 xmlNodePtr node,
16004 const xmlChar *nsName,
16005 const xmlChar *location)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016006{
16007 const xmlChar *targetNs, *oldtns;
16008 xmlDocPtr doc, olddoc;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016009 int oldflags, ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016010 xmlNodePtr docElem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016011 xmlSchemaParserCtxtPtr pctxt;
16012
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016013 /*
16014 * This should be used:
16015 * 1. on <import>(s)
16016 * 2. if requested by the validated instance
16017 * 3. if requested via the API
16018 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016019 if ((vctxt == NULL) || (schema == NULL))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016020 return (-1);
16021 /*
16022 * Create a temporary parser context.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016023 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016024 if ((vctxt->pctxt == NULL) &&
16025 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1)) {
16026 xmlSchemaVErr(vctxt, node,
16027 XML_SCHEMAV_INTERNAL,
16028 "Internal error: xmlSchemaAssembleByLocation, "
16029 "failed to create a temp. parser context.\n",
16030 NULL, NULL);
16031 return (-1);
16032 }
16033 pctxt = vctxt->pctxt;
16034 /*
16035 * Set the counter to produce unique names for anonymous items.
16036 */
16037 pctxt->counter = schema->counter;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016038 /*
16039 * Acquire the schema document.
16040 */
16041 ret = xmlSchemaAcquireSchemaDoc(pctxt, schema, node,
16042 nsName, location, &doc, &targetNs, 0);
16043 if (ret != 0) {
16044 if (doc != NULL)
16045 xmlFreeDoc(doc);
16046 } else if (doc != NULL) {
16047 docElem = xmlDocGetRootElement(doc);
16048 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016049 * Create new assemble info.
16050 */
16051 if (pctxt->assemble == NULL) {
16052 pctxt->assemble = xmlSchemaNewAssemble();
16053 if (pctxt->assemble == NULL) {
16054 xmlSchemaVErrMemory(vctxt,
16055 "Memory error: xmlSchemaAssembleByLocation, "
16056 "allocating assemble info", NULL);
16057 xmlFreeDoc(doc);
16058 return (-1);
16059 }
16060 }
16061 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016062 * Save and reset the context & schema.
16063 */
16064 oldflags = schema->flags;
16065 oldtns = schema->targetNamespace;
16066 olddoc = schema->doc;
16067
16068 xmlSchemaClearSchemaDefaults(schema);
16069 schema->targetNamespace = targetNs;
16070 /* schema->nbCurItems = 0; */
16071 pctxt->schema = schema;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016072 pctxt->ctxtType = NULL;
16073 pctxt->parentItem = NULL;
16074
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016075 xmlSchemaParseSchemaDefaults(pctxt, schema, docElem);
16076 xmlSchemaParseSchemaTopLevel(pctxt, schema, docElem->children);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016077 xmlSchemaPostSchemaAssembleFixup(pctxt);
16078 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016079 * Set the counter of items.
16080 */
16081 schema->counter = pctxt->counter;
16082 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016083 * Free the list of assembled components.
16084 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016085 pctxt->assemble->nbItems = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016086 /*
16087 * Restore the context & schema.
16088 */
16089 schema->flags = oldflags;
16090 schema->targetNamespace = oldtns;
16091 schema->doc = olddoc;
16092 ret = pctxt->err;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016093 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016094 return (ret);
16095}
16096
16097/**
16098 * xmlSchemaAssembleByXSIAttr:
16099 * @vctxt: a schema validation context
16100 * @xsiAttr: an xsi attribute
16101 * @noNamespace: whether a schema with no target namespace is exptected
16102 *
16103 * Expands an existing schema by an additional schema using
16104 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
16105 * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
16106 * must be set to 1.
16107 *
16108 * Returns 0 if the new schema is correct, a positive error code
16109 * number otherwise and -1 in case of an internal or API error.
16110 */
16111static int
16112xmlSchemaAssembleByXSIAttr(xmlSchemaValidCtxtPtr vctxt,
16113 xmlAttrPtr xsiAttr,
16114 int noNamespace)
16115{
16116 xmlChar *value;
16117 const xmlChar *cur, *end;
16118 const xmlChar *nsname = NULL, *location;
16119 int count = 0;
16120 int ret = 0;
16121
16122 if (xsiAttr == NULL) {
16123 xmlSchemaVCustomErr(vctxt, XML_SCHEMAV_INTERNAL,
16124 NULL, NULL,
16125 "Internal error: xmlSchemaAssembleByXSIAttr, "
16126 "bad arguments", NULL);
16127 return (-1);
16128 }
16129 /*
16130 * Parse the value; we will assume an even number of values
16131 * to be given (this is how Xerces and XSV work).
16132 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016133 value = xmlNodeGetContent((xmlNodePtr) xsiAttr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016134 cur = value;
16135 do {
16136 if (noNamespace != 1) {
16137 /*
16138 * Get the namespace name.
16139 */
16140 while (IS_BLANK_CH(*cur))
16141 cur++;
16142 end = cur;
16143 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
16144 end++;
16145 if (end == cur)
16146 break;
16147 count++;
16148 nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
16149 cur = end;
16150 }
16151 /*
16152 * Get the URI.
16153 */
16154 while (IS_BLANK_CH(*cur))
16155 cur++;
16156 end = cur;
16157 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
16158 end++;
16159 if (end == cur)
16160 break;
16161 count++;
16162 location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016163 cur = end;
16164 ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016165 xsiAttr->parent, nsname, location);
16166 if (ret == -1) {
16167 xmlSchemaVCustomErr(vctxt,
16168 XML_SCHEMAV_INTERNAL,
16169 (xmlNodePtr) xsiAttr, NULL,
16170 "Internal error: xmlSchemaAssembleByXSIAttr, "
16171 "assembling schemata", NULL);
16172 if (value != NULL)
16173 xmlFree(value);
16174 return (-1);
16175 }
16176 } while (*cur != 0);
16177 if (value != NULL)
16178 xmlFree(value);
16179 return (ret);
16180}
16181
16182/**
16183 * xmlSchemaAssembleByXSIElem:
16184 * @vctxt: a schema validation context
16185 * @elem: an element node possibly holding xsi attributes
16186 * @noNamespace: whether a schema with no target namespace is exptected
16187 *
16188 * Assembles an existing schema by an additional schema using
16189 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attributes
16190 * of the given @elem.
16191 *
16192 * Returns 0 if the new schema is correct, a positive error code
16193 * number otherwise and -1 in case of an internal or API error.
16194 */
16195static int
16196xmlSchemaAssembleByXSIElem(xmlSchemaValidCtxtPtr vctxt,
16197 xmlNodePtr elem)
16198{
16199 int ret = 0, retNs = 0;
16200 xmlAttrPtr attr;
16201
16202 attr = xmlHasNsProp(elem, BAD_CAST "schemaLocation", xmlSchemaInstanceNs);
16203 if (attr != NULL) {
16204 retNs = xmlSchemaAssembleByXSIAttr(vctxt, attr, 0);
16205 if (retNs == -1)
16206 return (-1);
16207 }
16208 attr = xmlHasNsProp(elem, BAD_CAST "noNamespaceSchemaLocation", xmlSchemaInstanceNs);
16209 if (attr != NULL) {
16210 ret = xmlSchemaAssembleByXSIAttr(vctxt, attr, 1);
16211 if (ret == -1)
16212 return (-1);
16213 }
16214 if (retNs != 0)
16215 return (retNs);
16216 else
16217 return (ret);
16218}
16219
Daniel Veillard4255d502002-04-16 15:50:10 +000016220/**
Daniel Veillard4255d502002-04-16 15:50:10 +000016221 * xmlSchemaValidateCallback:
16222 * @ctxt: a schema validation context
16223 * @name: the name of the element detected (might be NULL)
16224 * @type: the type
16225 *
16226 * A transition has been made in the automata associated to an element
16227 * content model
16228 */
16229static void
16230xmlSchemaValidateCallback(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016231 const xmlChar * name ATTRIBUTE_UNUSED,
16232 xmlSchemaTypePtr type, xmlNodePtr node)
16233{
Daniel Veillard4255d502002-04-16 15:50:10 +000016234 xmlSchemaTypePtr oldtype = ctxt->type;
16235 xmlNodePtr oldnode = ctxt->node;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016236
Daniel Veillard4255d502002-04-16 15:50:10 +000016237#ifdef DEBUG_CONTENT
Daniel Veillard8651f532002-04-17 09:06:27 +000016238 xmlGenericError(xmlGenericErrorContext,
16239 "xmlSchemaValidateCallback: %s, %s, %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016240 name, type->name, node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +000016241#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016242 /*
16243 * @type->type will be XML_SCHEMA_TYPE_ANY or XML_SCHEMA_TYPE_ELEMENT.
16244 */
Daniel Veillard4255d502002-04-16 15:50:10 +000016245 ctxt->type = type;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016246 ctxt->node = node;
16247 ctxt->cur = node->children;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016248
16249#ifdef ELEM_INFO_ENABLED
16250 xmlSchemaBeginElement(ctxt);
16251#endif
16252
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016253 /*
16254 * Assemble new schemata using xsi.
16255 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016256 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016257 int ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016258
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016259 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
16260 if (ret == -1) {
16261 xmlSchemaVCustomErr(ctxt,
16262 XML_SCHEMAV_INTERNAL,
16263 ctxt->node, NULL,
16264 "Internal error: xmlSchemaValidateElement, "
16265 "assembling schema by xsi", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016266 goto leave;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016267 }
16268 /*
16269 * NOTE: We won't react on schema parser errors here.
16270 * TODO: But a warning would be nice.
16271 */
16272 }
16273 switch (type->type) {
16274 case XML_SCHEMA_TYPE_ELEMENT: {
16275 /*
16276 * NOTE: The build of the content model
16277 * (xmlSchemaBuildAContentModel) ensures that the element
16278 * declaration (and not a reference to it) will be given.
16279 */
16280 if (((xmlSchemaElementPtr) ctxt->type)->ref != NULL) {
16281 /*
16282 * This is paranoid coding ;-)... it should not
16283 * happen here any more.
16284 */
16285 xmlSchemaVCustomErr(ctxt,
16286 XML_SCHEMAV_INTERNAL,
16287 node, NULL,
16288 "Internal error: xmlSchemaValidateCallback, "
16289 "element declaration 'reference' encountered, "
16290 "but an element declaration was expected",
16291 NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016292 goto leave;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016293 }
16294 xmlSchemaValidateElementByDeclaration(ctxt,
16295 (xmlSchemaElementPtr) type);
16296 break;
16297 }
16298 case XML_SCHEMA_TYPE_ANY:
16299 xmlSchemaValidateElementByWildcard(ctxt, type);
16300 break;
16301 default:
16302 break;
16303 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016304leave:
16305
16306#ifdef ELEM_INFO_ENABLED
16307 xmlSchemaEndElement(ctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016308#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000016309 ctxt->type = oldtype;
16310 ctxt->node = oldnode;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016311}
Daniel Veillard4255d502002-04-16 15:50:10 +000016312
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016313static int
16314xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
16315 const xmlChar *value,
16316 xmlSchemaValPtr *val,
16317 xmlNodePtr node)
16318{
16319 int ret;
16320
16321 ret = xmlValidateQName(value, 1);
16322 if (ret != 0)
16323 return (ret);
16324
16325 {
16326 xmlChar *uri = NULL;
16327 xmlChar *local = NULL;
16328 xmlChar *prefix;
16329
16330 local = xmlSplitQName2(value, &prefix);
16331 if (prefix != NULL) {
16332 xmlNsPtr ns;
16333
16334 /*
16335 * TODO: Make this streamable.
16336 */
16337 if ((node == NULL) || (node->doc == NULL)) {
16338 xmlFree(prefix);
16339 xmlFree(local);
16340 return (3);
16341 }
16342
16343 ns = xmlSearchNs(node->doc, node, prefix);
16344 if (ns == NULL) {
16345 xmlFree(prefix);
16346 xmlFree(local);
16347 return (1);
16348 }
16349 }
16350 if (prefix != NULL) {
16351 if (xmlHashLookup2(vctxt->schema->notaDecl, local, uri) == NULL)
16352 ret = 1;
16353 } else if (xmlHashLookup2(vctxt->schema->notaDecl, value,
16354 NULL) == NULL)
16355 ret = 1;
16356
16357 if ((ret == 0) && (val != NULL)) {
16358 if (prefix != NULL) {
16359 (*val) = xmlSchemaNewNOTATIONValue(BAD_CAST local,
16360 BAD_CAST xmlStrdup(uri));
16361 local = NULL;
16362 } else
16363 (*val) = xmlSchemaNewNOTATIONValue(BAD_CAST xmlStrdup(value),
16364 NULL);
16365 if (*val == NULL)
16366 ret = -1;
16367 }
16368 if (local != NULL)
16369 xmlFree(local);
16370 }
16371
16372 return (ret);
16373}
16374
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016375static xmlSchemaTypePtr
16376xmlSchemaGetSimpleContentType(xmlSchemaTypePtr complexType)
16377{
16378 xmlSchemaTypePtr ret;
16379
16380 if (complexType->type != XML_SCHEMA_TYPE_COMPLEX)
16381 return (NULL);
16382 if (complexType->contentTypeDef != NULL)
16383 return (complexType->contentTypeDef);
16384 /*
16385 * TODO: This is only a workaround until the simple content
16386 * type is computed for complex types with simple content.
16387 */
16388 ret = complexType->baseType;
16389 while (ret != NULL) {
16390 if (IS_SIMPLE_TYPE(ret))
16391 return (ret);
16392 if (ret->builtInType == XML_SCHEMAS_ANYTYPE)
16393 return (NULL);
16394 if ((ret->type == XML_SCHEMA_TYPE_COMPLEX) &&
16395 (ret->contentTypeDef != NULL))
16396 ret = ret->contentTypeDef;
16397 else
16398 ret = ret->baseType;
16399 }
16400 return (ret);
16401}
16402
Daniel Veillard01fa6152004-06-29 17:04:39 +000016403/**
16404 * xmlSchemaValidateSimpleTypeValue:
16405 * @ctxt: a schema validation context
16406 * @value: the value to be validated
16407 * @fireErrors: shall errors be reported?
16408 * @applyFacets: shall facets be applied?
Daniel Veillardc0826a72004-08-10 14:17:33 +000016409 * @normalize: shall the value be normalized?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016410 * @checkNodes: shall the content nodes be checked?
Daniel Veillard01fa6152004-06-29 17:04:39 +000016411 *
16412 * Validates a value by the given type (user derived or built-in).
16413 *
16414 * Returns 0 if the value is valid, a positive error code
16415 * number otherwise and -1 in case of an internal or API error.
Daniel Veillard01fa6152004-06-29 17:04:39 +000016416 */
16417static int
16418xmlSchemaValidateSimpleTypeValue(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016419 xmlSchemaTypePtr type,
16420 const xmlChar *value,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016421 int fireErrors,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016422 int applyFacets,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016423 int normalize,
16424 int checkNodes)
Daniel Veillard01fa6152004-06-29 17:04:39 +000016425{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016426 xmlNodePtr node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000016427 int ret = 0;
16428 xmlChar *normValue = NULL;
16429 int wtsp;
16430
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016431 node = ctxt->node;
16432 /* Save the current whitespace normalization type. */
Daniel Veillardc0826a72004-08-10 14:17:33 +000016433 wtsp = ctxt->valueWS;
16434 /*
16435 * Normalize the value.
16436 */
16437 if (normalize &&
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000016438 (ctxt->valueWS != XML_SCHEMAS_FACET_COLLAPSE)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000016439 int norm = xmlSchemaGetWhiteSpaceFacetValue(type);
16440
16441 if ((norm != -1) && (norm > ctxt->valueWS)) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000016442 if (norm == XML_SCHEMAS_FACET_COLLAPSE)
Daniel Veillardc0826a72004-08-10 14:17:33 +000016443 normValue = xmlSchemaCollapseString(value);
16444 else
16445 normValue = xmlSchemaWhiteSpaceReplace(value);
16446 ctxt->valueWS = norm;
16447 if (normValue != NULL)
16448 value = (const xmlChar *) normValue;
16449 }
16450 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016451 /*
16452 * The nodes of a content must be checked only once,
16453 * this is not working since list types will fire this
16454 * multiple times.
16455 */
16456 if ((checkNodes == 1) && (ctxt->cur != NULL)) {
16457 xmlNodePtr cur = ctxt->cur;
16458
16459 do {
16460 switch (cur->type) {
16461 case XML_TEXT_NODE:
16462 case XML_CDATA_SECTION_NODE:
16463 case XML_PI_NODE:
16464 case XML_COMMENT_NODE:
16465 case XML_XINCLUDE_START:
16466 case XML_XINCLUDE_END:
16467 break;
16468 case XML_ENTITY_REF_NODE:
16469 case XML_ENTITY_NODE:
16470 /* TODO: Scour the entities for illegal nodes. */
16471 TODO break;
16472 case XML_ELEMENT_NODE: {
16473 /* NOTE: Changed to an internal error, since the
16474 * existence of an element node will be already checked in
16475 * xmlSchemaValidateElementBySimpleType and in
16476 * xmlSchemaValidateElementByComplexType.
16477 */
16478 xmlSchemaVCustomErr(ctxt,
16479 XML_SCHEMAV_INTERNAL,
16480 /* XML_SCHEMAS_ERR_INVALIDELEM, */
16481 node, type,
16482 "Element '%s' found in simple type content",
16483 cur->name);
16484 return (XML_SCHEMAV_INTERNAL);
16485 }
16486 case XML_ATTRIBUTE_NODE:
16487 case XML_DOCUMENT_NODE:
16488 case XML_DOCUMENT_TYPE_NODE:
16489 case XML_DOCUMENT_FRAG_NODE:
16490 case XML_NOTATION_NODE:
16491 case XML_HTML_DOCUMENT_NODE:
16492 case XML_DTD_NODE:
16493 case XML_ELEMENT_DECL:
16494 case XML_ATTRIBUTE_DECL:
16495 case XML_ENTITY_DECL:
16496 case XML_NAMESPACE_DECL:
16497#ifdef LIBXML_DOCB_ENABLED
16498 case XML_DOCB_DOCUMENT_NODE:
16499#endif
16500 xmlSchemaVCustomErr(ctxt,
16501 XML_SCHEMAV_INTERNAL,
16502 /* XML_SCHEMAS_ERR_INVALIDELEM, */
16503 node, NULL,
16504 "Node of unexpected type found in simple type content",
16505 NULL);
16506 return (XML_SCHEMAV_INTERNAL);
16507 }
16508 cur = cur->next;
16509 } while (cur != NULL);
16510 }
16511
William M. Brack2f2a6632004-08-20 23:09:47 +000016512 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016513 xmlSchemaTypePtr simpType, anyType;
William M. Brack2f2a6632004-08-20 23:09:47 +000016514
16515 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
16516
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016517 simpType = xmlSchemaGetSimpleContentType(type);
16518 if (simpType == NULL) {
16519 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
16520 "Internal error: xmlSchemaValidateSimpleTypeValue, "
16521 "failed to obtain the simple content type of the complex "
16522 "type '%s'\n",
16523 type->name, NULL);
16524 return (-1);
William M. Brack2f2a6632004-08-20 23:09:47 +000016525 }
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016526 ret = xmlSchemaValidateSimpleTypeValue(ctxt, simpType, value, 1, 0, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000016527 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016528 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000016529 "Internal error: xmlSchemaValidateSimpleTypeValue, "
16530 "validating complex type '%s'\n",
16531 type->name, NULL);
16532 } else if ((ret == 0) && (applyFacets) && (type->facetSet != NULL)) {
16533 /*
16534 * Check facets.
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016535 *
16536 * TODO: This is somehow not nice, since if an error occurs
William M. Brack2f2a6632004-08-20 23:09:47 +000016537 * the reported type will be the complex type; the spec
16538 * wants a simple type to be created on the complex type
16539 * if it has a simple content. For now we have to live with
16540 * it.
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016541 */
16542 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000016543 value, 0, fireErrors);
16544 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016545 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000016546 "Internal error: xmlSchemaValidateSimpleTypeValue, "
16547 "validating facets of complex type '%s'\n",
16548 type->name, NULL);
16549 } else if (ret > 0) {
16550 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
William M. Brack2f2a6632004-08-20 23:09:47 +000016551 if (fireErrors)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016552 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
William M. Brack2f2a6632004-08-20 23:09:47 +000016553 }
16554 }
16555 } else if (type->type == XML_SCHEMA_TYPE_BASIC) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016556
16557 if (ctxt->value != NULL) {
16558 xmlSchemaFreeValue(ctxt->value);
16559 ctxt->value = NULL;
16560 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016561 /*
16562 * STREAM-READ-CHILDREN.
16563 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016564 if ((type->builtInType == XML_SCHEMAS_NOTATION) &&
16565 (ctxt->schema != NULL)) {
16566 /*
16567 * NOTATIONs need to be processed here, since they need
16568 * to lookup in the hashtable of NOTATION declarations.
16569 */
16570 ret = xmlSchemaValidateNotation(ctxt, value, &(ctxt->value), node);
16571 } else
16572 ret = xmlSchemaValPredefTypeNodeNoNorm(type, value, &(ctxt->value), node);
Daniel Veillardc0826a72004-08-10 14:17:33 +000016573 if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016574 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
16575 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
16576 else
16577 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000016578 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016579 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016580 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016581 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016582 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000016583 "validating built-in type '%s'\n", type->name, NULL);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000016584 } else if ((ctxt->value == NULL) &&
16585 (type->builtInType == XML_SCHEMAS_STRING) &&
16586 (ctxt->nodeInfo != NULL) &&
16587 (ctxt->nodeInfo->flags & XML_SCHEMA_ELEM_INFO_VALUE_NEEDED)) {
16588#ifdef IDC_VALUE_SUPPORT
16589 xmlChar *valdup;
16590 /*
16591 * Create a precomputed string value for "string" as well if
16592 * requested.
16593 */
16594 valdup = xmlStrdup(value);
16595 ctxt->value = xmlSchemaNewStringValue(XML_SCHEMAS_STRING,
16596 BAD_CAST valdup);
16597 if ((valdup != NULL) && (ctxt->value == NULL))
16598 xmlFree(valdup);
16599#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +000016600 }
16601 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
16602 /* 1.2.1 if {variety} is ·atomic· then the string must ·match·
16603 * a literal in the ·lexical space· of {base type definition}
16604 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016605 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type->baseType, value, 0, 0, 0, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016606 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016607 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016608 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000016609 "validating atomic simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000016610 type->name, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000016611 } else if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016612 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000016613 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016614 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillardc0826a72004-08-10 14:17:33 +000016615 } else if ((applyFacets) && (type->facetSet != NULL)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016616 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000016617 * Check facets.
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016618 */
16619 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016620 value, 0, fireErrors);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016621 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016622 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016623 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000016624 "validating facets of atomic simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000016625 type->name, NULL);
16626 } else if (ret > 0) {
16627 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000016628 /*
16629 Disabled, since the facet validation already reports errors.
16630 if (fireErrors)
16631 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
16632 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000016633 }
16634 }
16635 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
16636
16637 xmlSchemaTypePtr tmpType;
16638 const xmlChar *cur, *end;
16639 xmlChar *tmp;
Daniel Veillardc0826a72004-08-10 14:17:33 +000016640 unsigned long len = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016641
16642 /* 1.2.2 if {variety} is ·list· then the string must be a sequence
16643 * of white space separated tokens, each of which ·match·es a literal
16644 * in the ·lexical space· of {item type definition}
16645 */
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +000016646
Kasimier T. Buchcikde938cd2005-01-13 12:25:57 +000016647 if (value == NULL)
16648 value = BAD_CAST "";
Daniel Veillardc0826a72004-08-10 14:17:33 +000016649 tmpType = xmlSchemaGetListSimpleTypeItemType(type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016650 cur = value;
16651 do {
16652 while (IS_BLANK_CH(*cur))
16653 cur++;
16654 end = cur;
16655 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
16656 end++;
16657 if (end == cur)
16658 break;
16659 tmp = xmlStrndup(cur, end - cur);
16660 len++;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016661 ret = xmlSchemaValidateSimpleTypeValue(ctxt, tmpType, tmp, 0, 1, 0, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016662 xmlFree(tmp);
Daniel Veillardc0826a72004-08-10 14:17:33 +000016663 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016664 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016665 "Internal error: xmlSchemaValidateSimpleTypeValue, "
16666 "validating an item of list simple type '%s'\n",
16667 type->name, NULL);
16668 break;
16669 } else if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016670 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
Daniel Veillardc0826a72004-08-10 14:17:33 +000016671 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016672 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016673 break;
Daniel Veillardc0826a72004-08-10 14:17:33 +000016674 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000016675 cur = end;
16676 } while (*cur != 0);
16677 /*
16678 * Check facets.
16679 */
16680 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016681 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016682 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000016683 "validating list simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000016684 type->name, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000016685 } else if ((ret == 0) && (applyFacets)) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016686 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016687 value, len, fireErrors);
16688 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016689 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016690 "Internal error: xmlSchemaValidateSimpleTypeValue, "
16691 "validating facets of list simple type '%s'\n",
16692 type->name, NULL);
16693 } else if (ret > 0) {
16694 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016695 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000016696 Disabled, since the facet validation already reports errors.
16697 if (fireErrors)
16698 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016699 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000016700 }
16701
Daniel Veillard01fa6152004-06-29 17:04:39 +000016702 }
16703 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
16704 xmlSchemaTypeLinkPtr memberLink;
16705
16706 /*
16707 * TODO: For all datatypes ·derived· by ·union· whiteSpace does
16708 * not apply directly; however, the normalization behavior of ·union·
16709 * types is controlled by the value of whiteSpace on that one of the
16710 * ·memberTypes· against which the ·union· is successfully validated.
16711 *
16712 * This means that the value is normalized by the first validating
16713 * member type, then the facets of the union type are applied. This
16714 * needs changing of the value!
16715 */
16716
16717 /*
16718 * 1.2.3 if {variety} is ·union· then the string must ·match· a
16719 * literal in the ·lexical space· of at least one member of
16720 * {member type definitions}
16721 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000016722#ifdef DEBUG_UNION_VALIDATION
16723 printf("Union ST : '%s'\n", (const char *) type->name);
16724 printf(" fireErrors : %d\n", fireErrors);
16725 printf(" applyFacets: %d\n", applyFacets);
16726#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +000016727 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
16728 if (memberLink == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016729 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016730 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000016731 "union simple type '%s' has no member types\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000016732 type->name, NULL);
16733 ret = -1;
16734 }
16735 if (ret == 0) {
16736 while (memberLink != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016737 ret = xmlSchemaValidateSimpleTypeValue(ctxt, memberLink->type,
16738 value, 0, 1, 1, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016739 if ((ret <= 0) || (ret == 0))
16740 break;
16741 memberLink = memberLink->next;
16742 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000016743 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016744 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016745 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000016746 "validating members of union simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000016747 type->name, NULL);
16748 } else if (ret > 0) {
16749 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
Daniel Veillardc0826a72004-08-10 14:17:33 +000016750 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016751 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillardc0826a72004-08-10 14:17:33 +000016752 }
16753 }
16754 /*
16755 * Apply facets (pattern, enumeration).
16756 */
16757 if ((ret == 0) && (applyFacets) && (type->facetSet != NULL)) {
16758 int mws;
16759 /*
16760 * The normalization behavior of ·union· types is controlled by
16761 * the value of whiteSpace on that one of the ·memberTypes·
16762 * against which the ·union· is successfully validated.
16763 */
16764 if (normValue != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016765 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016766 "Internal error: xmlSchemaValidateSimpleTypeValue, "
16767 "the value was already normalized for the union simple "
16768 "type '%s'.\n", type->name, NULL);
16769 }
16770 mws = xmlSchemaGetWhiteSpaceFacetValue(memberLink->type);
16771 if (mws > ctxt->valueWS) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000016772 if (mws == XML_SCHEMAS_FACET_COLLAPSE)
Daniel Veillardc0826a72004-08-10 14:17:33 +000016773 normValue = xmlSchemaCollapseString(value);
16774 else
16775 normValue = xmlSchemaWhiteSpaceReplace(value);
16776 if (normValue != NULL)
16777 value = (const xmlChar *) normValue;
16778 }
16779
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016780 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016781 value, 0, fireErrors);
16782 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016783 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016784 "Internal error: xmlSchemaValidateSimpleTypeValue, "
16785 "validating facets of union simple type '%s'\n",
16786 type->name, NULL);
16787 } else if (ret > 0) {
16788 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
16789 /*
16790 if (fireErrors)
16791 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
16792 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000016793 }
16794 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000016795 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000016796 ctxt->valueWS = wtsp;
16797 if (normValue != NULL)
16798 xmlFree(normValue);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016799 return (ret);
16800}
16801
16802/**
16803 * xmlSchemaValidateSimpleTypeElement:
16804 * @ctxt: a schema validation context
16805 * @node: the element node to be validated.
16806 *
16807 * Validate the element against a simple type.
16808 *
16809 * Returns 0 if the element is valid, a positive error code
16810 * number otherwise and -1 in case of an internal or API error.
16811 */
16812static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016813xmlSchemaValidateElementBySimpleType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016814 xmlSchemaTypePtr type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000016815 int isNil,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016816 int valSimpleContent)
Daniel Veillard01fa6152004-06-29 17:04:39 +000016817{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016818 xmlSchemaTypePtr oldtype;
16819 xmlNodePtr node;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016820 xmlAttrPtr attr;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016821 xmlNodePtr cur;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016822 int ret = 0, retval = 0;
16823
Daniel Veillard01fa6152004-06-29 17:04:39 +000016824 if ((ctxt == NULL) || (type == NULL)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016825 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_INTERNAL, NULL, NULL,
16826 "Internal error: xmlSchemaValidateElementBySimpleType, "
16827 "bad arguments", NULL);
16828 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016829 }
16830
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016831 oldtype = ctxt->type;
16832 node = ctxt->node;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016833 /*
16834 * cvc-type: 3.1.2 The element information item must have no element
16835 * information item [children].
16836 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016837 /*
16838 * STREAM: Child nodes are processed.
16839 */
16840 cur = node->children;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016841 while (cur != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016842 /*
16843 * TODO: Entities, will they produce elements as well?
16844 */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016845 if (cur->type == XML_ELEMENT_NODE) {
16846 xmlSchemaVCustomErr(ctxt,
16847 XML_SCHEMAV_CVC_TYPE_3_1_2,
16848 node, type,
16849 "No element content allowed", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016850 ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016851 }
16852 cur = cur->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016853 }
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016854
Daniel Veillard01fa6152004-06-29 17:04:39 +000016855 /*
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016856 * cvc-type 3.1.1:
16857 *
16858 * The attributes of must be empty, excepting those whose namespace name
16859 * is identical to http://www.w3.org/2001/XMLSchema-instance and whose local
16860 * name is one of type, nil, schemaLocation or noNamespaceSchemaLocation.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016861 */
16862 /*
16863 * STREAM: Attribute nodes are processed.
16864 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000016865 attr = node->properties;
16866 while (attr != NULL) {
16867 if ((attr->ns == NULL) ||
16868 (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
16869 ((!xmlStrEqual(attr->name, BAD_CAST "type")) &&
16870 (!xmlStrEqual(attr->name, BAD_CAST "nil")) &&
16871 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation")) &&
16872 (!xmlStrEqual
16873 (attr->name, BAD_CAST "noNamespaceSchemaLocation")))) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016874 xmlSchemaVIllegalAttrErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016875 XML_SCHEMAV_CVC_TYPE_3_1_1, attr);
16876 ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016877 }
16878 attr = attr->next;
16879 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016880 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016881 * This will skip validation if the type is 'anySimpleType' and
16882 * if the value was already validated (e.g. default values).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016883 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000016884 if ((! isNil) &&
16885 (valSimpleContent == 1) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016886 ((type->type != XML_SCHEMA_TYPE_BASIC) ||
16887 (type->builtInType != XML_SCHEMAS_ANYSIMPLETYPE))) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016888 xmlChar *value;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016889
16890 value = xmlNodeGetContent(node);
16891 /*
16892 * NOTE: This call will not check the content nodes, since
16893 * this should be checked here already.
16894 */
16895 retval = xmlSchemaValidateSimpleTypeValue(ctxt, type, value,
16896 1, 1, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000016897 if (value != NULL)
16898 xmlFree(value);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016899 if (retval != 0)
16900 ret = retval;
William M. Brack2f2a6632004-08-20 23:09:47 +000016901 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016902 ctxt->type = oldtype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016903 return (ret);
16904}
Daniel Veillard4255d502002-04-16 15:50:10 +000016905
16906/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016907 * xmlSchemaValQNameAcquire:
16908 * @value: the lexical represantation of the QName value
16909 * @node: the node to search for the corresponding namespace declaration
16910 * @nsName: the resulting namespace name if found
16911 *
16912 * Checks that a value conforms to the lexical space of the type QName;
16913 * if valid, the corresponding namespace name is searched and retured
16914 * as a copy in @nsName. The local name is returned in @localName as
16915 * a copy.
16916 *
16917 * Returns 0 if valid, 1 if not valid by type, 2 if no corresponding
16918 * namespace declaration was found in scope; -1 in case of an internal or
16919 * API error.
16920 */
16921static int
16922xmlSchemaValQNameAcquire(const xmlChar *value, xmlNodePtr node,
16923 xmlChar **nsName, xmlChar **localName)
16924{
16925 int ret;
16926 xmlChar *local = NULL;
16927
16928 if ((nsName == NULL) || (localName == NULL) || (node == NULL))
16929 return (-1);
16930 *nsName = NULL;
16931 *localName = NULL;
16932 ret = xmlValidateQName(value, 1);
16933 if (ret == 0) {
16934 xmlChar *prefix;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016935 xmlNsPtr ns;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016936
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016937 /*
16938 * NOTE: xmlSplitQName2 will return a duplicated
16939 * string.
16940 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016941 local = xmlSplitQName2(value, &prefix);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016942 if (local == NULL)
16943 local = xmlStrdup(value);
16944 ns = xmlSearchNs(node->doc, node, prefix);
16945 /*
16946 * A namespace need not to be found if the prefix is NULL.
16947 */
16948 if (ns != NULL) {
16949 /*
16950 * TODO: Is it necessary to duplicate the URI here?
16951 */
16952 *nsName = xmlStrdup(ns->href);
16953 } else if (prefix != NULL) {
16954 xmlFree(prefix);
16955 if (local != NULL)
16956 xmlFree(local);
16957 return (2);
16958 }
16959 *localName = local;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016960 if (prefix != NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016961 xmlFree(prefix);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016962 } else
16963 return (1);
16964 return (ret);
16965}
16966
16967/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016968 * xmlSchemaHasElemContent:
16969 * @node: the node
16970 *
16971 * Scours the content of the given node for element
16972 * nodes.
16973 *
16974 * Returns 1 if an element node is found,
16975 * 0 otherwise.
16976 */
16977static int
16978xmlSchemaHasElemContent(xmlNodePtr node)
16979{
16980 if (node == NULL)
16981 return (0);
16982 node = node->children;
16983 while (node != NULL) {
16984 if (node->type == XML_ELEMENT_NODE)
16985 return (1);
16986 node = node->next;
16987 }
16988 return (0);
16989}
16990/**
16991 * xmlSchemaHasElemOrCharContent:
16992 * @node: the node
16993 *
16994 * Scours the content of the given node for element
16995 * and character nodes.
16996 *
16997 * Returns 1 if an element or character node is found,
16998 * 0 otherwise.
16999 */
17000static int
17001xmlSchemaHasElemOrCharContent(xmlNodePtr node)
17002{
17003 if (node == NULL)
17004 return (0);
17005 node = node->children;
17006 while (node != NULL) {
17007 switch (node->type) {
17008 case XML_ELEMENT_NODE:
17009 /*
17010 * TODO: Ask Daniel if these are all character nodes.
17011 */
17012 case XML_TEXT_NODE:
17013 case XML_CDATA_SECTION_NODE:
17014 /*
17015 * TODO: How XML_ENTITY_NODEs evaluated?
17016 */
17017 case XML_ENTITY_REF_NODE:
17018 case XML_ENTITY_NODE:
17019 return (1);
17020 break;
17021 default:
17022 break;
17023 }
17024 node = node->next;
17025 }
17026 return (0);
17027}
17028
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017029/************************************************************************
17030 * *
17031 * Identity-constraints (IDC) *
17032 * *
17033 ************************************************************************/
17034
17035#ifdef IDC_ENABLED
17036
17037/**
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017038 * xmlSchemaAugmentIDC:
17039 * @idcDef: the IDC definition
17040 *
17041 * Creates an augmented IDC definition item.
17042 *
17043 * Returns the item, or NULL on internal errors.
17044 */
17045static void
17046xmlSchemaAugmentIDC(xmlSchemaIDCPtr idcDef,
17047 xmlSchemaValidCtxtPtr vctxt)
17048{
17049 xmlSchemaIDCAugPtr aidc;
17050
17051 aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
17052 if (aidc == NULL) {
17053 xmlSchemaVErrMemory(vctxt,
17054 "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
17055 NULL);
17056 return;
17057 }
17058 aidc->bubbleDepth = -1;
17059 aidc->def = idcDef;
17060 aidc->next = NULL;
17061 if (vctxt->aidcs == NULL)
17062 vctxt->aidcs = aidc;
17063 else {
17064 aidc->next = vctxt->aidcs;
17065 vctxt->aidcs = aidc;
17066 }
17067}
17068
17069/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017070 * xmlSchemaIDCNewBinding:
17071 * @idcDef: the IDC definition of this binding
17072 *
17073 * Creates a new IDC binding.
17074 *
17075 * Returns the new binding in case of succeeded, NULL on internal errors.
17076 */
17077static xmlSchemaPSVIIDCBindingPtr
17078xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
17079{
17080 xmlSchemaPSVIIDCBindingPtr ret;
17081
17082 ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
17083 sizeof(xmlSchemaPSVIIDCBinding));
17084 if (ret == NULL) {
17085 xmlSchemaVErrMemory(NULL,
17086 "allocating a PSVI IDC binding item", NULL);
17087 return (NULL);
17088 }
17089 memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
17090 ret->definition = idcDef;
17091 return (ret);
17092}
17093
17094/**
17095 * xmlSchemaIDCStoreNodeTableItem:
17096 * @vctxt: the WXS validation context
17097 * @item: the IDC node table item
17098 *
17099 * The validation context is used to store an IDC node table items.
17100 * They are stored to avoid copying them if IDC node-tables are merged
17101 * with corresponding parent IDC node-tables (bubbling).
17102 *
17103 * Returns 0 if succeeded, -1 on internal errors.
17104 */
17105static int
17106xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
17107 xmlSchemaPSVIIDCNodePtr item)
17108{
17109 /*
17110 * Add to gobal list.
17111 */
17112 if (vctxt->idcNodes == NULL) {
17113 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
17114 xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
17115 if (vctxt->idcNodes == NULL) {
17116 xmlSchemaVErrMemory(vctxt,
17117 "allocating the IDC node table item list", NULL);
17118 return (-1);
17119 }
17120 vctxt->sizeIdcNodes = 20;
17121 } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
17122 vctxt->sizeIdcNodes *= 2;
17123 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
17124 xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
17125 sizeof(xmlSchemaPSVIIDCNodePtr));
17126 if (vctxt->idcNodes == NULL) {
17127 xmlSchemaVErrMemory(vctxt,
17128 "re-allocating the IDC node table item list", NULL);
17129 return (-1);
17130 }
17131 }
17132 vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
17133
17134 return (0);
17135}
17136
17137/**
17138 * xmlSchemaIDCStoreKey:
17139 * @vctxt: the WXS validation context
17140 * @item: the IDC key
17141 *
17142 * The validation context is used to store an IDC key.
17143 *
17144 * Returns 0 if succeeded, -1 on internal errors.
17145 */
17146static int
17147xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
17148 xmlSchemaPSVIIDCKeyPtr key)
17149{
17150 /*
17151 * Add to gobal list.
17152 */
17153 if (vctxt->idcKeys == NULL) {
17154 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
17155 xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
17156 if (vctxt->idcKeys == NULL) {
17157 xmlSchemaVErrMemory(vctxt,
17158 "allocating the IDC key storage list", NULL);
17159 return (-1);
17160 }
17161 vctxt->sizeIdcKeys = 40;
17162 } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
17163 vctxt->sizeIdcKeys *= 2;
17164 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
17165 xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
17166 sizeof(xmlSchemaPSVIIDCKeyPtr));
17167 if (vctxt->idcKeys == NULL) {
17168 xmlSchemaVErrMemory(vctxt,
17169 "re-allocating the IDC key storage list", NULL);
17170 return (-1);
17171 }
17172 }
17173 vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
17174
17175 return (0);
17176}
17177
17178/**
17179 * xmlSchemaIDCAppendNodeTableItem:
17180 * @bind: the IDC binding
17181 * @ntItem: the node-table item
17182 *
17183 * Appends the IDC node-table item to the binding.
17184 *
17185 * Returns 0 on success and -1 on internal errors.
17186 */
17187static int
17188xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
17189 xmlSchemaPSVIIDCNodePtr ntItem)
17190{
17191 if (bind->nodeTable == NULL) {
17192 bind->sizeNodes = 10;
17193 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
17194 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
17195 if (bind->nodeTable == NULL) {
17196 xmlSchemaVErrMemory(NULL,
17197 "allocating an array of IDC node-table items", NULL);
17198 return(-1);
17199 }
17200 } else if (bind->sizeNodes <= bind->nbNodes) {
17201 bind->sizeNodes *= 2;
17202 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
17203 xmlRealloc(bind->nodeTable, bind->sizeNodes *
17204 sizeof(xmlSchemaPSVIIDCNodePtr));
17205 if (bind->nodeTable == NULL) {
17206 xmlSchemaVErrMemory(NULL,
17207 "re-allocating an array of IDC node-table items", NULL);
17208 return(-1);
17209 }
17210 }
17211 bind->nodeTable[bind->nbNodes++] = ntItem;
17212 return(0);
17213}
17214
17215/**
17216 * xmlSchemaIDCAquireBinding:
17217 * @vctxt: the WXS validation context
17218 * @matcher: the IDC matcher
17219 *
17220 * Looks up an PSVI IDC binding, for the IDC definition and
17221 * of the given matcher. If none found, a new one is created
17222 * and added to the IDC table.
17223 *
17224 * Returns an IDC binding or NULL on internal errors.
17225 */
17226static xmlSchemaPSVIIDCBindingPtr
17227xmlSchemaIDCAquireBinding(xmlSchemaValidCtxtPtr vctxt,
17228 xmlSchemaIDCMatcherPtr matcher)
17229{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017230 xmlSchemaNodeInfoPtr info;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017231
17232 info = vctxt->elemInfos[matcher->depth];
17233
17234 if (info->idcTable == NULL) {
17235 info->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
17236 if (info->idcTable == NULL)
17237 return (NULL);
17238 return(info->idcTable);
17239 } else {
17240 xmlSchemaPSVIIDCBindingPtr bind = NULL;
17241
17242 bind = info->idcTable;
17243 do {
17244 if (bind->definition == matcher->aidc->def)
17245 return(bind);
17246 if (bind->next == NULL) {
17247 bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
17248 if (bind->next == NULL)
17249 return (NULL);
17250 return(bind->next);
17251 }
17252 bind = bind->next;
17253 } while (bind != NULL);
17254 }
17255 return (NULL);
17256}
17257
17258/**
17259 * xmlSchemaIDCFreeKey:
17260 * @key: the IDC key
17261 *
17262 * Frees an IDC key together with its compiled value.
17263 */
17264static void
17265xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
17266{
17267 if (key->compValue != NULL)
17268 xmlSchemaFreeValue(key->compValue);
17269 xmlFree(key);
17270}
17271
17272/**
17273 * xmlSchemaIDCFreeBinding:
17274 *
17275 * Frees an IDC binding. Note that the node table-items
17276 * are not freed.
17277 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017278static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017279xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
17280{
17281 if (bind->nodeTable != NULL) {
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017282 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
17283 int i;
17284 /*
17285 * Node-table items for keyrefs are not stored globally
17286 * to the validation context, since they are not bubbled.
17287 * We need to free them here.
17288 */
17289 for (i = 0; i < bind->nbNodes; i++) {
17290 xmlFree(bind->nodeTable[i]->keys);
17291 xmlFree(bind->nodeTable[i]);
17292 }
17293 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017294 xmlFree(bind->nodeTable);
17295 }
17296 xmlFree(bind);
17297}
17298
17299/**
17300 * xmlSchemaIDCFreeIDCTable:
17301 * @bind: the first IDC binding in the list
17302 *
17303 * Frees an IDC table, i.e. all the IDC bindings in the list.
17304 */
17305static void
17306xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
17307{
17308 xmlSchemaPSVIIDCBindingPtr prev;
17309
17310 while (bind != NULL) {
17311 prev = bind;
17312 bind = bind->next;
17313 xmlSchemaIDCFreeBinding(prev);
17314 }
17315}
17316
17317/**
17318 * xmlSchemaIDCFreeMatcherList:
17319 * @matcher: the first IDC matcher in the list
17320 *
17321 * Frees a list of IDC matchers.
17322 */
17323static void
17324xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
17325{
17326 xmlSchemaIDCMatcherPtr next;
17327
17328 while (matcher != NULL) {
17329 next = matcher->next;
17330 if (matcher->keySeqs != NULL) {
17331 int i;
17332 for (i = 0; i < matcher->sizeKeySeqs; i++)
17333 if (matcher->keySeqs[i] != NULL)
17334 xmlFree(matcher->keySeqs[i]);
17335 xmlFree(matcher->keySeqs);
17336 }
17337 xmlFree(matcher);
17338 matcher = next;
17339 }
17340}
17341
17342/**
17343 * xmlSchemaAreValuesEqual:
17344 * @ta: the first type
17345 * @a: the first value
17346 * @tb: the second type
17347 * @b: the second value
17348 *
17349 * Compares two values.
17350 *
17351 * Returns 1 if they are equal, 0 if not and -1 on internal errors.
17352 */
17353static int
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017354xmlSchemaAreValuesEqual(xmlSchemaValidCtxtPtr vctxt,
17355 xmlSchemaTypePtr ta,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017356 xmlSchemaValPtr a,
17357 xmlSchemaTypePtr tb,
17358 xmlSchemaValPtr b)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017359{
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017360 /* Same user derived/built-in derived/built-in primitive types. */
17361 if (ta == tb)
17362 goto compareValue;
17363
17364 /*
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017365 * Note that comparison with anySimpleTypes with be supported for
17366 * string based types as well.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017367 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017368#if 0
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017369 if ((ta->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
17370 (tb->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
17371 return(0);
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017372#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017373
17374 /*
17375 * 4.2.1 equal (data-types)
17376 *
17377 * the ·value space·s of all ·primitive· datatypes are disjoint
17378 * (they do not share any values)
17379 */
17380 if ((ta->builtInType != 0) && (tb->builtInType != 0) &&
17381 (ta->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE) &&
17382 (tb->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
17383 return(0);
17384
17385 if ((ta->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
17386 (ta->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) ||
17387 (tb->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
17388 (tb->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)) {
17389 TODO
17390 return(0);
17391 }
17392 /*
17393 * (1) if a datatype T' is ·derived· by ·restriction· from an atomic datatype
17394 * T then the ·value space· of T' is a subset of the ·value space· of T.
17395 */
17396 /*
17397 * (2) if datatypes T' and T'' are ·derived· by ·restriction· from a common
17398 * atomic ancestor T then the ·value space·s of T' and T'' may overlap.
17399 */
17400
17401 {
17402 xmlSchemaTypePtr pta = ta, ptb = tb;
17403
17404 /* Note that we will compare the primitives here. */
17405 while ((pta->builtInType == 0) ||
17406 ((pta->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE) == 0))
17407 pta = pta->baseType;
17408 while ((ptb->builtInType == 0) ||
17409 ((ptb->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE) == 0))
17410 ptb = ptb->baseType;
17411 if (pta == ptb)
17412 goto compareValue;
17413 return(0);
17414 }
17415compareValue:
17416 {
17417#ifdef IDC_VALUE_SUPPORT
17418 int ret;
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000017419 int aws, bws;
17420
17421 aws = xmlSchemaGetWhiteSpaceFacetValue(ta);
17422 bws = xmlSchemaGetWhiteSpaceFacetValue(tb);
17423
17424 ret = xmlSchemaCompareValuesWhtsp(
17425 a, (xmlSchemaWhitespaceValueType) aws,
17426 b, (xmlSchemaWhitespaceValueType) bws);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017427 if (ret == 0)
17428 return(1);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017429 else if (ret == -2) {
17430 xmlSchemaVErr(vctxt, vctxt->node,
17431 XML_SCHEMAV_INTERNAL,
17432 "Internal error: xmlSchemaAreValuesEqual, "
17433 "failed to compare the values.\n",
17434 NULL, NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017435 return(-1);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017436 } else
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017437 return(0);
17438#else
17439 return (1);
17440#endif
17441 }
17442}
17443
17444/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017445 * xmlSchemaIDCAddStateObject:
17446 * @vctxt: the WXS validation context
17447 * @matcher: the IDC matcher
17448 * @sel: the XPath information
17449 * @parent: the parent "selector" state object if any
17450 * @type: "selector" or "field"
17451 *
17452 * Creates/reuses and activates state objects for the given
17453 * XPath information; if the XPath expression consists of unions,
17454 * multiple state objects are created for every unioned expression.
17455 *
17456 * Returns 0 on success and -1 on internal errors.
17457 */
17458static int
17459xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
17460 xmlSchemaIDCMatcherPtr matcher,
17461 xmlSchemaIDCSelectPtr sel,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017462 int type)
17463{
17464 xmlSchemaIDCStateObjPtr sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017465
17466 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017467 * Reuse the state objects from the pool.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017468 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017469 if (vctxt->xpathStatePool != NULL) {
17470 sto = vctxt->xpathStatePool;
17471 vctxt->xpathStatePool = sto->next;
17472 sto->next = NULL;
17473 } else {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017474 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017475 * Create a new state object.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017476 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017477 sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
17478 if (sto == NULL) {
17479 xmlSchemaVErrMemory(NULL,
17480 "allocating an IDC state object", NULL);
17481 return (-1);
17482 }
17483 memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
17484 }
17485 /*
17486 * Add to global list.
17487 */
17488 if (vctxt->xpathStates != NULL)
17489 sto->next = vctxt->xpathStates;
17490 vctxt->xpathStates = sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017491
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017492 /*
17493 * Free the old xpath validation context.
17494 */
17495 if (sto->xpathCtxt != NULL)
17496 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
17497
17498 /*
17499 * Create a new XPath (pattern) validation context.
17500 */
17501 sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
17502 (xmlPatternPtr) sel->xpathComp);
17503 if (sto->xpathCtxt == NULL) {
17504 xmlSchemaVErr(vctxt, vctxt->node,
17505 XML_SCHEMAV_INTERNAL,
17506 "Internal error: xmlSchemaIDCAddStateObject, "
17507 "failed to create the XPath validation context.\n",
17508 NULL, NULL);
17509 return (-1);
17510 }
17511 sto->type = type;
17512 sto->depth = vctxt->depth;
17513 sto->matcher = matcher;
17514 sto->sel = sel;
17515 sto->nbHistory = 0;
17516
17517#if DEBUG_IDC
17518 xmlGenericError(xmlGenericErrorContext, "IDC: STO push '%s'\n",
17519 sto->sel->xpath);
17520#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017521 return (0);
17522}
17523
17524/**
17525 * xmlSchemaXPathEvaluate:
17526 * @vctxt: the WXS validation context
17527 * @nodeType: the nodeType of the current node
17528 *
17529 * Evaluates all active XPath state objects.
17530 *
17531 * Returns the number of IC "field" state objects which resolved to
17532 * this node, 0 if none resolved and -1 on internal errors.
17533 */
17534static int
17535xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017536 xmlElementType nodeType)
17537{
17538 xmlSchemaIDCStateObjPtr sto, head = NULL, first;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017539 int res, resolved = 0, depth = vctxt->depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017540
17541 if (vctxt->xpathStates == NULL)
17542 return (0);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017543
17544 if (nodeType == XML_ATTRIBUTE_NODE)
17545 depth++;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017546#if DEBUG_IDC
17547 {
17548 xmlChar *str = NULL;
17549 xmlGenericError(xmlGenericErrorContext,
17550 "IDC: EVAL on %s, depth %d, type %d\n",
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017551 xmlSchemaFormatNsUriLocal(&str, vctxt->nodeInfo->namespaceName,
17552 vctxt->nodeInfo->localName), depth, nodeType);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017553 FREE_AND_NULL(str)
17554 }
17555#endif
17556 /*
17557 * Process all active XPath state objects.
17558 */
17559 first = vctxt->xpathStates;
17560 sto = first;
17561 while (sto != head) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017562#if DEBUG_IDC
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017563 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017564 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] selector '%s'\n",
17565 sto->matcher->aidc->def->name, sto->sel->xpath);
17566 else
17567 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] field '%s'\n",
17568 sto->matcher->aidc->def->name, sto->sel->xpath);
17569#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017570
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017571#ifdef IDC_XPATH_SUPPORT
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017572 if (nodeType == XML_ELEMENT_NODE)
17573 res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
17574 vctxt->nodeInfo->localName, vctxt->nodeInfo->namespaceName);
17575 else
17576 res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
17577 vctxt->nodeInfo->localName, vctxt->nodeInfo->namespaceName);
17578
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017579#else
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017580 res = 0;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017581#endif
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017582 if (res == -1) {
17583 xmlSchemaVErr(vctxt, vctxt->node,
17584 XML_SCHEMAV_INTERNAL,
17585 "Internal error: xmlSchemaXPathEvaluate, "
17586 "failed to evaluate a node.\n",
17587 NULL, NULL);
17588 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017589 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017590 if (res == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017591 goto next_sto;
17592 /*
17593 * Full match.
17594 */
17595#if DEBUG_IDC
17596 xmlGenericError(xmlGenericErrorContext, "IDC: "
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017597 "MATCH\n");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017598#endif
17599 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017600 * Register a match in the state object history.
17601 */
17602 if (sto->history == NULL) {
17603 sto->history = (int *) xmlMalloc(5 * sizeof(int));
17604 if (sto->history == NULL) {
17605 xmlSchemaVErrMemory(NULL,
17606 "allocating the state object history", NULL);
17607 return(-1);
17608 }
17609 sto->sizeHistory = 10;
17610 } else if (sto->sizeHistory <= sto->nbHistory) {
17611 sto->sizeHistory *= 2;
17612 sto->history = (int *) xmlRealloc(sto->history,
17613 sto->sizeHistory * sizeof(int));
17614 if (sto->history == NULL) {
17615 xmlSchemaVErrMemory(NULL,
17616 "re-allocating the state object history", NULL);
17617 return(-1);
17618 }
17619 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017620 sto->history[sto->nbHistory++] = depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017621
17622#ifdef DEBUG_IDC
17623 xmlGenericError(xmlGenericErrorContext, "IDC: push match '%d'\n",
17624 vctxt->depth);
17625#endif
17626
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017627 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
17628 xmlSchemaIDCSelectPtr sel;
17629 /*
17630 * Activate state objects for the IDC fields of
17631 * the IDC selector.
17632 */
17633#if DEBUG_IDC
17634 xmlGenericError(xmlGenericErrorContext, "IDC: "
17635 "activating field states\n");
17636#endif
17637 sel = sto->matcher->aidc->def->fields;
17638 while (sel != NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017639 if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
17640 sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
17641 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017642 sel = sel->next;
17643 }
17644 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
17645 /*
17646 * An IDC key node was found.
17647 */
17648#if DEBUG_IDC
17649 xmlGenericError(xmlGenericErrorContext,
17650 "IDC: key found\n");
17651#endif
17652 /*
17653 * Notify that the character value of this node is
17654 * needed.
17655 */
17656 if (resolved == 0)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017657 vctxt->nodeInfo->flags |= XML_SCHEMA_ELEM_INFO_VALUE_NEEDED;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017658 resolved++;
17659 }
17660next_sto:
17661 if (sto->next == NULL) {
17662 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017663 * Evaluate field state objects created on this node as well.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017664 */
17665 head = first;
17666 sto = vctxt->xpathStates;
17667 } else
17668 sto = sto->next;
17669 }
17670 return (resolved);
17671}
17672
17673/**
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017674 * xmlSchemaXPathProcessHistory:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017675 * @vctxt: the WXS validation context
17676 * @type: the simple/complex type of the current node if any at all
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017677 * @compValue: the precompiled value
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017678 *
17679 * Processes and pops the history items of the IDC state objects.
17680 * IDC key-sequences are validated/created on IDC bindings.
17681 *
17682 * Returns 0 on success and -1 on internal errors.
17683 */
17684static int
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017685xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017686 int depth)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017687{
17688 xmlSchemaIDCStateObjPtr sto, nextsto;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017689 int res, matchDepth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017690 xmlSchemaPSVIIDCKeyPtr key = NULL;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017691 xmlSchemaTypePtr type = vctxt->nodeInfo->typeDef;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017692
17693 if (vctxt->xpathStates == NULL)
17694 return (0);
17695 sto = vctxt->xpathStates;
17696
17697#if DEBUG_IDC
17698 {
17699 xmlChar *str = NULL;
17700 xmlGenericError(xmlGenericErrorContext,
17701 "IDC: BACK on %s, depth %d\n",
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017702 xmlSchemaFormatNsUriLocal(&str, vctxt->nodeInfo->namespaceName,
17703 vctxt->nodeInfo->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017704 FREE_AND_NULL(str)
17705 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017706#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017707 /*
17708 * Evaluate the state objects.
17709 */
17710 while (sto != NULL) {
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017711#ifdef IDC_XPATH_SUPPORT
17712 xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
17713 #if DEBUG_IDC
17714 xmlGenericError(xmlGenericErrorContext, "IDC: stream pop '%s'\n",
17715 sto->sel->xpath);
17716 #endif
17717#endif
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017718 if (sto->nbHistory == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017719 goto deregister_check;
17720
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017721 matchDepth = sto->history[sto->nbHistory -1];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017722
17723 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017724 * Only matches at the current depth are of interest.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017725 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017726 if (matchDepth != depth) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017727 sto = sto->next;
17728 continue;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017729 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017730 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
17731 if (! IS_SIMPLE_TYPE(type)) {
17732 /*
17733 * Not qualified if the field resolves to a node of non
17734 * simple type.
17735 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017736 xmlSchemaStreamVCustomErr(vctxt,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017737 XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017738 vctxt->nodeInfo,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017739 (xmlSchemaTypePtr) sto->matcher->aidc->def,
17740 "The field '%s' does evaluate to a node of "
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017741 "non-simple type", sto->sel->xpath, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017742
17743 sto->nbHistory--;
17744 goto deregister_check;
17745 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017746 if ((key == NULL) && (vctxt->nodeInfo->value == NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017747 /*
17748 * Failed to provide the normalized value; maby
17749 * the value was invalid.
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017750 */
17751 xmlSchemaStreamVCustomErr(vctxt,
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000017752 XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017753 vctxt->nodeInfo,
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000017754 (xmlSchemaTypePtr) sto->matcher->aidc->def,
17755 "Warning: No precomputed value available, the value "
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017756 "was either invalid or something strange happend",
17757 NULL, NULL);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000017758 /*
17759 xmlSchemaVErr(vctxt, vctxt->nodeInfo->node,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017760 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017761 "Internal error: xmlSchemaXPathProcessHistory, "
17762 "computed value not available.\n",
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017763 NULL, NULL);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000017764 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017765 sto->nbHistory--;
17766 goto deregister_check;
17767 } else {
17768 xmlSchemaIDCMatcherPtr matcher = sto->matcher;
17769 xmlSchemaPSVIIDCKeyPtr *keySeq;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017770 int pos, idx;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017771
17772 /*
17773 * The key will be anchored on the matcher's list of
17774 * key-sequences. The position in this list is determined
17775 * by the target node's depth relative to the matcher's
17776 * depth of creation (i.e. the depth of the scope element).
17777 */
17778 pos = sto->depth - matcher->depth;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017779 idx = sto->sel->index;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017780
17781 /*
17782 * Create/grow the array of key-sequences.
17783 */
17784 if (matcher->keySeqs == NULL) {
17785 if (pos > 9)
17786 matcher->sizeKeySeqs = pos * 2;
17787 else
17788 matcher->sizeKeySeqs = 10;
17789 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
17790 xmlMalloc(matcher->sizeKeySeqs *
17791 sizeof(xmlSchemaPSVIIDCKeyPtr *));
17792 if (matcher->keySeqs == NULL) {
17793 xmlSchemaVErrMemory(NULL,
17794 "allocating an array of key-sequences",
17795 NULL);
17796 return(-1);
17797 }
17798 memset(matcher->keySeqs, 0,
17799 matcher->sizeKeySeqs *
17800 sizeof(xmlSchemaPSVIIDCKeyPtr *));
17801 } else if (pos >= matcher->sizeKeySeqs) {
17802 int i = matcher->sizeKeySeqs;
17803
17804 matcher->sizeKeySeqs *= 2;
17805 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
17806 xmlRealloc(matcher->keySeqs,
17807 matcher->sizeKeySeqs *
17808 sizeof(xmlSchemaPSVIIDCKeyPtr *));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017809 if (matcher->keySeqs == NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017810 xmlSchemaVErrMemory(NULL,
17811 "reallocating an array of key-sequences",
17812 NULL);
17813 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017814 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017815 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017816 * The array needs to be NULLed.
17817 * TODO: Use memset?
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017818 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017819 for (; i < matcher->sizeKeySeqs; i++)
17820 matcher->keySeqs[i] = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017821 }
17822
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017823 /*
17824 * Get/create the key-sequence.
17825 */
17826 keySeq = matcher->keySeqs[pos];
17827 if (keySeq == NULL) {
17828 goto create_sequence;
17829 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017830 if (keySeq[idx] != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017831 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017832 * cvc-identity-constraint:
17833 * 3 For each node in the ·target node set· all
17834 * of the {fields}, with that node as the context
17835 * node, evaluate to either an empty node-set or
17836 * a node-set with exactly one member, which must
17837 * have a simple type.
17838 *
17839 * The key was already set; report an error.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017840 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017841 xmlSchemaStreamVCustomErr(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017842 XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017843 vctxt->nodeInfo,
17844 (xmlSchemaTypePtr) matcher->aidc->def,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017845 "The field '%s' evaluates to a node-set "
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017846 "with more than one member",
17847 sto->sel->xpath, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017848 sto->nbHistory--;
17849 goto deregister_check;
17850 } else {
17851 goto create_key;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017852 }
17853 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017854
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017855create_sequence:
17856 /*
17857 * Create a key-sequence.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017858 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017859 keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
17860 matcher->aidc->def->nbFields *
17861 sizeof(xmlSchemaPSVIIDCKeyPtr));
17862 if (keySeq == NULL) {
17863 xmlSchemaVErrMemory(NULL,
17864 "allocating an IDC key-sequence", NULL);
17865 return(-1);
17866 }
17867 memset(keySeq, 0, matcher->aidc->def->nbFields *
17868 sizeof(xmlSchemaPSVIIDCKeyPtr));
17869 matcher->keySeqs[pos] = keySeq;
17870create_key:
17871 /*
17872 * Created a key once per node only.
17873 */
17874 if (key == NULL) {
17875 key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
17876 sizeof(xmlSchemaPSVIIDCKey));
17877 if (key == NULL) {
17878 xmlSchemaVErrMemory(NULL,
17879 "allocating a IDC key", NULL);
17880 xmlFree(keySeq);
17881 matcher->keySeqs[pos] = NULL;
17882 return(-1);
17883 }
17884 /*
17885 * Consume the compiled value.
17886 */
17887 key->type = type;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017888 key->compValue = vctxt->nodeInfo->value;
17889 vctxt->nodeInfo->value = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017890 /*
17891 * Store the key in a global list.
17892 */
17893 if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
17894 xmlSchemaIDCFreeKey(key);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017895 return (-1);
17896 }
17897 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017898 keySeq[idx] = key;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017899 }
17900 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017901
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017902 xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
17903 xmlSchemaPSVIIDCBindingPtr bind;
17904 xmlSchemaPSVIIDCNodePtr ntItem;
17905 xmlSchemaIDCMatcherPtr matcher;
17906 xmlSchemaIDCPtr idc;
17907 int pos, i, j, nbKeys;
17908 /*
17909 * Here we have the following scenario:
17910 * An IDC 'selector' state object resolved to a target node,
17911 * during the time this target node was in the
17912 * ancestor-or-self axis, the 'field' state object(s) looked
17913 * out for matching nodes to create a key-sequence for this
17914 * target node. Now we are back to this target node and need
17915 * to put the key-sequence, together with the target node
17916 * itself, into the node-table of the corresponding IDC
17917 * binding.
17918 */
17919 matcher = sto->matcher;
17920 idc = matcher->aidc->def;
17921 nbKeys = idc->nbFields;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017922 pos = depth - matcher->depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017923 /*
17924 * Check if the matcher has any key-sequences at all, plus
17925 * if it has a key-sequence for the current target node.
17926 */
17927 if ((matcher->keySeqs == NULL) ||
17928 (matcher->sizeKeySeqs <= pos)) {
17929 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
17930 goto selector_key_error;
17931 else
17932 goto selector_leave;
17933 }
17934
17935 keySeq = &(matcher->keySeqs[pos]);
17936 if (*keySeq == NULL) {
17937 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
17938 goto selector_key_error;
17939 else
17940 goto selector_leave;
17941 }
17942
17943 for (i = 0; i < nbKeys; i++) {
17944 if ((*keySeq)[i] == NULL) {
17945 /*
17946 * Not qualified, if not all fields did resolve.
17947 */
17948 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
17949 /*
17950 * All fields of a "key" IDC must resolve.
17951 */
17952 goto selector_key_error;
17953 }
17954 goto selector_leave;
17955 }
17956 }
17957 /*
17958 * All fields did resolve.
17959 */
17960
17961 /*
17962 * 4.1 If the {identity-constraint category} is unique(/key),
17963 * then no two members of the ·qualified node set· have
17964 * ·key-sequences· whose members are pairwise equal, as
17965 * defined by Equal in [XML Schemas: Datatypes].
17966 *
17967 * Get the IDC binding from the matcher and check for
17968 * duplicate key-sequences.
17969 */
17970 bind = xmlSchemaIDCAquireBinding(vctxt, matcher);
17971 if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
17972 (bind->nbNodes != 0)) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017973 xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017974
17975 i = 0;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017976 res = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017977 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017978 * Compare the key-sequences, key by key.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017979 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017980 do {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017981 bkeySeq = bind->nodeTable[i]->keys;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017982 for (j = 0; j < nbKeys; j++) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017983 ckey = (*keySeq)[j];
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017984 bkey = bkeySeq[j];
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017985 res = xmlSchemaAreValuesEqual(vctxt, ckey->type,
17986 ckey->compValue, bkey->type, bkey->compValue);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017987 if (res == -1) {
17988 return (-1);
17989 } else if (res == 0)
17990 break;
17991 }
17992 if (res == 1) {
17993 /*
17994 * Duplicate found.
17995 */
17996 break;
17997 }
17998 i++;
17999 } while (i < bind->nbNodes);
18000 if (i != bind->nbNodes) {
18001 /*
18002 * TODO: Try to report the key-sequence.
18003 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000018004 xmlSchemaStreamVCustomErr(vctxt,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018005 XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000018006 vctxt->nodeInfo,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018007 (xmlSchemaTypePtr) idc,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000018008 "Duplicate key-sequence found", NULL, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018009
18010 goto selector_leave;
18011 }
18012 }
18013 /*
18014 * Add a node-table item to the IDC binding.
18015 */
18016 ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
18017 sizeof(xmlSchemaPSVIIDCNode));
18018 if (ntItem == NULL) {
18019 xmlSchemaVErrMemory(NULL,
18020 "allocating an IDC node-table item", NULL);
18021 xmlFree(*keySeq);
18022 *keySeq = NULL;
18023 return(-1);
18024 }
18025 memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
18026
18027 /*
18028 * Store the node-table item on global list.
18029 */
18030 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
18031 if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
18032 xmlFree(ntItem);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018033 xmlFree(*keySeq);
18034 *keySeq = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018035 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018036 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018037 }
18038 /*
18039 * Init the node-table item. Consume the key-sequence.
18040 */
18041 ntItem->node = vctxt->node;
18042 ntItem->keys = *keySeq;
18043 *keySeq = NULL;
18044 if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1) {
18045 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
18046 /*
18047 * Free the item, since keyref items won't be
18048 * put on a global list.
18049 */
18050 xmlFree(ntItem->keys);
18051 xmlFree(ntItem);
18052 }
18053 return (-1);
18054 }
18055
18056 goto selector_leave;
18057selector_key_error:
18058 /*
18059 * 4.2.1 (KEY) The ·target node set· and the
18060 * ·qualified node set· are equal, that is, every
18061 * member of the ·target node set· is also a member
18062 * of the ·qualified node set· and vice versa.
18063 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000018064 xmlSchemaStreamVCustomErr(vctxt,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018065 XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000018066 vctxt->nodeInfo,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018067 (xmlSchemaTypePtr) idc,
18068 "All 'key' fields must evaluate to a node",
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000018069 NULL, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018070selector_leave:
18071 /*
18072 * Free the key-sequence if not added to the IDC table.
18073 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018074 if ((keySeq != NULL) && (*keySeq != NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018075 xmlFree(*keySeq);
18076 *keySeq = NULL;
18077 }
18078 } /* if selector */
18079
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018080 sto->nbHistory--;
18081
18082deregister_check:
18083 /*
18084 * Deregister state objects if they reach the depth of creation.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018085 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018086 if ((sto->nbHistory == 0) && (sto->depth == depth)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018087#if DEBUG_IDC
18088 xmlGenericError(xmlGenericErrorContext, "IDC: STO pop '%s'\n",
18089 sto->sel->xpath);
18090#endif
18091 if (vctxt->xpathStates != sto) {
18092 xmlSchemaVErr(vctxt, vctxt->node,
18093 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018094 "Internal error: xmlSchemaXPathProcessHistory, "
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018095 "The state object to be removed is not the first "
18096 "in the list.\n",
18097 NULL, NULL);
18098 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018099 nextsto = sto->next;
18100 /*
18101 * Unlink from the list of active XPath state objects.
18102 */
18103 vctxt->xpathStates = sto->next;
18104 sto->next = vctxt->xpathStatePool;
18105 /*
18106 * Link it to the pool of reusable state objects.
18107 */
18108 vctxt->xpathStatePool = sto;
18109 sto = nextsto;
18110 } else
18111 sto = sto->next;
18112 } /* while (sto != NULL) */
18113 return (0);
18114}
18115
18116/**
18117 * xmlSchemaIDCRegisterMatchers:
18118 * @vctxt: the WXS validation context
18119 * @elemDecl: the element declaration
18120 *
18121 * Creates helper objects to evaluate IDC selectors/fields
18122 * successively.
18123 *
18124 * Returns 0 if OK and -1 on internal errors.
18125 */
18126static int
18127xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
18128 xmlSchemaElementPtr elemDecl)
18129{
18130 xmlSchemaIDCMatcherPtr matcher, last = NULL;
18131 xmlSchemaIDCPtr idc, refIdc;
18132 xmlSchemaIDCAugPtr aidc;
18133
18134 idc = (xmlSchemaIDCPtr) elemDecl->idcs;
18135 if (idc == NULL)
18136 return (0);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018137
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018138#if DEBUG_IDC
18139 {
18140 xmlChar *str = NULL;
18141 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018142 "IDC: REGISTER on %s, depth %d\n",
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018143 (char *) xmlSchemaFormatNsUriLocal(&str, vctxt->nodeInfo->namespaceName,
18144 vctxt->nodeInfo->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018145 FREE_AND_NULL(str)
18146 }
18147#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018148 if (vctxt->nodeInfo->idcMatchers != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018149 xmlSchemaVErr(vctxt, vctxt->node,
18150 XML_SCHEMAV_INTERNAL,
18151 "Internal error: xmlSchemaIDCRegisterMatchers: "
18152 "The chain of IDC matchers is expected to be empty.\n",
18153 NULL, NULL);
18154 return (-1);
18155 }
18156 do {
18157 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
18158 /*
18159 * Since IDCs bubbles are expensive we need to know the
18160 * depth at which the bubbles should stop; this will be
18161 * the depth of the top-most keyref IDC. If no keyref
18162 * references a key/unique IDC, the bubbleDepth will
18163 * be -1, indicating that no bubbles are needed.
18164 */
18165 refIdc = (xmlSchemaIDCPtr) idc->ref->item;
18166 if (refIdc != NULL) {
18167 /*
18168 * Lookup the augmented IDC.
18169 */
18170 aidc = vctxt->aidcs;
18171 while (aidc != NULL) {
18172 if (aidc->def == refIdc)
18173 break;
18174 aidc = aidc->next;
18175 }
18176 if (aidc == NULL) {
18177 xmlSchemaVErr(vctxt, vctxt->node,
18178 XML_SCHEMAV_INTERNAL,
18179 "Internal error: xmlSchemaIDCRegisterMatchers: "
18180 "Could not find an augmented IDC item for an IDC "
18181 "definition.\n",
18182 NULL, NULL);
18183 return (-1);
18184 }
18185 if ((aidc->bubbleDepth == -1) ||
18186 (vctxt->depth < aidc->bubbleDepth))
18187 aidc->bubbleDepth = vctxt->depth;
18188 }
18189 }
18190 /*
18191 * Lookup the augmented IDC item for the IDC definition.
18192 */
18193 aidc = vctxt->aidcs;
18194 while (aidc != NULL) {
18195 if (aidc->def == idc)
18196 break;
18197 aidc = aidc->next;
18198 }
18199 if (aidc == NULL) {
18200 xmlSchemaVErr(vctxt, vctxt->node,
18201 XML_SCHEMAV_INTERNAL,
18202 "Internal error: xmlSchemaIDCRegisterMatchers: "
18203 "Could not find an augmented IDC item for an IDC definition.\n",
18204 NULL, NULL);
18205 return (-1);
18206 }
18207 /*
18208 * Create an IDC matcher for every IDC definition.
18209 */
18210 matcher = (xmlSchemaIDCMatcherPtr)
18211 xmlMalloc(sizeof(xmlSchemaIDCMatcher));
18212 if (matcher == NULL) {
18213 xmlSchemaVErrMemory(vctxt,
18214 "allocating an IDC matcher", NULL);
18215 return (-1);
18216 }
18217 memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
18218 if (last == NULL)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018219 vctxt->nodeInfo->idcMatchers = matcher;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018220 else
18221 last->next = matcher;
18222 last = matcher;
18223
18224 matcher->type = IDC_MATCHER;
18225 matcher->depth = vctxt->depth;
18226 matcher->aidc = aidc;
18227#if DEBUG_IDC
18228 xmlGenericError(xmlGenericErrorContext, "IDC: register matcher\n");
18229#endif
18230 /*
18231 * Init the automaton state object.
18232 */
18233 if (xmlSchemaIDCAddStateObject(vctxt, matcher,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018234 idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018235 return (-1);
18236
18237 idc = idc->next;
18238 } while (idc != NULL);
18239 return (0);
18240}
18241
18242/**
18243 * xmlSchemaBubbleIDCNodeTables:
18244 * @depth: the current tree depth
18245 *
18246 * Merges IDC bindings of an element at @depth into the corresponding IDC
18247 * bindings of its parent element. If a duplicate note-table entry is found,
18248 * both, the parent node-table entry and child entry are discarded from the
18249 * node-table of the parent.
18250 *
18251 * Returns 0 if OK and -1 on internal errors.
18252 */
18253static int
18254xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
18255{
18256 xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018257 xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL, lastParBind = NULL; /* parent IDC bindings. */
18258 xmlSchemaPSVIIDCNodePtr node, parNode = NULL; /* node-table entries. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018259 xmlSchemaPSVIIDCKeyPtr key, parKey; /* keys of in a key-sequence. */
18260 xmlSchemaIDCAugPtr aidc;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018261 int i, j, k, ret = 0, oldNum, newDupls = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018262 int duplTop;
18263
18264 /*
18265 * The node table has the following sections:
18266 *
18267 * O --> old node-table entries (first)
18268 * O
18269 * + --> new node-table entries
18270 * +
18271 * % --> new duplicate node-table entries
18272 * %
18273 * # --> old duplicate node-table entries
18274 * # (last)
18275 *
18276 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018277 bind = vctxt->nodeInfo->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018278 if (bind == NULL) {
18279 /* Fine, no table, no bubbles. */
18280 return (0);
18281 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018282
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018283 parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
18284 /*
18285 * Walk all bindings; create new or add to existing bindings.
18286 * Remove duplicate key-sequences.
18287 */
18288start_binding:
18289 while (bind != NULL) {
18290 /*
18291 * Skip keyref IDCs.
18292 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018293 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
18294 bind = bind->next;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018295 continue;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018296 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018297 /*
18298 * Check if the key/unique IDC table needs to be bubbled.
18299 */
18300 aidc = vctxt->aidcs;
18301 do {
18302 if (aidc->def == bind->definition) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018303 if (aidc->bubbleDepth >= vctxt->depth) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018304 bind = bind->next;
18305 goto start_binding;
18306 }
18307 break;
18308 }
18309 aidc = aidc->next;
18310 } while (aidc != NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018311
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018312 if (parTable != NULL)
18313 parBind = *parTable;
18314 while (parBind != NULL) {
18315 /*
18316 * Search a matching parent binding for the
18317 * IDC definition.
18318 */
18319 if (parBind->definition == bind->definition) {
18320
18321 /*
18322 * Compare every node-table entry of the child node,
18323 * i.e. the key-sequence within, ...
18324 */
18325 oldNum = parBind->nbNodes; /* Skip newly added items. */
18326 duplTop = oldNum + parBind->nbDupls;
18327
18328 for (i = 0; i < bind->nbNodes; i++) {
18329 node = bind->nodeTable[i];
18330 if (node == NULL)
18331 continue;
18332 /*
18333 * ...with every key-sequence of the parent node, already
18334 * evaluated to be a duplicate key-sequence.
18335 */
18336 if (parBind->nbDupls != 0) {
18337 j = bind->nbNodes + newDupls;
18338 while (j < duplTop) {
18339 parNode = parBind->nodeTable[j];
18340 for (k = 0; k < bind->definition->nbFields; k++) {
18341 key = node->keys[k];
18342 parKey = parNode->keys[k];
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018343 ret = xmlSchemaAreValuesEqual(vctxt, key->type,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018344 key->compValue,
18345 parKey->type, parKey->compValue);
18346 if (ret == -1) {
18347 /* TODO: Internal error */
18348 return(-1);
18349 } else if (ret == 0)
18350 break;
18351
18352 }
18353 if (ret == 1)
18354 /* Duplicate found. */
18355 break;
18356 j++;
18357 }
18358 if (j != duplTop) {
18359 /* Duplicate found. */
18360 continue;
18361 }
18362 }
18363 /*
18364 * ... and with every key-sequence of the parent node.
18365 */
18366 j = 0;
18367 while (j < oldNum) {
18368 parNode = parBind->nodeTable[j];
18369 /*
18370 * Compare key by key.
18371 */
18372 for (k = 0; k < parBind->definition->nbFields; k++) {
18373 key = node->keys[k];
18374 parKey = parNode->keys[k];
18375
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018376 ret = xmlSchemaAreValuesEqual(vctxt, key->type,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018377 key->compValue,
18378 parKey->type, parKey->compValue);
18379 if (ret == -1) {
18380 /* TODO: Internal error */
18381 } else if (ret == 0)
18382 break;
18383
18384 }
18385 if (ret == 1)
18386 /*
18387 * The key-sequences are equal.
18388 */
18389 break;
18390 j++;
18391 }
18392 if (j != oldNum) {
18393 /*
18394 * Handle duplicates.
18395 */
18396 newDupls++;
18397 oldNum--;
18398 parBind->nbNodes--;
18399 /*
18400 * Move last old item to pos of duplicate.
18401 */
18402 parBind->nodeTable[j] =
18403 parBind->nodeTable[oldNum];
18404
18405 if (parBind->nbNodes != oldNum) {
18406 /*
18407 * If new items exist, move last new item to
18408 * last of old items.
18409 */
18410 parBind->nodeTable[oldNum] =
18411 parBind->nodeTable[parBind->nbNodes];
18412 }
18413 /*
18414 * Move duplicate to last pos of new/old items.
18415 */
18416 parBind->nodeTable[parBind->nbNodes] = parNode;
18417
18418 } else {
18419 /*
18420 * Add the node-table entry (node and key-sequence) of
18421 * the child node to the node table of the parent node.
18422 */
18423 if (parBind->nodeTable == NULL) {
18424 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
18425 xmlMalloc(1 * sizeof(xmlSchemaPSVIIDCNodePtr));
18426 if (parBind->nodeTable == NULL) {
18427 xmlSchemaVErrMemory(NULL,
18428 "allocating IDC list of node-table items", NULL);
18429 return(-1);
18430 }
18431 parBind->sizeNodes = 1;
18432 } else if (duplTop >= parBind->sizeNodes) {
18433 parBind->sizeNodes++;
18434 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
18435 xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
18436 sizeof(xmlSchemaPSVIIDCNodePtr));
18437 if (parBind->nodeTable == NULL) {
18438 xmlSchemaVErrMemory(NULL,
18439 "re-allocating IDC list of node-table items", NULL);
18440 return(-1);
18441 }
18442 }
18443
18444 /*
18445 * Move first old duplicate to last position
18446 * of old duplicates +1.
18447 */
18448 if (parBind->nbDupls != 0) {
18449 parBind->nodeTable[duplTop] =
18450 parBind->nodeTable[parBind->nbNodes + newDupls];
18451 }
18452 /*
18453 * Move first new duplicate to last position of
18454 * new duplicates +1.
18455 */
18456 if (newDupls != 0) {
18457 parBind->nodeTable[parBind->nbNodes + newDupls] =
18458 parBind->nodeTable[parBind->nbNodes];
18459 }
18460 /*
18461 * Append the new node-table entry to the 'new node-table
18462 * entries' section.
18463 */
18464 parBind->nodeTable[parBind->nbNodes] = node;
18465 parBind->nbNodes++;
18466 duplTop++;
18467 }
18468 }
18469 parBind->nbDupls += newDupls;
18470 break;
18471 }
18472 if (parBind->next == NULL)
18473 lastParBind = parBind;
18474 parBind = parBind->next;
18475 }
18476 if (parBind == NULL) {
18477 /*
18478 * No binding for the IDC was found: create a new one and
18479 * copy all node-tables.
18480 */
18481 parBind = xmlSchemaIDCNewBinding(bind->definition);
18482 if (parBind == NULL)
18483 return(-1);
18484
18485 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
18486 xmlMalloc(bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
18487 if (parBind->nodeTable == NULL) {
18488 xmlSchemaVErrMemory(NULL,
18489 "allocating an array of IDC node-table items", NULL);
18490 xmlSchemaIDCFreeBinding(parBind);
18491 return(-1);
18492 }
18493 parBind->sizeNodes = bind->nbNodes;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018494 parBind->nbNodes = bind->nbNodes;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018495 memcpy(parBind->nodeTable, bind->nodeTable,
18496 bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018497 if (*parTable == NULL)
18498 *parTable = parBind;
18499 else
18500 lastParBind->next = parBind;
18501 }
18502 bind = bind->next;
18503 }
18504 return (0);
18505}
18506
18507/**
18508 * xmlSchemaCheckCVCIDCKeyRef:
18509 * @vctxt: the WXS validation context
18510 * @elemDecl: the element declaration
18511 *
18512 * Check the cvc-idc-keyref constraints.
18513 */
18514static int
18515xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
18516{
18517 xmlSchemaPSVIIDCBindingPtr refbind, bind;
18518
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018519 refbind = vctxt->nodeInfo->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018520 /*
18521 * Find a keyref.
18522 */
18523 while (refbind != NULL) {
18524 if (refbind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
18525 int i, j, k, res;
18526 xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
18527 xmlSchemaPSVIIDCKeyPtr refKey, key;
18528
18529 /*
18530 * Find the referred key/unique.
18531 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018532 bind = vctxt->nodeInfo->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018533 do {
18534 if ((xmlSchemaIDCPtr) refbind->definition->ref->item ==
18535 bind->definition)
18536 break;
18537 bind = bind->next;
18538 } while (bind != NULL);
18539
18540 /*
18541 * Search for a matching key-sequences.
18542 */
18543 for (i = 0; i < refbind->nbNodes; i++) {
18544 res = 0;
18545 if (bind != NULL) {
18546 refKeys = refbind->nodeTable[i]->keys;
18547 for (j = 0; j < bind->nbNodes; j++) {
18548 keys = bind->nodeTable[j]->keys;
18549 for (k = 0; k < bind->definition->nbFields; k++) {
18550 refKey = refKeys[k];
18551 key = keys[k];
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018552 res = xmlSchemaAreValuesEqual(vctxt,
18553 key->type, key->compValue,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018554 refKey->type, refKey->compValue);
18555 if (res == 0)
18556 break;
18557 else if (res == -1) {
18558 return (-1);
18559 }
18560 }
18561 if (res == 1) {
18562 /*
18563 * Match found.
18564 */
18565 break;
18566 }
18567 }
18568 }
18569 if (res == 0) {
18570 /* TODO: Report the key-sequence. */
18571 xmlSchemaVCustomErr(vctxt,
18572 XML_SCHEMAV_CVC_IDC,
18573 refbind->nodeTable[i]->node,
18574 (xmlSchemaTypePtr) refbind->definition,
18575 "No matching key-sequence found", NULL);
18576 }
18577 }
18578 }
18579 refbind = refbind->next;
18580 }
18581 return (0);
18582}
18583#endif /* IDC_ENABLED */
18584
18585#ifdef ELEM_INFO_ENABLED
18586/**
18587 * xmlSchemaBeginElement:
18588 * @vctxt: the WXS validation context
18589 *
18590 * Just a temporary workaround to simulate streaming validation
18591 * a bit.
18592 */
18593static void
18594xmlSchemaBeginElement(xmlSchemaValidCtxtPtr vctxt)
18595{
18596 vctxt->depth++;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018597 vctxt->nodeInfo = xmlSchemaGetFreshElemInfo(vctxt, vctxt->depth);
18598 vctxt->nodeInfo->node = vctxt->node;
18599 vctxt->nodeInfo->localName = vctxt->node->name;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018600 if (vctxt->node->ns != NULL)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018601 vctxt->nodeInfo->namespaceName = vctxt->node->ns->href;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018602 else
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018603 vctxt->nodeInfo->namespaceName = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018604}
18605
18606/**
18607 * xmlSchemaEndElement:
18608 * @vctxt: the WXS validation context
18609 *
18610 * Just a temporary workaround to simulate streaming validation
18611 * a bit.
18612 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018613static int
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018614xmlSchemaEndElement(xmlSchemaValidCtxtPtr vctxt)
18615{
18616 if (vctxt->depth < 0) {
18617 /* TODO: raise error? */
18618 vctxt->depth--;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018619 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018620 }
18621#ifdef IDC_ENABLED
18622 /*
18623 * Evaluate the history of changes of active state objects.
18624 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018625 if (xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1)
18626 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018627
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018628 if (vctxt->nodeInfo->value != NULL) {
18629 xmlSchemaFreeValue(vctxt->nodeInfo->value);
18630 vctxt->nodeInfo->value = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018631 }
18632 /*
18633 * TODO: 6 The element information item must be ·valid· with respect to each of
18634 * the {identity-constraint definitions} as per Identity-constraint
18635 * Satisfied (§3.11.4).
18636 */
18637 /*
18638 * Validate IDC keyrefs.
18639 */
18640 xmlSchemaCheckCVCIDCKeyRef(vctxt);
18641#endif
18642
18643 /*
18644 * Merge/free the IDC table.
18645 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018646 if (vctxt->nodeInfo->idcTable != NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018647#ifdef IDC_ENABLED
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018648#ifdef DEBUG_IDC
18649 xmlSchemaDebugDumpIDCTable(stdout,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018650 vctxt->nodeInfo->namespaceName,
18651 vctxt->nodeInfo->localName,
18652 vctxt->nodeInfo->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018653#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018654 if (vctxt->depth > 0) {
18655 /*
18656 * Merge the IDC node table with the table of the parent node.
18657 */
18658 xmlSchemaBubbleIDCNodeTables(vctxt);
18659 }
18660 /*
18661 * TODO: Don't free the PSVI IDC tables if they are
18662 * requested for the PSVI.
18663 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018664 xmlSchemaIDCFreeIDCTable(vctxt->nodeInfo->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018665#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018666 vctxt->nodeInfo->idcTable = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018667 }
18668
18669 /*
18670 * Cleanup IDC matchers.
18671 */
18672#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018673 if (vctxt->nodeInfo->idcMatchers != NULL) {
18674 xmlSchemaIDCFreeMatcherList(vctxt->nodeInfo->idcMatchers);
18675 vctxt->nodeInfo->idcMatchers = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018676 }
18677#endif
18678
18679 /*
18680 * Skip further processing if we are on the validation root.
18681 */
18682 if (vctxt->depth == 0) {
18683 vctxt->depth--;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018684 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018685 }
18686
18687 /*
18688 * Reset the bubbleDepth if needed.
18689 */
18690#ifdef IDC_ENABLED
18691 if (vctxt->aidcs != NULL) {
18692 xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
18693 do {
18694 if (aidc->bubbleDepth == vctxt->depth) {
18695 /*
18696 * A bubbleDepth of a key/unique IDC matches the current
18697 * depth, this means that we are leaving the scope of the
18698 * top-most keyref IDC.
18699 */
18700 aidc->bubbleDepth = -1;
18701 }
18702 aidc = aidc->next;
18703 } while (aidc != NULL);
18704 }
18705#endif
18706 vctxt->depth--;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018707 /*
18708 * Clear the current elemInfo.
18709 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018710 if (vctxt->nodeInfo->value != NULL) {
18711 xmlSchemaFreeValue(vctxt->nodeInfo->value);
18712 vctxt->nodeInfo->value = NULL;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018713 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018714 vctxt->nodeInfo = vctxt->elemInfos[vctxt->depth];
18715 vctxt->node = vctxt->nodeInfo->node;
18716
18717 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018718}
18719
18720#endif /* ELEM_INFO_ENABLED */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018721
18722/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018723 * xmlSchemaValidateElementByDeclaration:
Daniel Veillard4255d502002-04-16 15:50:10 +000018724 * @ctxt: a schema validation context
18725 * @node: the top node.
18726 *
18727 * Validate the content of an element type.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018728 * Validation Rule: Element Locally Valid (Element)
Daniel Veillard4255d502002-04-16 15:50:10 +000018729 *
18730 * Returns 0 if the element is schemas valid, a positive error code
18731 * number otherwise and -1 in case of internal or API error.
18732 */
18733static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018734xmlSchemaValidateElementByDeclaration(xmlSchemaValidCtxtPtr ctxt,
18735 xmlSchemaElementPtr elemDecl)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018736{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018737 xmlNodePtr elem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018738 int ret = 0;
18739 xmlSchemaTypePtr actualType = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018740 xmlAttrPtr attr;
18741 xmlChar *attrValue;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018742 int nilled = 0, elemHasContent = -1;
Daniel Veillard3646d642004-06-02 19:19:14 +000018743
18744 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018745 * This one is called by xmlSchemaValidateElementByWildcardInternal,
18746 * xmlSchemaValidateElementByAnyType and xmlSchemaValidateElement.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018747 * Note that @elemDecl will be the declaration and never the
18748 * reference to a declaration.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018749 */
Daniel Veillard3646d642004-06-02 19:19:14 +000018750
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018751 if (ctxt == NULL) {
18752 xmlSchemaVErr(ctxt, NULL, XML_SCHEMAV_INTERNAL,
18753 "Internal error: xmlSchemaValidateElementByDeclaration, "
18754 "bad arguments.\n",
18755 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018756 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000018757 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018758
18759 elem = ctxt->node;
18760
18761 /*
18762 * cvc-elt (3.3.4) : 1
18763 */
18764 if (elemDecl == NULL) {
18765 xmlSchemaVCustomErr(ctxt,
18766 XML_SCHEMAV_CVC_ELT_1,
18767 elem, NULL,
18768 "No matching declaration available", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018769 /*
18770 * Evaluate IDCs even if an error occured.
18771 */
18772#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018773 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018774 return (-1);
18775#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018776 return (ctxt->err);
18777 }
18778 /*
18779 * cvc-elt (3.3.4) : 2
18780 */
18781 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
18782 xmlSchemaVCustomErr(ctxt,
18783 XML_SCHEMAV_CVC_ELT_2,
18784 elem, NULL,
18785 "The element declaration is abstract", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018786 /*
18787 * Evaluate IDCs even if an error occured.
18788 */
18789#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018790 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018791 return (-1);
18792#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018793 return (ctxt->err);
18794 }
18795
18796 /*
18797 * cvc-elt (3.3.4) : 3
18798 * Handle 'xsi:nil'.
18799 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018800
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018801 attr = xmlHasNsProp(elem, BAD_CAST "nil", xmlSchemaInstanceNs);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018802 if (attr != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018803 attrValue = xmlNodeGetContent((xmlNodePtr) attr);
18804 ctxt->node = (xmlNodePtr) attr;
18805 ctxt->cur = attr->children;
18806 ret = xmlSchemaValidateSimpleTypeValue(ctxt,
18807 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
18808 BAD_CAST attrValue, 1, 1, 1, 1);
18809 ctxt->node = elem;
18810 ctxt->type = (xmlSchemaTypePtr) elemDecl;
18811 if (ret < 0) {
18812 xmlSchemaVCustomErr(ctxt,
18813 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018814 (xmlNodePtr) attr, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018815 "Internal error: xmlSchemaValidateElementByDeclaration, "
18816 "validating the attribute 'xsi:nil'", NULL);
18817 if (attrValue != NULL)
18818 xmlFree(attrValue);
18819 return (-1);
18820 }
18821 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018822 /*
18823 * cvc-elt (3.3.4) : 3.1
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018824 */
18825 xmlSchemaVCustomErr(ctxt,
18826 XML_SCHEMAV_CVC_ELT_3_1,
18827 elem, NULL,
18828 "The element is not 'nillable'", NULL);
18829 } else {
18830 if (xmlStrEqual(BAD_CAST attrValue, BAD_CAST "true") ||
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018831 xmlStrEqual(BAD_CAST attrValue, BAD_CAST "1")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018832 ret = 0;
18833 /*
18834 * cvc-elt (3.3.4) : 3.2.1
18835 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018836 elemHasContent = xmlSchemaHasElemOrCharContent(elem);
18837 if (elemHasContent == 1) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018838 xmlSchemaVCustomErr(ctxt,
18839 XML_SCHEMAV_CVC_ELT_3_2_1,
18840 /* XML_SCHEMAS_ERR_NOTEMPTY, */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018841 elem, (xmlSchemaTypePtr) elemDecl,
18842 "The 'nilled' element must have no character or "
18843 "element content", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018844 ret = XML_SCHEMAV_CVC_ELT_3_2_1;
18845 }
18846 /*
18847 * cvc-elt (3.3.4) : 3.2.2
18848 */
18849 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
18850 (elemDecl->value != NULL)) {
18851 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_CVC_ELT_3_2_2,
18852 /* XML_SCHEMAS_ERR_HAVEDEFAULT, */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018853 elem, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018854 "There is a fixed value constraint defined for "
18855 "the 'nilled' element", NULL);
18856 ret = XML_SCHEMAV_CVC_ELT_3_2_2;
18857 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018858 if (ret == 0)
18859 nilled = 1;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018860 }
18861 }
18862 if (attrValue != NULL)
18863 xmlFree(attrValue);
18864 }
18865
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018866
18867 actualType = elemDecl->subtypes;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018868 /*
18869 * cvc-elt (3.3.4) : 4
18870 * Handle 'xsi:type'.
18871 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018872
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018873 attr = xmlHasNsProp(elem, BAD_CAST "type", xmlSchemaInstanceNs);
18874 if (attr != NULL) {
18875 xmlChar *nsName = NULL, *local = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018876
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018877 /*
18878 * TODO: We should report a *warning* that the type was overriden
18879 * by the instance.
18880 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018881
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018882 /*
18883 * cvc-elt (3.3.4) : 4.1
18884 */
18885 attrValue = xmlNodeGetContent((xmlNodePtr) attr);
18886 ret = xmlSchemaValQNameAcquire(attrValue, attr->parent,
18887 &nsName, &local);
18888 if (ret < 0) {
18889 xmlSchemaVCustomErr(ctxt,
18890 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018891 (xmlNodePtr) attr, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018892 "Internal error: xmlSchemaValidateElementByDeclaration, "
18893 "validating the attribute 'xsi:type'", NULL);;
18894 FREE_AND_NULL(attrValue)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018895 FREE_AND_NULL(nsName)
18896 FREE_AND_NULL(local)
18897 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018898 } else if (ret == 1) {
18899 xmlSchemaVSimpleTypeErr(ctxt,
18900 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
18901 (xmlNodePtr) attr, attrValue,
18902 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME));
18903 } else if (ret == 2) {
18904 xmlSchemaVCustomErr(ctxt,
18905 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
18906 (xmlNodePtr) attr,
18907 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
18908 "The QName value '%s' has no "
18909 "corresponding namespace declaration in scope",
18910 attrValue);
18911 } else {
18912 /*
18913 * cvc-elt (3.3.4) : 4.2
18914 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018915 actualType = xmlSchemaGetType(ctxt->schema, local, nsName);
18916 if (actualType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018917 xmlChar *strA = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018918
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018919 xmlSchemaVCustomErr(ctxt,
18920 XML_SCHEMAV_CVC_ELT_4_2,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018921 (xmlNodePtr) attr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018922 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
18923 "The value %s does not resolve to a type "
18924 "definition",
18925 xmlSchemaFormatNsUriLocal(&strA, nsName, local));
18926 FREE_AND_NULL(strA);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018927 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018928 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018929 * URGENT TODO: cvc-elt (3.3.4) : 4.3 (Type Derivation OK)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018930 */
18931 }
18932 }
18933 FREE_AND_NULL(attrValue)
18934 FREE_AND_NULL(nsName)
18935 FREE_AND_NULL(local)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018936 }
18937 /* TODO: Change the handling of missing types according to
18938 * the spec.
18939 */
18940 if (actualType == NULL) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018941 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018942 XML_SCHEMAV_CVC_TYPE_1,
18943 elem, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018944 "The type definition is absent", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018945 /*
18946 * Evaluate IDCs even if an error occured.
18947 */
18948#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018949 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018950 return (-1);
18951#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018952 return (XML_SCHEMAV_CVC_TYPE_1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018953 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018954
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018955 /*
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018956 * Remember the actual-type definition.
18957 */
18958#ifdef ELEM_INFO_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018959 ctxt->nodeInfo->typeDef = actualType;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018960#endif
18961
18962 /*
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018963 * TODO: Since this should be already checked by the content model automaton,
18964 * and we want to get rid of the XML_SCHEMAS_ERR... types, the error code
18965 * has been changed to XML_SCHEMAV_INTERNAL.
18966 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018967 /*
Daniel Veillard4255d502002-04-16 15:50:10 +000018968 if (child == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000018969 if (decl->minOccurs > 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018970 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018971 XML_SCHEMAS_ERR_MISSING,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018972 "Element %s: missing child %s\n",
18973 node->name, decl->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018974 }
18975 return (ctxt->err);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018976 }
18977 */
Daniel Veillard4255d502002-04-16 15:50:10 +000018978 /*
18979 * Verify the element matches
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018980 * TODO, FIXME: Can this still happen here? Isn't this already checked
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018981 * by the content model automaton?
Daniel Veillardc0826a72004-08-10 14:17:33 +000018982 if (!xmlStrEqual(child->name, decl->name)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018983 xmlSchemaVErr3(ctxt, node, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018984 XML_SCHEMAS_ERR_WRONGELEM,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018985 "Element %s: missing child %s found %s\n",
18986 node->name, decl->name, child->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018987 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000018988 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018989 */
18990 if (elemHasContent == -1)
18991 elemHasContent = xmlSchemaHasElemOrCharContent(elem);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018992
18993 /*
18994 * IDC: Register identity-constraint XPath matchers.
18995 */
18996#ifdef IDC_ENABLED
18997 if (elemDecl->idcs != NULL)
18998 xmlSchemaIDCRegisterMatchers(ctxt, elemDecl);
18999 /*
19000 * Evaluate IDCs.
19001 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019002 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019003 return (-1);
19004#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019005 /*
19006 * cvc-elt (3.3.4) : 5
19007 * The appropriate case among the following must be true:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019008 */
Daniel Veillard4255d502002-04-16 15:50:10 +000019009 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019010 * cvc-elt (3.3.4) : 5.1
19011 * If the declaration has a {value constraint},
19012 * the item has neither element nor character [children] and
19013 * clause 3.2 has not applied, then all of the following must be true:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019014 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019015 if ((elemHasContent == 0) && (nilled == 0) && (elemDecl->value != NULL)) {
19016 /*
19017 * cvc-elt (3.3.4) : 5.1.1
19018 * If the ·actual type definition· is a ·local type definition·
19019 * then the canonical lexical representation of the {value constraint}
19020 * value must be a valid default for the ·actual type definition· as
19021 * defined in Element Default Valid (Immediate) (§3.3.6).
19022 */
19023 /*
19024 * NOTE: 'local' above means types aquired by xsi:type.
19025 */
19026 ret = 0;
19027 if (actualType != elemDecl->subtypes) {
19028 xmlSchemaCreatePCtxtOnVCtxt(ctxt);
19029 ret = xmlSchemaCheckCOSValidDefault(ctxt->pctxt, ctxt, actualType,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019030 elemDecl->value, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019031 if (ret < 0) {
19032 xmlSchemaVCustomErr(ctxt,
19033 XML_SCHEMAV_INTERNAL,
19034 elem, actualType,
19035 "Internal error: xmlSchemaValidateElementByDeclaration, "
19036 "validating a default value", NULL);
19037 return (-1);
19038 }
19039 }
19040 /*
19041 * cvc-elt (3.3.4) : 5.1.2
19042 * The element information item with the canonical lexical
19043 * representation of the {value constraint} value used as its
19044 * ·normalized value· must be ·valid· with respect to the
19045 * ·actual type definition· as defined by Element Locally Valid (Type)
19046 * (§3.3.4).
19047 */
19048 /*
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019049 * Disable validation of the simple content, if it was already
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019050 * done above.
19051 */
19052 if (ret == 0) {
19053 if (actualType != elemDecl->subtypes)
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019054 ret = xmlSchemaValidateElementByType(ctxt, actualType, 0, 0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019055 else
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019056 ret = xmlSchemaValidateElementByType(ctxt, actualType, 0, 1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019057 ctxt->node = elem;
19058 if (ret < 0) {
19059 xmlSchemaVCustomErr(ctxt,
19060 XML_SCHEMAV_INTERNAL,
19061 elem, actualType,
19062 "Internal error: xmlSchemaValidateElementByDeclaration, "
19063 "validating against the type", NULL);
19064 return (-1);
19065 }
19066 /*
19067 * PSVI: Create a text node on the instance element.
19068 */
19069 if (ctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
19070 xmlNodePtr textChild;
19071
19072 textChild = xmlNewText(elemDecl->value);
19073 if (textChild == NULL) {
19074 xmlSchemaVCustomErr(ctxt,
19075 XML_SCHEMAV_INTERNAL,
19076 elem, actualType,
19077 "Internal error: xmlSchemaValidateElementByDeclaration, "
19078 "could not create a default text node for the instance",
19079 NULL);
19080 } else
19081 xmlAddChild(elem, textChild);
19082 }
19083 }
19084
19085 } else {
19086 /*
19087 * 5.2.1 The element information item must be ·valid· with respect
19088 * to the ·actual type definition· as defined by Element Locally
19089 * Valid (Type) (§3.3.4).
19090 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019091 ret = xmlSchemaValidateElementByType(ctxt, actualType, nilled, 1);
19092 /*
19093 * Consume the computed value for IDCs, ect. Note that default
19094 * values are not supported yet.
19095 */
19096#ifdef ELEM_INFO_ENABLED
19097 if (ctxt->value != NULL) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019098 ctxt->nodeInfo->value = ctxt->value;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019099 ctxt->value = NULL;
19100 }
19101#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019102 ctxt->node = elem;
19103 if (ret < 0) {
19104 xmlSchemaVCustomErr(ctxt,
19105 XML_SCHEMAV_INTERNAL,
19106 elem, actualType,
19107 "Internal error: xmlSchemaValidateElementByDeclaration, "
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000019108 "calling validation by type", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019109 return (-1);
19110 }
19111 /*
19112 * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
19113 * not applied, all of the following must be true:
19114 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019115 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) && (nilled == 0)) {
19116 /*
19117 * 5.2.2.1 The element information item must have no element
19118 * information item [children].
19119 *
19120 * TODO REDUNDANT: If the actual type exists, the above call to
19121 * xmlSchemaValidateElementByType will already check for element
19122 * nodes.
19123 */
19124 if (xmlSchemaHasElemContent(elem)) {
19125 xmlSchemaVCustomErr(ctxt,
19126 XML_SCHEMAV_CVC_ELT_5_2_2_1,
19127 elem, (xmlSchemaTypePtr) elemDecl,
19128 "Elements in the content are not allowed if it is "
19129 "constrained by a fixed value", NULL);
19130 } else {
19131 /*
19132 * 5.2.2.2 The appropriate case among the following must
19133 * be true:
19134 */
19135
19136 if (actualType->contentType == XML_SCHEMA_CONTENT_MIXED) {
19137 xmlChar *value;
19138 /*
19139 * 5.2.2.2.1 If the {content type} of the ·actual type
19140 * definition· is mixed, then the *initial value* of the
19141 * item must match the canonical lexical representation
19142 * of the {value constraint} value.
19143 *
19144 * ... the *initial value* of an element information
19145 * item is the string composed of, in order, the
19146 * [character code] of each character information item in
19147 * the [children] of that element information item.
19148 */
19149 value = xmlNodeListGetString(elem->doc, elem->children, 1);
19150 if (! xmlStrEqual(BAD_CAST value, elemDecl->value)) {
19151 /*
19152 * TODO: Report invalid & expected values as well.
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019153 * TODO: Implement the canonical stuff.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019154 */
19155 xmlSchemaVCustomErr(ctxt,
19156 XML_SCHEMAV_CVC_ELT_5_2_2_2_1,
19157 elem, (xmlSchemaTypePtr) elemDecl,
19158 "The value does not match the cononical "
19159 "lexical representation of the fixed constraint",
19160 NULL);
19161 }
19162 if (value != NULL)
19163 xmlFree(value);
19164 } else if ((actualType->contentType ==
19165 XML_SCHEMA_CONTENT_SIMPLE) ||
19166 (actualType->contentType == XML_SCHEMA_CONTENT_BASIC)) {
19167 xmlChar *value;
19168
19169 /*
19170 * 5.2.2.2.2 If the {content type} of the ·actual type
19171 * definition· is a simple type definition, then the
19172 * *actual value* of the item must match the canonical
19173 * lexical representation of the {value constraint} value.
19174 */
19175 /*
19176 * TODO: *actual value* is the normalized value, impl. this.
19177 * TODO: Report invalid & expected values as well.
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019178 * TODO: Implement the canonical stuff.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019179 *
19180 */
19181 value = xmlNodeListGetString(elem->doc, elem->children, 1);
19182 if (! xmlStrEqual(BAD_CAST value, elemDecl->value)) {
19183 xmlSchemaVCustomErr(ctxt,
19184 XML_SCHEMAV_CVC_ELT_5_2_2_2_2,
19185 elem, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019186 "The normalized value does not match the canonical "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019187 "lexical representation of the fixed constraint",
19188 NULL);
19189 }
19190 if (value != NULL)
19191 xmlFree(value);
19192
19193 }
19194 /*
19195 * TODO: What if the content type is not 'mixed' or simple?
19196 */
19197
19198 }
19199
19200 }
19201 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019202 /*
19203 * TODO: 7 If the element information item is the ·validation root·, it must be
19204 * ·valid· per Validation Root Valid (ID/IDREF) (§3.3.4).
19205 */
19206
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019207 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000019208}
19209
Daniel Veillard4255d502002-04-16 15:50:10 +000019210/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019211 * xmlSchemaValidateElementByWildcardInternal:
Daniel Veillardc0826a72004-08-10 14:17:33 +000019212 * @ctxt: a schema validation context
19213 * @node: the top node.
19214 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019215 * Represents the recursive portion of xmlSchemaValidateElementByWildcard.
19216 * Not intended to be used by other functions.
Daniel Veillardc0826a72004-08-10 14:17:33 +000019217 *
19218 * Returns 0 if the element is valid, a positive error code
19219 * number otherwise and -1 in case of an internal error.
19220 */
19221static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019222xmlSchemaValidateElementByWildcardInternal(xmlSchemaValidCtxtPtr ctxt,
19223 xmlSchemaWildcardPtr wild,
19224 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +000019225{
19226 const xmlChar *uri;
19227 int ret = 0;
19228 xmlNodePtr child;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019229
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019230 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019231 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
19232 if (ret == -1) {
19233 xmlSchemaVCustomErr(ctxt,
19234 XML_SCHEMAV_INTERNAL,
19235 ctxt->node, NULL,
19236 "Internal error: xmlSchemaValidateElement, "
19237 "assembling schema by xsi", NULL);
19238 return (-1);
19239 }
19240 /*
19241 * NOTE: We won't react on schema parser errors here.
19242 * TODO: But a warning would be nice.
19243 */
19244 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000019245 if (wild->processContents != XML_SCHEMAS_ANY_SKIP) {
19246 xmlSchemaElementPtr decl = NULL;
19247
19248 if (node->ns != NULL)
19249 decl = xmlHashLookup3(ctxt->schema->elemDecl,
19250 node->name, node->ns->href, NULL);
19251 else
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019252 decl = xmlHashLookup3(ctxt->schema->elemDecl, node->name,
19253 NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000019254 if (decl != NULL) {
19255 ctxt->node = node;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019256 ret = xmlSchemaValidateElementByDeclaration(ctxt, decl);
Daniel Veillardc0826a72004-08-10 14:17:33 +000019257 if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000019258 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000019259 "Internal error: xmlSchemaValidateAnyInternal, "
19260 "validating an element in the context of a wildcard.",
19261 NULL, NULL);
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +000019262 }
19263 return (ret);
Daniel Veillardc0826a72004-08-10 14:17:33 +000019264 } else if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
19265 /* TODO: Change to proper error code. */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000019266 xmlSchemaVWildcardErr(ctxt, XML_SCHEMAV_CVC_ELT_1,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019267 node, wild, "No matching global declaration available");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019268 /*
19269 * Evaluate IDCs even if a validation error occured.
19270 */
19271#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019272 if (xmlSchemaXPathEvaluate(ctxt,XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019273 return(-1);
19274#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +000019275 return (ctxt->err);
19276 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019277 /*
19278 * Evaluate IDCs; we need to know if an IDC field resolves to
19279 * such a node. This node has no type definition and will
19280 * definitely result in an IDC validation error if an IDC field
19281 * resolves.
19282 */
19283#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019284 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019285 return(-1);
19286#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +000019287 }
19288 if (node->children != NULL) {
19289 child = node->children;
19290 do {
19291 if (child->type == XML_ELEMENT_NODE) {
19292 if (child->ns != NULL)
19293 uri = child->ns->href;
19294 else
19295 uri = NULL;
19296 if (xmlSchemaMatchesWildcardNs(wild, uri) == 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000019297 /* TODO: error code. */
19298 xmlSchemaVWildcardErr(ctxt, XML_SCHEMAV_ELEMENT_CONTENT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000019299 child, wild,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019300 "The namespace of the element is not allowed");
Daniel Veillardc0826a72004-08-10 14:17:33 +000019301 return (ctxt->err);
19302 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019303#ifdef ELEM_INFO_ENABLED
19304 ctxt->node = child;
19305 xmlSchemaBeginElement(ctxt);
19306#endif
19307 /*
19308 * Recurse over the children.
19309 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019310 ret = xmlSchemaValidateElementByWildcardInternal(ctxt,
19311 wild, child);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019312 if (ret == -1)
19313 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019314#ifdef ELEM_INFO_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019315 if (xmlSchemaEndElement(ctxt) == -1)
19316 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019317#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +000019318 if (ret != 0)
19319 return (ret);
19320 }
19321 child = child->next;
19322 } while (child != NULL);
19323 }
19324 return (0);
19325}
19326
19327/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019328 * xmlSchemaValidateElementContByWildcard:
Daniel Veillardc0826a72004-08-10 14:17:33 +000019329 * @ctxt: a schema validation context
19330 *
19331 * Returns 0 if the element is valid, a positive error code
19332 * number otherwise and -1 in case of an internal or API error.
19333 */
19334static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019335xmlSchemaValidateElementByWildcard(xmlSchemaValidCtxtPtr ctxt,
19336 xmlSchemaTypePtr type)
Daniel Veillardc0826a72004-08-10 14:17:33 +000019337{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019338 if ((type == NULL) || (type->type != XML_SCHEMA_TYPE_ANY) ||
19339 (ctxt->node == NULL)) {
19340 xmlSchemaVCustomErr(ctxt,
19341 XML_SCHEMAV_INTERNAL, ctxt->node, NULL,
19342 "Internal error: xmlSchemaValidateElementByWildcard, "
19343 "bad arguments", NULL);
19344 return (-1);
19345 }
19346 return(xmlSchemaValidateElementByWildcardInternal(ctxt,
19347 type->attributeWildcard, ctxt->node));
Daniel Veillardc0826a72004-08-10 14:17:33 +000019348}
19349
19350/**
William M. Brack2f2a6632004-08-20 23:09:47 +000019351 * xmlSchemaValidateAnyTypeContent:
19352 * @ctxt: a schema validation context
19353 * @node: the current element
19354 *
19355 * This one validates the content of an element of the type
19356 * 'anyType'. The process contents of the wildcard of 'anyType' is "lax",
19357 * thus elements in the subtree will be validated, if a corresponding
19358 * declaration in the schema exists.
19359 *
19360 * Returns 0 if the element and its subtree is valid, a positive error code
19361 * otherwise and -1 in case of an internal or API error.
19362 */
19363static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019364xmlSchemaValidateElementByAnyType(xmlSchemaValidCtxtPtr ctxt,
19365 xmlSchemaTypePtr type)
William M. Brack2f2a6632004-08-20 23:09:47 +000019366{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019367 xmlSchemaTypePtr oldtype;
19368 xmlNodePtr top, cur;
19369 xmlSchemaElementPtr decl;
William M. Brack2f2a6632004-08-20 23:09:47 +000019370 int skipContent, ret;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019371
19372 if ((type == NULL) || (ctxt->node == NULL))
19373 return (-1);
19374
19375 if (ctxt->node->children == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +000019376 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019377
19378 oldtype = ctxt->type;
19379 top = ctxt->node;
19380 /*
19381 * STREAM: Child nodes are processed.
19382 */
19383 cur = ctxt->node->children;
19384 while (cur != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +000019385 skipContent = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019386 if (cur->type == XML_ELEMENT_NODE) {
William M. Brack2f2a6632004-08-20 23:09:47 +000019387 /*
19388 * The process contents of the wildcard is "lax", thus
19389 * we need to validate the element if a declaration
19390 * exists.
19391 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019392 if (cur->ns != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +000019393 decl = xmlHashLookup3(ctxt->schema->elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019394 cur->name, cur->ns->href, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000019395 else
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019396 decl = xmlHashLookup3(ctxt->schema->elemDecl, cur->name, NULL, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000019397 if (decl != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019398 ctxt->node = cur;
19399 ret = xmlSchemaValidateElementByDeclaration(ctxt, decl);
19400 ctxt->node = top;
William M. Brack2f2a6632004-08-20 23:09:47 +000019401 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019402 xmlSchemaVErr(ctxt, cur, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000019403 "Internal error: xmlSchemaValidateAnyTypeContent, "
19404 "validating an element in the context of a wildcard.",
19405 NULL, NULL);
19406 return (ret);
19407 } else if (ret > 0)
19408 return (ret);
19409 skipContent = 1;
19410 }
19411 }
19412 /*
19413 * Browse the full subtree, deep first.
19414 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019415 if ((skipContent == 0) && (cur->children != NULL)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000019416 /* deep first */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019417 cur = cur->children;
19418 } else if ((cur != top) && (cur->next != NULL)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000019419 /* then siblings */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019420 cur = cur->next;
19421 } else if (cur != top) {
William M. Brack2f2a6632004-08-20 23:09:47 +000019422 /* go up to parents->next if needed */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019423 while (cur != top) {
19424 if (cur->parent != NULL)
19425 cur = cur->parent;
19426 if ((cur != top) && (cur->next != NULL)) {
19427 cur = cur->next;
William M. Brack2f2a6632004-08-20 23:09:47 +000019428 break;
19429 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019430 if (cur->parent == NULL) {
19431 cur = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000019432 break;
19433 }
19434 }
19435 /* exit condition */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019436 if (cur == top)
19437 cur = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000019438 } else
19439 break;
19440 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019441 ctxt->type = oldtype;
William M. Brack2f2a6632004-08-20 23:09:47 +000019442 return (0);
19443}
19444
19445/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019446 * xmlSchemaValidateElementByComplexType:
Daniel Veillard4255d502002-04-16 15:50:10 +000019447 * @ctxt: a schema validation context
19448 * @node: the top node.
19449 *
19450 * Validate the content of an element expected to be a complex type type
19451 * xmlschema-1.html#cvc-complex-type
19452 * Validation Rule: Element Locally Valid (Complex Type)
19453 *
19454 * Returns 0 if the element is schemas valid, a positive error code
Daniel Veillard01fa6152004-06-29 17:04:39 +000019455 * number otherwise and -1 in case of internal or API error.
19456 * Note on reported errors: Although it might be nice to report
19457 * the name of the simple/complex type, used to validate the content
19458 * of a node, it is quite unnecessary: for global defined types
19459 * the local name of the element is equal to the NCName of the type,
19460 * for local defined types it makes no sense to output the internal
19461 * computed name of the type. TODO: Instead, one should attach the
19462 * struct of the type involved to the error handler - this allows
19463 * the report of any additional information by the user.
Daniel Veillard4255d502002-04-16 15:50:10 +000019464 */
19465static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019466xmlSchemaValidateElementByComplexType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019467 xmlSchemaTypePtr type,
19468 int valSimpleContent)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019469{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019470 xmlSchemaTypePtr oldtype;
19471 xmlNodePtr elem, child;
Daniel Veillard01fa6152004-06-29 17:04:39 +000019472 int ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +000019473 const xmlChar *nsUri;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019474 xmlSchemaAttrStatePtr attrs = NULL, attrTop = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000019475
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019476 if ((ctxt == NULL) || (type->type != XML_SCHEMA_TYPE_COMPLEX))
19477 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000019478
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019479 oldtype = ctxt->type;
19480 ctxt->type = type;
19481 elem = ctxt->node;
19482
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019483 /*
19484 * Verify the attributes
19485 */
19486 /*
19487 * TODO: This "attrTop" thing is not needed any more.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019488 */
19489 /* NOTE: removed, since a check for abstract is
19490 * done in the cvc-type constraint.
19491 *
19492 *
19493 * if (type->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
19494 * xmlSchemaVComplexTypeErr(ctxt,
19495 * XML_SCHEMAV_CVC_COMPLEX_TYPE_1,
19496 * elem, type,
19497 * "The type definition is abstract");
19498 * return (XML_SCHEMAV_CVC_COMPLEX_TYPE_1);
19499 *}
19500 */
19501
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019502 attrs = ctxt->attr;
19503 attrTop = ctxt->attrTop;
19504 /*
19505 * STREAM: Attribute nodes are processed.
19506 */
19507 xmlSchemaRegisterAttributes(ctxt, elem->properties);
19508 xmlSchemaValidateAttributes(ctxt, elem, type);
19509 if (ctxt->attr != NULL)
19510 xmlSchemaFreeAttributeStates(ctxt->attr);
19511 ctxt->attr = attrs;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019512 ctxt->attrTop = attrTop;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019513
19514 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019515 * TODO: This one creates a regexp even if no content
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019516 * model was defined. Somehow ->contModel is always not NULL
19517 * for complex types, even if they are empty.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019518 * TODO: Check if the obove still occurs.
19519 */
Daniel Veillard4255d502002-04-16 15:50:10 +000019520 switch (type->contentType) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000019521 case XML_SCHEMA_CONTENT_EMPTY: {
19522 /*
19523 * 1 If the {content type} is empty, then the element information
19524 * item has no character or element information item [children].
Daniel Veillard3646d642004-06-02 19:19:14 +000019525 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000019526 /*
19527 * TODO: Is the entity stuff correct?
19528 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019529 if (xmlSchemaHasElemOrCharContent(elem) == 1) {
William M. Brack2f2a6632004-08-20 23:09:47 +000019530 xmlSchemaVComplexTypeErr(ctxt,
19531 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019532 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000019533 "Character or element content is not allowed, "
19534 "because the content type is empty");
Daniel Veillard01fa6152004-06-29 17:04:39 +000019535 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019536 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000019537 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019538 case XML_SCHEMA_CONTENT_MIXED:
19539 if ((type->subtypes == NULL) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019540 (type->baseType->builtInType == XML_SCHEMAS_ANYTYPE)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019541 /*
19542 * The type has 'anyType' as its base and no content model
19543 * is defined -> use 'anyType' as the type to validate
19544 * against.
19545 */
19546 ret = xmlSchemaValidateElementByAnyType(ctxt, type->baseType);
19547 /* TODO: Handle -1. */
19548 break;
19549 }
19550 /* No break on purpose. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000019551 case XML_SCHEMA_CONTENT_ELEMENTS:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019552 {
19553 xmlRegExecCtxtPtr oldregexp = NULL;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019554 xmlChar *values[10];
19555 int terminal, nbval = 10, nbneg;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019556
19557 /*
19558 * Content model check initialization.
19559 */
19560 if (type->contModel != NULL) {
19561 oldregexp = ctxt->regexp;
19562 ctxt->regexp = xmlRegNewExecCtxt(type->contModel,
19563 (xmlRegExecCallbacks)
19564 xmlSchemaValidateCallback, ctxt);
19565#ifdef DEBUG_AUTOMATA
19566 xmlGenericError(xmlGenericErrorContext, "====> %s\n", elem->name);
19567#endif
19568 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019569 /*
19570 * STREAM: Children are processed.
19571 */
19572 child = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000019573 while (child != NULL) {
19574 if (child->type == XML_ELEMENT_NODE) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000019575 if (child->ns != NULL)
19576 nsUri = child->ns->href;
19577 else
19578 nsUri = NULL;
19579 ret = xmlRegExecPushString2(ctxt->regexp,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019580 child->name, nsUri, child);
19581 if (ctxt->err == XML_SCHEMAV_INTERNAL)
19582 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019583 /*
19584 * URGENT TODO: Could we anchor an error report
19585 * here to notify of invalid elements?
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019586 * TODO: Perhaps it would be better to report
19587 * only the first erroneous element and then break.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019588 */
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019589#ifdef DEBUG_AUTOMATA
Daniel Veillard01fa6152004-06-29 17:04:39 +000019590 if (ret < 0)
19591 xmlGenericError(xmlGenericErrorContext,
19592 " --> %s Error\n", child->name);
William M. Bracke7091952004-05-11 15:09:58 +000019593 else
19594 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard01fa6152004-06-29 17:04:39 +000019595 " --> %s\n", child->name);
19596#endif
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019597 if (ret < 0) {
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019598 xmlRegExecErrInfo(ctxt->regexp, NULL, &nbval, &nbneg,
19599 &values[0], &terminal);
19600 xmlSchemaVComplexTypeElemErr(ctxt,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019601 XML_SCHEMAV_ELEMENT_CONTENT,
19602 child, NULL/* type */,
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019603 "This element is not expected",
19604 nbval, nbneg, values);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019605 ret = 1;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019606 /*
19607 * Note that this will skip further validation of the
19608 * content.
19609 */
19610 break;
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019611 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000019612 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) &&
19613 /*
19614 * TODO: Ask Daniel if this are all character nodes.
19615 */
19616 (((child->type == XML_TEXT_NODE) && (!IS_BLANK_NODE(child))) ||
19617 (child->type == XML_ENTITY_NODE) ||
19618 (child->type == XML_ENTITY_REF_NODE) ||
19619 (child->type == XML_CDATA_SECTION_NODE))) {
19620 /*
19621 * 2.3 If the {content type} is element-only, then the
19622 * element information item has no character information
19623 * item [children] other than those whose [character
19624 * code] is defined as a white space in [XML 1.0 (Second
19625 * Edition)].
19626 */
William M. Brack2f2a6632004-08-20 23:09:47 +000019627 xmlSchemaVComplexTypeErr(ctxt,
19628 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019629 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000019630 "Character content is not allowed, "
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019631 "because the content type is element-only");
19632 ret = 1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000019633 break;
19634 }
19635 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019636 }
19637 /*
19638 * Content model check finalization.
19639 */
19640 if (type->contModel != NULL) {
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019641 if (ret == 0) {
19642 xmlRegExecNextValues(ctxt->regexp, &nbval, &nbneg,
19643 &values[0], &terminal);
19644 if (nbval + nbneg != 0) {
19645 /*
19646 * If a next value still exists, I does not have to
19647 * mean that there's an element missing, since it
19648 * might be an optional element. So double check it.
19649 */
19650 ret = xmlRegExecPushString(ctxt->regexp,
19651 NULL, NULL);
19652 if (ret <= 0) {
19653 ret = 1;
19654 xmlSchemaVComplexTypeElemErr(ctxt,
19655 XML_SCHEMAV_ELEMENT_CONTENT,
19656 elem, type, "Missing child element(s)",
19657 nbval, nbneg, values);
19658 } else
19659 ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019660#ifdef DEBUG_AUTOMATA
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019661 xmlGenericError(xmlGenericErrorContext,
19662 "====> %s : %d\n", elem->name, ret);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019663#endif
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019664 }
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019665#ifdef DEBUG_CONTENT
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019666 if (ret == 0)
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019667 xmlGenericError(xmlGenericErrorContext,
19668 "Element %s content check succeeded\n",
19669 elem->name);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019670#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019671 }
19672 xmlRegFreeExecCtxt(ctxt->regexp);
19673 ctxt->regexp = oldregexp;
19674 }
19675 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000019676 break;
19677 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019678 case XML_SCHEMA_CONTENT_BASIC:
19679 /*
19680 * If the simple content was already validated
19681 * (e.g. a default value), the content need not
19682 * to be validated again.
19683 */
19684 if (valSimpleContent == 1) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000019685 xmlChar *value = NULL;
19686 /*
19687 * We hit a complexType with a simpleContent resolving
19688 * to a user derived or built-in simple type.
William M. Brack2f2a6632004-08-20 23:09:47 +000019689 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000019690 /*
19691 * 2.2 If the {content type} is a simple type definition,
19692 * then the element information item has no element
19693 * information item [children], and the ·normalized value·
19694 * of the element information item is ·valid· with respect
19695 * to that simple type definition as defined by String
19696 * Valid (§3.14.4).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019697 */
19698 /*
19699 * STREAM: Children are processed.
19700 */
19701 child = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000019702 while (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019703 /*
19704 * TODO: Could the entity stuff produce elements
19705 * as well?
19706 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000019707 if (child->type == XML_ELEMENT_NODE) {
William M. Brack2f2a6632004-08-20 23:09:47 +000019708 xmlSchemaVComplexTypeErr(ctxt,
19709 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019710 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000019711 "Element content is not allowed, because "
19712 "the content type is a simple type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000019713 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
19714 break;
19715 }
19716 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019717 }
19718 ctxt->node = elem;
19719 ctxt->cur = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000019720 if (ret == 0) {
19721 /*
19722 * Validate the character content against a simple type.
Daniel Veillard3646d642004-06-02 19:19:14 +000019723 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019724 /*
19725 * STREAM: Children are processed.
19726 */
19727 if (elem->children == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000019728 value = NULL;
19729 else
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019730 value = xmlNodeGetContent(elem);
19731 /*
19732 * URGENT TODO: Should facets for the simple type validation be
19733 * disabled, if the derivation of facets for complex types
19734 * is implemented?
19735 */
19736 /*
19737 * NOTE: This call won't check the correct types of the
19738 * content nodes, since this should be done here.
19739 */
19740 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type, value, 1, 1, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000019741 if (ret > 0) {
19742 /*
19743 * NOTE: Although an error will be reported by
19744 * xmlSchemaValidateSimpleTypeValue, the spec wants
19745 * a specific complex type error to be reported
19746 * additionally.
19747 */
19748 xmlSchemaVComplexTypeErr(ctxt,
19749 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019750 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000019751 "The character content is not valid");
Daniel Veillard01fa6152004-06-29 17:04:39 +000019752 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
19753 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019754 xmlSchemaVErr(ctxt, elem, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000019755 "Internal error: xmlSchemaValidateComplexType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000019756 "Element '%s': Error while validating character "
19757 "content against complex type '%s'.\n",
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019758 elem->name, type->name);
19759 if (value != NULL)
19760 xmlFree(value);
19761 ctxt->type = oldtype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000019762 return (-1);
19763 }
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000019764 }
19765#if 0
19766 /*
19767 * REMOVED since handled by xmlSchemaValidateSimpleTypeValue
19768 * already.
19769 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000019770 if (ret == 0) {
19771 /*
19772 * Apply facets of the complexType. Be sure to pass the
19773 * built-in type to xmlSchemaValidateFacetsInternal.
19774 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019775 /* URGENT TODO: I don't know yet if the facets of the simple type
Daniel Veillard01fa6152004-06-29 17:04:39 +000019776 * are used, or if the facets, defined by this complex type,
19777 * are to be used only. This here applies both facet sets.
19778 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000019779
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019780 ret = xmlSchemaValidateFacetsInternal(ctxt,
19781 type, value, 0, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000019782 if (ret > 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +000019783 xmlSchemaVComplexTypeErr(ctxt,
19784 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019785 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000019786 "The character content is not valid");
Daniel Veillard01fa6152004-06-29 17:04:39 +000019787 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
19788 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019789 xmlSchemaVErr(ctxt, elem, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000019790 "Internal error: xmlSchemaValidateComplexType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000019791 "Element '%s': Error while validating character "
19792 "content against complex type '%s'; failed to "
Daniel Veillard01fa6152004-06-29 17:04:39 +000019793 "apply facets.\n",
19794 type->name, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019795 if (value != NULL)
19796 xmlFree(value);
19797 ctxt->type = oldtype;
19798 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000019799 }
19800 }
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000019801#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +000019802 if (value != NULL)
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019803 xmlFree(value);
19804
Daniel Veillard01fa6152004-06-29 17:04:39 +000019805 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019806 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019807 default:
19808 TODO xmlGenericError(xmlGenericErrorContext,
19809 "unimplemented content type %d\n",
19810 type->contentType);
Daniel Veillard4255d502002-04-16 15:50:10 +000019811 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019812 ctxt->type = oldtype;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019813 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000019814}
19815
19816/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019817 * xmlSchemaValidateElementByType:
Daniel Veillard4255d502002-04-16 15:50:10 +000019818 * @ctxt: a schema validation context
19819 * @elem: an element
19820 * @type: the list of type declarations
19821 *
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019822 * Validation Rule: Element Locally Valid (Type).
Daniel Veillard4255d502002-04-16 15:50:10 +000019823 *
19824 * Returns 0 if the element is schemas valid, a positive error code
19825 * number otherwise and -1 in case of internal or API error.
19826 */
19827static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019828xmlSchemaValidateElementByType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019829 xmlSchemaTypePtr type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019830 int isNil,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019831 int valSimpleContent)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019832{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019833 int ret;
Daniel Veillard4255d502002-04-16 15:50:10 +000019834
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019835
19836 if ((ctxt == NULL) || (type == NULL)) {
19837 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_INTERNAL, NULL, NULL,
19838 "Internal error: xmlSchemaValidateElementByType, "
19839 "bad arguments", NULL);
19840 return (-1);
19841 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019842 /*
19843 * This one is called by "xmlSchemaValidateElementByDeclaration".
19844 * It will forward to the proper validation
19845 * procedures for the given type.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019846 */
19847 if (type == NULL) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019848 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019849 XML_SCHEMAV_CVC_TYPE_1,
19850 ctxt->node, NULL,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019851 "The type definition is absent", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019852 return (XML_SCHEMAV_CVC_TYPE_1);
19853 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019854
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019855 if (type->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019856 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019857 XML_SCHEMAV_CVC_TYPE_2,
19858 ctxt->node, type,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019859 "The type definition is abstract", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019860 return (XML_SCHEMAV_CVC_TYPE_2);
19861 }
19862
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019863 switch (type->type) {
19864 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019865 ret = xmlSchemaValidateElementByComplexType(ctxt, type,
19866 valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019867 break;
19868 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019869 ret = xmlSchemaValidateElementBySimpleType(ctxt, type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019870 isNil, valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019871 break;
19872 case XML_SCHEMA_TYPE_BASIC:
19873 if (type->builtInType == XML_SCHEMAS_ANYTYPE)
19874 ret = xmlSchemaValidateElementByAnyType(ctxt, type);
19875 else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019876 ret = xmlSchemaValidateElementBySimpleType(ctxt, type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019877 isNil, valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019878 break;
19879 default:
19880 ret = -1;
19881 break;
19882 }
19883 if (ret == -1)
19884 return (-1);
19885 else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019886 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000019887}
19888
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019889static int
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019890xmlSchemaPostCreateVal(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000019891 xmlSchemaTypePtr type,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019892 const xmlChar *value,
19893 xmlSchemaValPtr *val)
19894{
19895 xmlSchemaTypePtr prim;
19896
19897 if (val == NULL) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000019898 xmlSchemaVErr(vctxt, NULL,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019899 XML_SCHEMAV_INTERNAL,
19900 "Internal error: xmlSchemaPostCreateVal, "
19901 "bad arguments", NULL, NULL);
19902 return (-1);
19903 }
19904 /*
19905 * Only string or anySimpleType values are expected to be post-created.
19906 */
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000019907 prim = xmlSchemaGetPrimitiveType(type);
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019908 if ((prim->builtInType == XML_SCHEMAS_STRING) ||
19909 (prim->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
19910 {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019911 if (value == NULL)
19912 /* TODO: Can this happen at all? */
19913 *val = xmlSchemaNewStringValue(XML_SCHEMAS_STRING,
19914 xmlStrdup(BAD_CAST ""));
19915 else
19916 *val = xmlSchemaNewStringValue(XML_SCHEMAS_STRING, value);
19917 if ((*val) == NULL) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000019918 xmlSchemaVErr(vctxt, NULL,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019919 XML_SCHEMAV_INTERNAL,
19920 "Internal error: xmlSchemaPostCreateVal, "
19921 "failed to create the value", NULL, NULL);
19922 return (-1);
19923 }
19924 return (0);
19925 }
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000019926 xmlSchemaVErr(vctxt, NULL,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019927 XML_SCHEMAV_INTERNAL,
19928 "Internal error: xmlSchemaPostCreateVal, "
19929 "the given type is not supported", NULL, NULL);
19930 return (-1);
19931}
19932
19933static int
19934xmlSchemaCheckAttrLocallyValid(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019935 xmlSchemaAttrStatePtr state)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019936{
19937 xmlChar *value;
19938 const xmlChar *defValue;
19939 xmlSchemaValPtr defVal;
19940 int fixed;
19941 int ret;
19942
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019943 if (vctxt->attrInfo->typeDef == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019944 state->state = XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED;
19945 return (XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED);
19946 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019947 vctxt->node = vctxt->attrInfo->node;
19948 vctxt->cur = vctxt->node->children;
19949 /* STREAM */
19950 value = xmlNodeListGetString(vctxt->node->doc, vctxt->cur, 1);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019951
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019952 /*
19953 * NOTE: This call also checks the content nodes for correct type.
19954 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019955 ret = xmlSchemaValidateSimpleTypeValue(vctxt, vctxt->attrInfo->typeDef,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019956 value, 1, 1, 1, 1);
19957
19958 /*
19959 * Handle 'fixed' attributes.
19960 */
19961 if (ret > 0) {
19962 state->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
19963 /*
19964 * NOTE: Fixed value constraints will be not
19965 * applied if the value was invalid, because:
19966 * 1. The validation process does not return a precomputed
19967 * value.
19968 * 2. An invalid value implies a violation of a fixed
19969 * value constraint.
19970 */
19971 } else if (ret == 0) {
19972 state->state = XML_SCHEMAS_ATTR_CHECKED;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019973 if (xmlSchemaGetEffectiveValueConstraint(
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019974 (xmlSchemaAttributePtr) vctxt->attrInfo->decl,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019975 &fixed, &defValue, &defVal) && (fixed == 1)) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000019976
19977 int ws = xmlSchemaGetWhiteSpaceFacetValue(
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019978 vctxt->nodeInfo->typeDef);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019979 /*
19980 * cvc-au : Attribute Locally Valid (Use)
19981 * For an attribute information item to be·valid·
19982 * with respect to an attribute use its ·normalized
19983 * value· must match the canonical lexical representation
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019984 * of the attribute use's {value constraint} value, if it
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019985 * is present and fixed.
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019986 *
19987 * TODO: Use somehow the *normalized* value and the *canonical*
19988 * fixed value. This here compares the canonical values of both.
19989 * The normalized value of, for example, a float type can differ
19990 * from its canonical representation. This all means that a fixed
19991 * value can only be OK, if it's present in the canonical form in
19992 * the instance.
19993 * NOTE: Since the value for string and anySimpleType is not always
19994 * precomputed during validation, we need to do it now.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019995 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019996 if (vctxt->value == NULL) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000019997 /*
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019998 * Post-create the value.
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000019999 */
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000020000 if (xmlSchemaPostCreateVal(vctxt, vctxt->attrInfo->typeDef,
20001 value, &(vctxt->value)) == -1) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020002 ret = -1;
20003 goto exit;
20004 }
20005 value = NULL;
20006 }
20007 if (defVal == NULL) {
20008 xmlChar *str;
20009
20010 /*
20011 * Post-create the default/fixed value.
20012 */
20013 if (defValue == NULL)
20014 str = xmlStrdup(BAD_CAST "");
20015 else
20016 str = xmlStrdup(defValue);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000020017 if (xmlSchemaPostCreateVal(vctxt, vctxt->attrInfo->typeDef,
20018 str, &defVal) == -1) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020019 ret = -1;
20020 FREE_AND_NULL(str)
20021 goto exit;
20022 }
20023 ((xmlSchemaAttributePtr) vctxt->attrInfo->decl)->defVal = defVal;
20024 }
20025 if (xmlSchemaCompareValuesWhtsp(vctxt->value,
20026 (xmlSchemaWhitespaceValueType) ws,
20027 defVal,
20028 (xmlSchemaWhitespaceValueType) ws) != 0)
20029 {
20030 state->state = XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020031 }
20032 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020033 }
20034exit:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020035 if (value != NULL) {
20036 xmlFree(value);
20037 }
20038 return (ret);
20039}
20040
Daniel Veillard4255d502002-04-16 15:50:10 +000020041/**
20042 * xmlSchemaValidateAttributes:
20043 * @ctxt: a schema validation context
20044 * @elem: an element
Daniel Veillard3646d642004-06-02 19:19:14 +000020045 * @type: the complexType holding the attribute uses
Daniel Veillard4255d502002-04-16 15:50:10 +000020046 *
20047 * Validate the attributes of an element.
20048 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000020049 * 1. Existent, invalid attributes are reported in the form
20050 * "prefix:localName".
20051 * Reason: readability - it is easier to find the actual XML
20052 * representation of the attributes QName.
20053 * 2. Missing attributes are reported in the form
20054 * {"URI", "localName"}.
20055 * This is necessary, since the the prefix need not to be declared
20056 * at all, and thus is not computable.
20057 *
Daniel Veillard4255d502002-04-16 15:50:10 +000020058 * Returns 0 if the element is schemas valid, a positive error code
20059 * number otherwise and -1 in case of internal or API error.
20060 */
20061static int
Daniel Veillard3646d642004-06-02 19:19:14 +000020062xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem, xmlSchemaTypePtr type)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020063{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020064 const xmlChar *nsURI;
Daniel Veillard3646d642004-06-02 19:19:14 +000020065 int ret;
20066 xmlAttrPtr attr; /* An attribute on the element. */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020067 const xmlChar *defValue;
20068 xmlSchemaValPtr defVal;
20069 int fixed;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020070 xmlSchemaAttributeLinkPtr attrUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000020071 xmlSchemaAttributePtr attrDecl;
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000020072 int found;
William M. Brack803812b2004-06-03 02:11:24 +000020073 xmlSchemaAttrStatePtr curState, reqAttrStates = NULL, reqAttrStatesTop = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020074 xmlSchemaAttrStatePtr defAttrStates = NULL, defAttrStatesTop = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020075 xmlNodePtr oldnode;
Daniel Veillard3646d642004-06-02 19:19:14 +000020076#ifdef DEBUG_ATTR_VALIDATION
20077 int redundant = 0;
20078#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000020079
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020080
Daniel Veillardc0826a72004-08-10 14:17:33 +000020081 /*
20082 * Allow all attributes if the type is anyType.
20083 */
20084 if (type == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE))
20085 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020086
20087 oldnode = ctxt->node;
20088 if (type != NULL)
20089 attrUse = type->attributeUses;
Daniel Veillard3646d642004-06-02 19:19:14 +000020090 while (attrUse != NULL) {
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000020091 found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000020092 attrDecl = attrUse->attr;
20093#ifdef DEBUG_ATTR_VALIDATION
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020094 printf("attr use - name: %s\n", xmlSchemaGetAttrName(attrDecl));
Daniel Veillard3646d642004-06-02 19:19:14 +000020095 printf("attr use - use: %d\n", attrDecl->occurs);
20096#endif
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020097 for (curState = ctxt->attr; curState != NULL; curState = curState->next) {
Daniel Veillard3646d642004-06-02 19:19:14 +000020098
20099 if (curState->decl == attrUse->attr) {
20100#ifdef DEBUG_ATTR_VALIDATION
20101 redundant = 1;
20102#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020103 }
Daniel Veillard3646d642004-06-02 19:19:14 +000020104 attr = curState->attr;
20105#ifdef DEBUG_ATTR_VALIDATION
20106 printf("attr - name: %s\n", attr->name);
20107 if (attr->ns != NULL)
20108 printf("attr - ns: %s\n", attr->ns->href);
20109 else
20110 printf("attr - ns: none\n");
20111#endif
20112 /* TODO: Can this ever happen? */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020113 if (attr == NULL)
20114 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000020115 if (attrDecl->ref != NULL) {
20116 if (!xmlStrEqual(attr->name, attrDecl->ref))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020117 continue;
20118 if (attr->ns != NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000020119 if ((attrDecl->refNs == NULL) ||
20120 (!xmlStrEqual(attr->ns->href, attrDecl->refNs)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020121 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000020122 } else if (attrDecl->refNs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020123 continue;
20124 }
20125 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000020126 if (!xmlStrEqual(attr->name, attrDecl->name))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020127 continue;
20128 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +000020129 * handle the namespaces checks here
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020130 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000020131 if (attr->ns == NULL) {
20132 /*
William M. Bracke7091952004-05-11 15:09:58 +000020133 * accept an unqualified attribute only if the target
20134 * namespace of the declaration is absent.
Daniel Veillardbe9c6322003-11-22 20:37:51 +000020135 */
Daniel Veillard3646d642004-06-02 19:19:14 +000020136 if (attrDecl->targetNamespace != NULL)
William M. Bracke7091952004-05-11 15:09:58 +000020137 /*
20138 * This check was removed, since the target namespace
20139 * was evaluated during parsing and already took
20140 * "attributeFormDefault" into account.
20141 */
20142 /* ((attributes->flags & XML_SCHEMAS_ATTR_NSDEFAULT) == 0)) */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000020143 continue;
20144 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000020145 if (attrDecl->targetNamespace == NULL)
Daniel Veillardbe9c6322003-11-22 20:37:51 +000020146 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000020147 if (!xmlStrEqual(attrDecl->targetNamespace,
Daniel Veillardbe9c6322003-11-22 20:37:51 +000020148 attr->ns->href))
20149 continue;
20150 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020151 }
Daniel Veillard3646d642004-06-02 19:19:14 +000020152#ifdef DEBUG_ATTR_VALIDATION
20153 printf("found\n");
20154#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020155 found = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +000020156 curState->decl = attrDecl;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020157 curState->state = XML_SCHEMAS_ATTR_VALIDATE_VALUE;
20158 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020159 ret = xmlSchemaCheckAttrLocallyValid(ctxt, attrDecl, curState, attr);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020160 */
Daniel Veillard3646d642004-06-02 19:19:14 +000020161 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020162 if (!found) {
20163 if (attrDecl->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
20164 xmlSchemaAttrStatePtr tmp;
20165
Daniel Veillard3646d642004-06-02 19:19:14 +000020166#ifdef DEBUG_ATTR_VALIDATION
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020167 printf("required attr not found\n");
Daniel Veillard3646d642004-06-02 19:19:14 +000020168#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020169 /*
20170 * Add a new dummy attribute state.
20171 */
20172 tmp = (xmlSchemaAttrStatePtr) xmlMalloc(sizeof(xmlSchemaAttrState));
20173 if (tmp == NULL) {
20174 xmlSchemaVErrMemory(ctxt, "registering required attributes", NULL);
20175 ctxt->node = oldnode;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020176 goto fatal_exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020177 }
20178 tmp->attr = NULL;
20179 tmp->state = XML_SCHEMAS_ATTR_MISSING;
20180 tmp->decl = attrDecl;
20181 tmp->next = NULL;
20182
20183 if (reqAttrStates == NULL) {
20184 reqAttrStates = tmp;
20185 reqAttrStatesTop = tmp;
20186 } else {
20187 reqAttrStatesTop->next = tmp;
20188 reqAttrStatesTop = tmp;
20189 }
20190 } else if ((attrDecl->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
20191 (xmlSchemaGetEffectiveValueConstraint(attrDecl,
20192 &fixed, &defValue, &defVal))) {
20193 xmlSchemaAttrStatePtr tmp;
20194 /*
20195 * Handle non existent default/fixed attributes.
20196 */
20197 tmp = (xmlSchemaAttrStatePtr)
20198 xmlMalloc(sizeof(xmlSchemaAttrState));
20199 if (tmp == NULL) {
20200 xmlSchemaVErrMemory(ctxt,
20201 "registering schema specified attributes", NULL);
20202 ctxt->node = oldnode;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020203 goto fatal_exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020204 }
20205 tmp->attr = NULL;
20206 tmp->state = XML_SCHEMAS_ATTR_DEFAULT;
20207 tmp->decl = attrDecl;
20208 tmp->value = defValue;
20209 tmp->next = NULL;
20210
20211 if (defAttrStates == NULL) {
20212 defAttrStates = tmp;
20213 defAttrStates = tmp;
20214 } else {
20215 defAttrStates->next = tmp;
20216 defAttrStatesTop = tmp;
20217 }
20218 }
Daniel Veillard3646d642004-06-02 19:19:14 +000020219 }
20220 attrUse = attrUse->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000020221 }
Daniel Veillard3646d642004-06-02 19:19:14 +000020222 /*
20223 * Add required attributes to the attribute states of the context.
20224 */
20225 if (reqAttrStates != NULL) {
20226 if (ctxt->attr == NULL) {
20227 ctxt->attr = reqAttrStates;
20228 } else {
20229 ctxt->attrTop->next = reqAttrStates;
20230 }
20231 ctxt->attrTop = reqAttrStatesTop;
Daniel Veillardc0826a72004-08-10 14:17:33 +000020232 }
Daniel Veillard3646d642004-06-02 19:19:14 +000020233 /*
20234 * Process wildcards.
20235 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020236
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020237 if ((type != NULL) && (type->attributeWildcard != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000020238#ifdef DEBUG_ATTR_VALIDATION
20239 xmlSchemaWildcardNsPtr ns;
20240 printf("matching wildcard: [%d] of complexType: %s\n", type->attributeWildcard, type->name);
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000020241 if (type->attributeWildcard->processContents ==
20242 XML_SCHEMAS_ANY_LAX)
20243 printf("processContents: lax\n");
20244 else if (type->attributeWildcard->processContents ==
20245 XML_SCHEMAS_ANY_STRICT)
20246 printf("processContents: strict\n");
20247 else
20248 printf("processContents: skip\n");
Daniel Veillard3646d642004-06-02 19:19:14 +000020249 if (type->attributeWildcard->any)
20250 printf("type: any\n");
20251 else if (type->attributeWildcard->negNsSet != NULL) {
20252 printf("type: negated\n");
20253 if (type->attributeWildcard->negNsSet->value == NULL)
20254 printf("ns: (absent)\n");
20255 else
20256 printf("ns: %s\n", type->attributeWildcard->negNsSet->value);
20257 } else if (type->attributeWildcard->nsSet != NULL) {
20258 printf("type: set\n");
20259 ns = type->attributeWildcard->nsSet;
20260 while (ns != NULL) {
20261 if (ns->value == NULL)
20262 printf("ns: (absent)\n");
20263 else
20264 printf("ns: %s\n", ns->value);
20265 ns = ns->next;
20266 }
20267 } else
20268 printf("empty\n");
20269
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000020270
20271#endif
Daniel Veillard3646d642004-06-02 19:19:14 +000020272 curState = ctxt->attr;
20273 while (curState != NULL) {
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000020274 if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
20275 if (curState->attr->ns != NULL)
20276 nsURI = curState->attr->ns->href;
20277 else
20278 nsURI = NULL;
20279 if (xmlSchemaMatchesWildcardNs(type->attributeWildcard,
20280 nsURI)) {
20281 /*
20282 * Handle processContents.
20283 */
20284 if ((type->attributeWildcard->processContents ==
20285 XML_SCHEMAS_ANY_LAX) ||
20286 (type->attributeWildcard->processContents ==
20287 XML_SCHEMAS_ANY_STRICT)) {
20288
20289 attr = curState->attr;
20290 attrDecl = xmlSchemaGetAttribute(ctxt->schema,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020291 attr->name, nsURI);
20292 curState->decl = attrDecl;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000020293 if (attrDecl != NULL) {
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000020294 curState->decl = attrDecl;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020295 curState->state = XML_SCHEMAS_ATTR_VALIDATE_VALUE;
20296 /* TODO
20297 ret = xmlSchemaCheckAttrLocallyValid(ctxt, attrDecl, curState, attr);
20298 */
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000020299 } else if (type->attributeWildcard->processContents ==
20300 XML_SCHEMAS_ANY_LAX) {
20301 curState->state = XML_SCHEMAS_ATTR_CHECKED;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020302 } else
20303 curState->state = XML_SCHEMAS_ATTR_WILD_NO_DECL;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000020304 } else
Daniel Veillard3646d642004-06-02 19:19:14 +000020305 curState->state = XML_SCHEMAS_ATTR_CHECKED;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020306 }
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000020307 }
Daniel Veillard3646d642004-06-02 19:19:14 +000020308 curState = curState->next;
20309 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020310 }
20311
Daniel Veillardc0826a72004-08-10 14:17:33 +000020312 if (ctxt->attr != NULL) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020313 int valueNeeded;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020314
20315 /*
20316 * Validate the value of the attribute.
20317 */
20318 if (ctxt->value != NULL) {
20319 xmlSchemaFreeValue(ctxt->value);
20320 ctxt->value = NULL;
20321 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000020322 curState = ctxt->attr;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020323 while ((curState != NULL) && (curState != ctxt->attrTop->next)) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020324 valueNeeded = 0;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020325 switch (curState->state) {
20326 case XML_SCHEMAS_ATTR_VALIDATE_VALUE:
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020327
20328 /*
20329 * Create an attribute info if needed.
20330 */
20331 if (ctxt->attrInfo == NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020332 ctxt->attrInfo = (xmlSchemaNodeInfoPtr)
20333 xmlMalloc(sizeof(xmlSchemaNodeInfo));
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020334 if (ctxt->attrInfo == NULL) {
20335 xmlSchemaVErrMemory(ctxt,
20336 "allocating an attribute info", NULL);
20337 goto fatal_exit;
20338 }
20339 }
20340 /*
20341 * Init the attribute info.
20342 */
20343 ctxt->attrInfo->flags = 0;
20344 ctxt->attrInfo->node = (xmlNodePtr) curState->attr;
20345 ctxt->attrInfo->decl = (xmlSchemaTypePtr) curState->decl;
20346 ctxt->attrInfo->value = NULL;
20347 if (curState->decl != NULL)
20348 ctxt->attrInfo->typeDef = curState->decl->subtypes;
20349 else
20350 ctxt->attrInfo->typeDef = NULL;
20351 if (curState->attr->ns != NULL)
20352 ctxt->attrInfo->namespaceName =
20353 curState->attr->ns->href;
20354 else
20355 ctxt->attrInfo->namespaceName = NULL;
20356 ctxt->attrInfo->localName = curState->attr->name;
20357
20358 ctxt->nodeInfo = ctxt->attrInfo;
20359
20360#ifdef IDC_ENABLED
20361 /*
20362 * Evaluate IDCs.
20363 */
20364 if (ctxt->xpathStates != NULL) {
20365 ret = xmlSchemaXPathEvaluate(ctxt,
20366 XML_ATTRIBUTE_NODE);
20367 if (ret == -1)
20368 goto fatal_exit;
20369 }
20370
20371#endif
20372 ret = xmlSchemaCheckAttrLocallyValid(ctxt, curState);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020373 if (ret == -1)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020374 goto fatal_exit;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020375 if ((ret != 0) && (ctxt->value != NULL)) {
20376 xmlSchemaFreeValue(ctxt->value);
20377 ctxt->value = NULL;
20378 }
20379 /* No break on purpose. */
20380 case XML_SCHEMAS_ATTR_CHECKED:
20381#ifdef IDC_ENABLED
20382 if (ctxt->xpathStates != NULL) {
20383 /*
20384 * Evaluate IDCs.
20385 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020386 if (ctxt->value != NULL) {
20387 ctxt->attrInfo->value = ctxt->value;
20388 ctxt->value = NULL;
20389 }
20390 if (xmlSchemaXPathProcessHistory(ctxt, ctxt->depth +1) == -1)
20391 goto fatal_exit;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020392 }
20393 break;
20394#endif
20395 default:
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020396 break;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020397 }
20398 curState = curState->next;
20399 }
20400
20401 /*
20402 * Report missing and illegal attributes.
20403 */
20404 curState = ctxt->attr;
20405 while ((curState != NULL) && (curState != ctxt->attrTop->next)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000020406 if (curState->state != XML_SCHEMAS_ATTR_CHECKED) {
20407 attr = curState->attr;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020408 if (curState->decl != NULL) {
20409 if (curState->decl->ref != NULL)
20410 attrDecl = curState->decl->refDecl;
20411 else
20412 attrDecl = curState->decl;
20413 } else
20414 attrDecl = NULL;
20415 if (curState->state == XML_SCHEMAS_ATTR_MISSING) {
20416 xmlSchemaVMissingAttrErr(ctxt, elem, attrDecl);
20417 } else if (curState->state ==
20418 XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED) {
20419 xmlSchemaVCustomErr(ctxt,
20420 XML_SCHEMAV_CVC_ATTRIBUTE_2,
20421 (xmlNodePtr) attr,
20422 (xmlSchemaTypePtr) attrDecl,
20423 "The type definition is absent",
20424 NULL);
20425 } else if (curState->state ==
20426 XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE) {
20427 xmlSchemaVCustomErr(ctxt,
20428 XML_SCHEMAV_CVC_AU,
20429 (xmlNodePtr) attr, (xmlSchemaTypePtr) attrDecl,
20430 "The value does not match the fixed value "
20431 "constraint", NULL);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020432 } else if (curState->state == XML_SCHEMAS_ATTR_WILD_NO_DECL) {
20433 xmlSchemaVWildcardErr(ctxt,
20434 XML_SCHEMAV_CVC_WILDCARD,
20435 (xmlNodePtr) attr,
20436 type->attributeWildcard,
20437 "No global attribute declaration found, but "
20438 "stipulated by the strict processContents of "
20439 "the wildcard");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020440 } else if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000020441 /* TODO: "prohibited" won't ever be touched here!.
20442 (curState->state == XML_SCHEMAS_ATTR_PROHIBITED))
20443 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020444 /*
20445 * TODO: One might report different error messages
20446 * for the following errors.
20447 */
20448 if ((type == NULL) || (type->attributeWildcard == NULL)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000020449 xmlSchemaVIllegalAttrErr(ctxt,
20450 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, attr);
20451 } else {
20452 xmlSchemaVIllegalAttrErr(ctxt,
20453 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, attr);
20454 }
20455 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000020456 }
20457 curState = curState->next;
20458 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020459 }
20460
20461 /*
20462 * Add missing default/fixed attributes.
20463 */
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000020464 if (defAttrStates != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020465 curState = defAttrStates;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000020466
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020467 while (curState != NULL) {
20468 attrDecl = curState->decl;
20469 if (attrDecl->ref != NULL)
20470 attrDecl = attrDecl->refDecl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020471
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000020472#ifdef IDC_ENABLED
20473 /*
20474 * Evaluate IDCs on default attributes.
20475 */
20476 if (ctxt->xpathStates != NULL) {
20477 /*
20478 * Create an attribute info if needed.
20479 */
20480 if (ctxt->attrInfo == NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020481 ctxt->attrInfo = (xmlSchemaNodeInfoPtr)
20482 xmlMalloc(sizeof(xmlSchemaNodeInfo));
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000020483 if (ctxt->attrInfo == NULL) {
20484 xmlSchemaVErrMemory(ctxt,
20485 "allocating an attribute info", NULL);
20486 goto fatal_exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020487 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020488 ctxt->attrInfo->value = NULL;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000020489 }
20490 /*
20491 * Init the attribute info.
Kasimier T. Buchcik285ebab2005-03-04 18:04:59 +000020492 * TODO: Hmm, maby a bit oversized this all.
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000020493 */
20494 ctxt->attrInfo->flags = 0;
20495 ctxt->attrInfo->decl = (xmlSchemaTypePtr) attrDecl;
20496 ctxt->attrInfo->node = NULL;
20497 ctxt->attrInfo->typeDef = attrDecl->subtypes;
20498 ctxt->attrInfo->namespaceName = attrDecl->targetNamespace;
20499 ctxt->attrInfo->localName = attrDecl->name;
20500
20501 ctxt->nodeInfo = ctxt->attrInfo;
20502
20503 ret = xmlSchemaXPathEvaluate(ctxt,
20504 XML_ATTRIBUTE_NODE);
20505 if (ret == -1)
20506 goto fatal_exit;
20507 if (ctxt->attrInfo->value != NULL) {
20508 xmlSchemaFreeValue(ctxt->attrInfo->value);
20509 ctxt->attrInfo->value = NULL;
20510 }
20511 if (ret > 0) {
Kasimier T. Buchcik285ebab2005-03-04 18:04:59 +000020512 /*
20513 * IDCs will consume the precomputed default value,
20514 * so we need to clone it somehow.
20515 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020516 /*
20517 * string or anySimpleType does not create a precomputed value
20518 * by default, so it will be created here on demand.
20519 * TODO: default/fixed attributes are a bit unoptimized:
20520 * the string value will be hold by ->defValue and inside
20521 * the precomputed value.
20522 */
20523 if (attrDecl->defVal == NULL) {
20524 xmlChar *str = xmlStrdup(attrDecl->defValue);
20525
20526 if (xmlSchemaPostCreateVal(ctxt,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000020527 ctxt->attrInfo->typeDef,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020528 str,
20529 &(attrDecl->defVal)) == -1) {
20530 FREE_AND_NULL(str)
20531 goto fatal_exit;
20532 }
20533 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000020534 ctxt->attrInfo->value = xmlSchemaCopyValue(attrDecl->defVal);
20535 /* TODO: error on NULL return. */
20536 }
Kasimier T. Buchcik285ebab2005-03-04 18:04:59 +000020537
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000020538 if (xmlSchemaXPathProcessHistory(ctxt, ctxt->depth +1) == -1)
20539 goto fatal_exit;
20540 }
20541#endif
20542
20543 if (ctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
20544 /*
20545 * PSVI: Add a new attribute node to the current element.
20546 */
20547 if (attrDecl->targetNamespace == NULL) {
20548 xmlNewProp(elem, attrDecl->name, curState->value);
20549 } else {
20550 xmlNsPtr ns;
20551
20552 ns = xmlSearchNsByHref(elem->doc, elem,
20553 attrDecl->targetNamespace);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020554 if (ns == NULL) {
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000020555 xmlChar prefix[12];
20556 int counter = 1;
20557
20558 attr = curState->attr;
20559 /*
20560 * Create a namespace declaration on the validation
20561 * root node if no namespace declaration is in scope.
20562 */
20563 snprintf((char *) prefix, sizeof(prefix), "p");
20564 /*
20565 * This is somehow not performant, since the ancestor
20566 * axis beyond @elem will be searched as well.
20567 */
20568 ns = xmlSearchNs(elem->doc, elem, BAD_CAST prefix);
20569 while (ns != NULL) {
20570 if (counter > 1000) {
20571 xmlSchemaVErr(ctxt, (xmlNodePtr) attr,
20572 XML_SCHEMAV_INTERNAL,
20573 "Internal error: xmlSchemaValidateAttributes, "
20574 "could not compute a ns prefix for "
20575 "default/fixed attribute '%s'.\n",
20576 attrDecl->name, NULL);
20577
20578 break;
20579 }
20580 snprintf((char *) prefix,
20581 sizeof(prefix), "p%d", counter++);
20582 ns = xmlSearchNs(elem->doc, elem,
20583 BAD_CAST prefix);
20584 }
20585 if (ns == NULL) {
20586 ns = xmlNewNs(ctxt->validationRoot,
20587 attrDecl->targetNamespace, BAD_CAST prefix);
20588 xmlNewNsProp(elem, ns, attrDecl->name,
20589 curState->value);
20590 }
20591 } else {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020592 xmlNewNsProp(elem, ns, attrDecl->name,
20593 curState->value);
20594 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020595 }
20596 }
20597 curState = curState->next;
20598 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000020599 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020600 ret = ctxt->err;
20601 goto exit;
20602
20603fatal_exit:
20604 ret = -1;
20605
20606exit:
20607
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020608 if (defAttrStates != NULL)
20609 xmlSchemaFreeAttributeStates(defAttrStates);
20610
Daniel Veillard3646d642004-06-02 19:19:14 +000020611#ifdef DEBUG_ATTR_VALIDATION
20612 if (redundant)
20613 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020614 "xmlSchemaValidateAttributes: redundant call by "
20615 "type: %s\n", type->name);
Daniel Veillard3646d642004-06-02 19:19:14 +000020616#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020617 ctxt->nodeInfo = ctxt->elemInfos[ctxt->depth];
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020618 ctxt->node = oldnode;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020619 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000020620}
20621
20622/**
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020623 * xmlSchemaStartValidation:
Daniel Veillard4255d502002-04-16 15:50:10 +000020624 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000020625 *
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020626 * The starting point of the validation, called by
20627 * xmlSchemaValidateDocument and xmlSchemaValidateOneElement.
Daniel Veillard4255d502002-04-16 15:50:10 +000020628 *
20629 * Returns 0 if the element is schemas valid, a positive error code
20630 * number otherwise and -1 in case of internal or API error.
20631 */
20632static int
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020633xmlSchemaStartValidation(xmlSchemaValidCtxtPtr ctxt)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020634{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020635 xmlSchemaElementPtr elemDecl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020636 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000020637
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020638 ctxt->err = 0;
20639 ctxt->nberrors = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020640 if (ctxt->schema == NULL) {
20641 /*
20642 * No schema was specified at time of creation of the validation
20643 * context. Use xsi:schemaLocation and xsi:noNamespaceSchemaLocation
20644 * of the instance to build a schema.
20645 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020646 if (ctxt->pctxt == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020647 if (xmlSchemaCreatePCtxtOnVCtxt(ctxt) == -1)
20648 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020649 ctxt->schema = xmlSchemaNewSchema(ctxt->pctxt);
20650 if (ctxt->schema == NULL)
20651 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020652 ctxt->xsiAssemble = 1;
20653 } else
20654 ctxt->xsiAssemble = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020655 /*
20656 * Assemble new schemata using xsi.
Daniel Veillardc0826a72004-08-10 14:17:33 +000020657 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020658 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020659 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
20660 if (ret == -1) {
20661 xmlSchemaVCustomErr(ctxt,
20662 XML_SCHEMAV_INTERNAL,
20663 ctxt->node, NULL,
20664 "Internal error: xmlSchemaValidateElement, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020665 "assembling schema by xsi", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020666 }
20667 /*
20668 * NOTE: We won't react on schema parser errors here.
20669 * TODO: But a warning would be nice.
20670 */
20671 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020672 if (ret != -1) {
20673 if (ctxt->node->ns != NULL)
20674 elemDecl = xmlSchemaGetElem(ctxt->schema, ctxt->node->name,
20675 ctxt->node->ns->href);
20676 else
20677 elemDecl = xmlSchemaGetElem(ctxt->schema, ctxt->node->name, NULL);
20678
20679 if (elemDecl == NULL) {
20680 xmlSchemaVCustomErr(ctxt,
20681 XML_SCHEMAV_CVC_ELT_1,
20682 ctxt->node, NULL,
20683 "No matching global declaration available", NULL);
20684 ret = XML_SCHEMAV_CVC_ELT_1;
20685 } else {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020686 /*
20687 * Augment the IDC definitions.
20688 */
20689 if (ctxt->schema->idcDef != NULL) {
20690 xmlHashScan(ctxt->schema->idcDef,
20691 (xmlHashScanner) xmlSchemaAugmentIDC, ctxt);
20692 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020693 ctxt->depth = -1;
20694 xmlSchemaBeginElement(ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020695 ret = xmlSchemaValidateElementByDeclaration(ctxt, elemDecl);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020696 xmlSchemaEndElement(ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020697 if (ret < 0) {
20698 xmlSchemaVCustomErr(ctxt,
20699 XML_SCHEMAV_INTERNAL, ctxt->node, NULL,
20700 "Internal error: xmlSchemaValidateElement, "
20701 "calling validation by declaration", NULL);
20702 }
20703 }
20704 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020705
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020706 if (ctxt->xsiAssemble) {
20707 if (ctxt->schema != NULL) {
20708 xmlSchemaFree(ctxt->schema);
20709 ctxt->schema = NULL;
20710 }
Daniel Veillard4255d502002-04-16 15:50:10 +000020711 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020712 xmlSchemaClearValidCtxt(ctxt);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020713 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000020714}
20715
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020716
Daniel Veillard4255d502002-04-16 15:50:10 +000020717/**
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000020718 * xmlSchemaValidateOneElement:
20719 * @ctxt: a schema validation context
20720 * @elem: an element node
20721 *
20722 * Validate a branch of a tree, starting with the given @elem.
20723 *
20724 * Returns 0 if the element and its subtree is valid, a positive error
20725 * code number otherwise and -1 in case of an internal or API error.
20726 */
20727int
20728xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
20729{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020730 if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000020731 return (-1);
20732
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020733 if (ctxt->schema == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020734 xmlSchemaVErr(ctxt, NULL,
20735 XML_SCHEMAV_INTERNAL,
20736 "API error: xmlSchemaValidateOneElement, "
20737 "no schema specified.\n", NULL, NULL);
20738 return (-1);
20739 }
20740
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000020741 ctxt->doc = elem->doc;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020742 ctxt->node = elem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020743 ctxt->validationRoot = elem;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020744 return (xmlSchemaStartValidation(ctxt));
Daniel Veillard4255d502002-04-16 15:50:10 +000020745}
20746
20747/************************************************************************
20748 * *
20749 * SAX Validation code *
20750 * *
20751 ************************************************************************/
20752
20753/************************************************************************
20754 * *
20755 * Validation interfaces *
20756 * *
20757 ************************************************************************/
20758
20759/**
20760 * xmlSchemaNewValidCtxt:
20761 * @schema: a precompiled XML Schemas
20762 *
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020763 * Create an XML Schemas validation context based on the given schema.
Daniel Veillard4255d502002-04-16 15:50:10 +000020764 *
20765 * Returns the validation context or NULL in case of error
20766 */
20767xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020768xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
20769{
Daniel Veillard4255d502002-04-16 15:50:10 +000020770 xmlSchemaValidCtxtPtr ret;
20771
20772 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
20773 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020774 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000020775 return (NULL);
20776 }
20777 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
Daniel Veillardc0826a72004-08-10 14:17:33 +000020778 ret->schema = schema;
Daniel Veillard4255d502002-04-16 15:50:10 +000020779 return (ret);
20780}
20781
20782/**
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020783 * xmlSchemaClearValidCtxt:
20784 * @ctxt: the schema validation context
20785 *
20786 * Free the resources associated to the schema validation context;
20787 * leaves some fields alive intended for reuse of the context.
20788 */
20789static void
20790xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
20791{
20792 if (vctxt == NULL)
20793 return;
20794
20795 vctxt->validationRoot = NULL;
20796 if (vctxt->attr != NULL) {
20797 xmlSchemaFreeAttributeStates(vctxt->attr);
20798 vctxt->attr = NULL;
20799 }
20800 if (vctxt->value != NULL) {
20801 xmlSchemaFreeValue(vctxt->value);
20802 vctxt->value = NULL;
20803 }
20804 /*
20805 * Augmented IDC information.
20806 */
20807 if (vctxt->aidcs != NULL) {
20808 xmlSchemaIDCAugPtr cur = vctxt->aidcs, next;
20809 do {
20810 next = cur->next;
20811 xmlFree(cur);
20812 cur = next;
20813 } while (cur != NULL);
20814 vctxt->aidcs = NULL;
20815 }
20816 if (vctxt->idcNodes != NULL) {
20817 int i;
20818 xmlSchemaPSVIIDCNodePtr item;
20819
20820 for (i = 0; i < vctxt->nbIdcNodes; i++) {
20821 item = vctxt->idcNodes[i];
20822 xmlFree(item->keys);
20823 xmlFree(item);
20824 }
20825 xmlFree(vctxt->idcNodes);
20826 vctxt->idcNodes = NULL;
20827 }
20828 /*
20829 * Note that we won't delete the XPath state pool here.
20830 */
20831 if (vctxt->xpathStates != NULL) {
20832 xmlSchemaFreeIDCStateObjList(vctxt->xpathStates);
20833 vctxt->xpathStates = NULL;
20834 }
20835 if (vctxt->attrInfo != NULL) {
20836 if (vctxt->attrInfo->value != NULL) {
20837 xmlSchemaFreeValue(vctxt->attrInfo->value);
20838 }
20839 memset(vctxt->attrInfo, 0, sizeof(xmlSchemaNodeInfo));
20840 }
20841 if (vctxt->elemInfos != NULL) {
20842 int i;
20843 xmlSchemaNodeInfoPtr info;
20844
20845 for (i = 0; i < vctxt->sizeElemInfos; i++) {
20846 info = vctxt->elemInfos[i];
20847 if (info == NULL)
20848 break;
20849 if (info->value != NULL) {
20850 xmlSchemaFreeValue(info->value);
20851 info->value = NULL;
20852 }
20853 if (info->idcMatchers != NULL) {
20854 xmlSchemaIDCFreeMatcherList(info->idcMatchers);
20855 info->idcMatchers = NULL;
20856 }
20857 if (info->idcTable != NULL) {
20858 xmlSchemaIDCFreeIDCTable(info->idcTable);
20859 info->idcTable = NULL;
20860 }
20861 }
20862 }
20863}
20864
20865/**
Daniel Veillard4255d502002-04-16 15:50:10 +000020866 * xmlSchemaFreeValidCtxt:
20867 * @ctxt: the schema validation context
20868 *
20869 * Free the resources associated to the schema validation context
20870 */
20871void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020872xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
20873{
Daniel Veillard4255d502002-04-16 15:50:10 +000020874 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020875 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000020876 if (ctxt->attr != NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000020877 xmlSchemaFreeAttributeStates(ctxt->attr);
Daniel Veillard88c58912002-04-23 07:12:20 +000020878 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020879 xmlSchemaFreeValue(ctxt->value);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020880 if (ctxt->pctxt != NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020881 xmlSchemaFreeParserCtxt(ctxt->pctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020882 if (ctxt->idcNodes != NULL) {
20883 int i;
20884 xmlSchemaPSVIIDCNodePtr item;
20885
20886 for (i = 0; i < ctxt->nbIdcNodes; i++) {
20887 item = ctxt->idcNodes[i];
20888 xmlFree(item->keys);
20889 xmlFree(item);
20890 }
20891 xmlFree(ctxt->idcNodes);
20892 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020893 if (ctxt->idcKeys != NULL) {
20894 int i;
20895 for (i = 0; i < ctxt->nbIdcKeys; i++)
20896 xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
20897 xmlFree(ctxt->idcKeys);
20898 }
20899
20900 if (ctxt->xpathStates != NULL)
20901 xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
20902 if (ctxt->xpathStatePool != NULL)
20903 xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
20904
20905 /*
20906 * Augmented IDC information.
20907 */
20908 if (ctxt->aidcs != NULL) {
20909 xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
20910 do {
20911 next = cur->next;
20912 xmlFree(cur);
20913 cur = next;
20914 } while (cur != NULL);
20915 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020916 if (ctxt->attrInfo != NULL) {
20917 if (ctxt->attrInfo->value != NULL)
20918 xmlSchemaFreeValue(ctxt->attrInfo->value);
20919 xmlFree(ctxt->attrInfo);
20920 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020921 if (ctxt->elemInfos != NULL) {
20922 int i;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020923 xmlSchemaNodeInfoPtr info;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020924
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020925 for (i = 0; i < ctxt->sizeElemInfos; i++) {
20926 info = ctxt->elemInfos[i];
20927 if (info == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020928 break;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020929 if (info->value != NULL)
20930 xmlSchemaFreeValue(info->value);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020931 if (info->idcMatchers != NULL)
20932 xmlSchemaIDCFreeMatcherList(info->idcMatchers);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020933 if (info->idcTable != NULL)
20934 xmlSchemaIDCFreeIDCTable(info->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020935 /*
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020936 * TODO: Don't know if those will have to be freed if in streaming
20937 * mode.
20938 *
20939 * xmlFree(info->localName);
20940 * if (info->namespaceName != NULL)
20941 * xmlFree(info->namespaceName);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020942 */
20943 xmlFree(info);
20944 }
20945 xmlFree(ctxt->elemInfos);
20946 }
Daniel Veillard4255d502002-04-16 15:50:10 +000020947 xmlFree(ctxt);
20948}
20949
20950/**
20951 * xmlSchemaSetValidErrors:
20952 * @ctxt: a schema validation context
20953 * @err: the error function
20954 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +000020955 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +000020956 *
William M. Brack2f2a6632004-08-20 23:09:47 +000020957 * Set the error and warning callback informations
Daniel Veillard4255d502002-04-16 15:50:10 +000020958 */
20959void
20960xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020961 xmlSchemaValidityErrorFunc err,
20962 xmlSchemaValidityWarningFunc warn, void *ctx)
20963{
Daniel Veillard4255d502002-04-16 15:50:10 +000020964 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020965 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000020966 ctxt->error = err;
20967 ctxt->warning = warn;
20968 ctxt->userData = ctx;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020969 if (ctxt->pctxt != NULL)
20970 xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
Daniel Veillard4255d502002-04-16 15:50:10 +000020971}
20972
20973/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000020974 * xmlSchemaGetValidErrors:
20975 * @ctxt: a XML-Schema validation context
20976 * @err: the error function result
20977 * @warn: the warning function result
20978 * @ctx: the functions context result
20979 *
20980 * Get the error and warning callback informations
20981 *
20982 * Returns -1 in case of error and 0 otherwise
20983 */
20984int
20985xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
20986 xmlSchemaValidityErrorFunc * err,
20987 xmlSchemaValidityWarningFunc * warn, void **ctx)
20988{
20989 if (ctxt == NULL)
20990 return (-1);
20991 if (err != NULL)
20992 *err = ctxt->error;
20993 if (warn != NULL)
20994 *warn = ctxt->warning;
20995 if (ctx != NULL)
20996 *ctx = ctxt->userData;
20997 return (0);
20998}
20999
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021000
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021001/**
Daniel Veillard6927b102004-10-27 17:29:04 +000021002 * xmlSchemaSetValidOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021003 * @ctxt: a schema validation context
21004 * @options: a combination of xmlSchemaValidOption
21005 *
21006 * Sets the options to be used during the validation.
21007 *
21008 * Returns 0 in case of success, -1 in case of an
21009 * API error.
21010 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021011int
21012xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
21013 int options)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021014
21015{
21016 int i;
21017
21018 if (ctxt == NULL)
21019 return (-1);
21020 /*
21021 * WARNING: Change the start value if adding to the
21022 * xmlSchemaValidOption.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021023 * TODO: Is there an other, more easy to maintain,
21024 * way?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021025 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021026 for (i = 1; i < (int) sizeof(int) * 8; i++) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021027 if (options & 1<<i) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021028 xmlSchemaVErr(ctxt, NULL,
21029 XML_SCHEMAV_INTERNAL,
21030 "Internal error: xmlSchemaSetValidOptions, "
21031 "invalid option argument.\n", NULL, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021032 return (-1);
21033 }
21034 }
21035 ctxt->options = options;
21036 return (0);
21037}
21038
21039/**
Daniel Veillard6927b102004-10-27 17:29:04 +000021040 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021041 * @ctxt: a schema validation context
21042 *
William M. Brack21e4ef22005-01-02 09:53:13 +000021043 * Get the validation context options.
21044 *
21045 * Returns the option combination or -1 on error.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021046 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021047int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021048xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
21049
21050{
21051 if (ctxt == NULL)
21052 return (-1);
21053 else
21054 return (ctxt->options);
21055}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021056
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021057
Daniel Veillard259f0df2004-08-18 09:13:18 +000021058/**
Daniel Veillard4255d502002-04-16 15:50:10 +000021059 * xmlSchemaValidateDoc:
21060 * @ctxt: a schema validation context
21061 * @doc: a parsed document tree
21062 *
21063 * Validate a document tree in memory.
21064 *
21065 * Returns 0 if the document is schemas valid, a positive error code
21066 * number otherwise and -1 in case of internal or API error.
21067 */
21068int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021069xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
21070{
Daniel Veillard4255d502002-04-16 15:50:10 +000021071 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021072 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000021073
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000021074 ctxt->doc = doc;
21075 ctxt->node = xmlDocGetRootElement(doc);
21076 if (ctxt->node == NULL) {
21077 xmlSchemaVCustomErr(ctxt,
21078 XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
21079 (xmlNodePtr) doc, NULL,
21080 "The document has no document element", NULL);
21081 return (ctxt->err);
21082 }
21083 ctxt->validationRoot = ctxt->node;
21084 xmlSchemaStartValidation(ctxt);
21085
21086 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000021087}
21088
21089/**
21090 * xmlSchemaValidateStream:
21091 * @ctxt: a schema validation context
21092 * @input: the input to use for reading the data
21093 * @enc: an optional encoding information
21094 * @sax: a SAX handler for the resulting events
21095 * @user_data: the context to provide to the SAX handler.
21096 *
21097 * Validate a document tree in memory.
21098 *
21099 * Returns 0 if the document is schemas valid, a positive error code
21100 * number otherwise and -1 in case of internal or API error.
21101 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021102int
Daniel Veillard4255d502002-04-16 15:50:10 +000021103xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021104 xmlParserInputBufferPtr input, xmlCharEncoding enc,
21105 xmlSAXHandlerPtr sax, void *user_data)
21106{
Daniel Veillard4255d502002-04-16 15:50:10 +000021107 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021108 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000021109 ctxt->input = input;
21110 ctxt->enc = enc;
21111 ctxt->sax = sax;
21112 ctxt->user_data = user_data;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021113 TODO return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000021114}
21115
21116#endif /* LIBXML_SCHEMAS_ENABLED */