blob: 3835adac8b10a35c5bf6dc9c26243074754181f3 [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);
1434 } else if (node->type == XML_ATTRIBUTE_NODE) {
1435 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
1436 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value, NULL);
1437 } else {
1438 msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
1439 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
1440 }
1441 } else {
1442 msg = xmlStrcat(msg, (const xmlChar *) message);
1443 msg = xmlStrcat(msg, BAD_CAST ".\n");
1444 xmlSchemaVErr3(ctxt, node, error, (const char *) msg, str1, str2, str3);
1445 }
1446 FREE_AND_NULL(str)
1447 xmlFree(msg);
1448}
1449
1450/**
1451 * xmlSchemaVSimpleTypeErr:
1452 * @ctxt: the schema validation context
1453 * @error: the error code
1454 * @type: the type used for validation
1455 * @node: the node containing the validated value
1456 * @value: the validated value
1457 *
1458 * Reports a simple type validation error.
1459 * TODO: Should this report the value of an element as well?
1460 */
1461static void
1462xmlSchemaVSimpleTypeErr(xmlSchemaValidCtxtPtr ctxt,
1463 xmlParserErrors error,
1464 xmlNodePtr node,
1465 const xmlChar *value,
1466 xmlSchemaTypePtr type)
1467{
1468 xmlChar *str = NULL, *msg = NULL;
1469
1470 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
1471 msg = xmlStrcat(msg, BAD_CAST " [");
1472 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1473 if (node->type == XML_ATTRIBUTE_NODE) {
1474 msg = xmlStrcat(msg, BAD_CAST "]: The value '%s' is not valid.\n");
1475 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value, NULL);
1476 } else {
1477 msg = xmlStrcat(msg, BAD_CAST "]: The character content is not valid.\n");
1478 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
1479 }
1480 FREE_AND_NULL(str)
1481 xmlFree(msg);
1482}
1483
1484/**
William M. Brack2f2a6632004-08-20 23:09:47 +00001485 * xmlSchemaVComplexTypeErr:
1486 * @ctxt: the schema validation context
1487 * @error: the error code
1488 * @node: the node containing the validated value
1489 * @type: the complex type used for validation
1490 * @message: the error message
1491 *
1492 * Reports a complex type validation error.
1493 */
1494static void
1495xmlSchemaVComplexTypeErr(xmlSchemaValidCtxtPtr ctxt,
1496 xmlParserErrors error,
1497 xmlNodePtr node,
1498 xmlSchemaTypePtr type,
1499 const char *message)
1500{
1501 xmlChar *str = NULL, *msg = NULL;
1502
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00001503 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00001504 /* Specify the complex type only if it is global. */
1505 if ((type != NULL) && (type->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00001506 msg = xmlStrcat(msg, BAD_CAST " [");
1507 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1508 msg = xmlStrcat(msg, BAD_CAST "]");
1509 }
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001510 msg = xmlStrcat(msg, BAD_CAST ": %s.\n");
1511 xmlSchemaVErr(ctxt, node, error, (const char *) msg,
William M. Brack2f2a6632004-08-20 23:09:47 +00001512 (const xmlChar *) message, NULL);
1513 FREE_AND_NULL(str)
1514 xmlFree(msg);
1515}
1516
1517/**
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001518 * xmlSchemaVComplexTypeElemErr:
1519 * @ctxt: the schema validation context
1520 * @error: the error code
1521 * @node: the node containing the validated value
1522 * @type: the complex type used for validation
1523 * @message: the error message
1524 *
1525 * Reports a complex type validation error.
1526 */
1527static void
1528xmlSchemaVComplexTypeElemErr(xmlSchemaValidCtxtPtr ctxt,
1529 xmlParserErrors error,
1530 xmlNodePtr node,
1531 xmlSchemaTypePtr type,
1532 const char *message,
1533 int nbval,
1534 int nbneg,
1535 xmlChar **values)
1536{
1537 xmlChar *str = NULL, *msg = NULL;
1538 xmlChar *localName, *nsName;
1539 const xmlChar *cur, *end;
1540 int i;
1541
1542 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
1543 /* Specify the complex type only if it is global. */
1544 if ((type != NULL) && (type->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
1545 msg = xmlStrcat(msg, BAD_CAST " [");
1546 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1547 msg = xmlStrcat(msg, BAD_CAST "]");
1548 FREE_AND_NULL(str)
1549 }
1550 msg = xmlStrcat(msg, BAD_CAST ": ");
1551 msg = xmlStrcat(msg, (const xmlChar *) message);
1552 /*
1553 * Note that is does not make sense to report that we have a
1554 * wildcard here, since the wildcard might be unfolded into
1555 * multiple transitions.
1556 */
1557 if (nbval + nbneg > 0) {
1558 if (nbval + nbneg > 1) {
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00001559 str = xmlStrdup(BAD_CAST ". Expected is one of ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001560 } else
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00001561 str = xmlStrdup(BAD_CAST ". Expected is ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001562 nsName = NULL;
1563
1564 for (i = 0; i < nbval + nbneg; i++) {
1565 cur = values[i];
1566 /*
1567 * Get the local name.
1568 */
1569 localName = NULL;
1570
1571 end = cur;
1572 if (*end == '*') {
1573 localName = xmlStrdup(BAD_CAST "*");
1574 *end++;
1575 } else {
1576 while ((*end != 0) && (*end != '|'))
1577 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001578 localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001579 }
1580 if (*end != 0) {
1581 *end++;
1582 /*
1583 * Skip "*|*" if they come with negated expressions, since
1584 * they represent the same negated wildcard.
1585 */
1586 if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
1587 /*
1588 * Get the namespace name.
1589 */
1590 cur = end;
1591 if (*end == '*') {
1592 nsName = xmlStrdup(BAD_CAST "{*}");
1593 } else {
1594 while (*end != 0)
1595 end++;
1596
1597 if (i >= nbval)
1598 nsName = xmlStrdup(BAD_CAST "{##other:");
1599 else
1600 nsName = xmlStrdup(BAD_CAST "{");
1601
1602 nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
1603 nsName = xmlStrcat(nsName, BAD_CAST "}");
1604 }
1605 str = xmlStrcat(str, BAD_CAST nsName);
1606 FREE_AND_NULL(nsName)
1607 } else {
1608 FREE_AND_NULL(localName);
1609 continue;
1610 }
1611 }
1612 str = xmlStrcat(str, BAD_CAST localName);
1613 FREE_AND_NULL(localName);
1614
1615 if (i < nbval + nbneg -1)
1616 str = xmlStrcat(str, BAD_CAST ", ");
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00001617 }
1618 str = xmlStrcat(str, BAD_CAST " )");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001619 msg = xmlStrcat(msg, BAD_CAST str);
1620 FREE_AND_NULL(str)
1621 }
1622 msg = xmlStrcat(msg, BAD_CAST ".\n");
1623 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
1624 xmlFree(msg);
1625}
1626
1627/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00001628 * xmlSchemaPMissingAttrErr:
1629 * @ctxt: the schema validation context
1630 * @ownerDes: the designation of the owner
1631 * @ownerName: the name of the owner
1632 * @ownerItem: the owner as a schema object
1633 * @ownerElem: the owner as an element node
1634 * @node: the parent element node of the missing attribute node
1635 * @type: the corresponding type of the attribute node
1636 *
1637 * Reports an illegal attribute.
1638 */
1639static void
1640xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
1641 xmlParserErrors error,
1642 xmlChar **ownerDes,
1643 xmlSchemaTypePtr ownerItem,
1644 xmlNodePtr ownerElem,
1645 const char *name,
1646 const char *message)
1647{
1648 xmlChar *des = NULL;
1649
1650 if (ownerDes == NULL)
1651 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
1652 else if (*ownerDes == NULL) {
1653 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
1654 des = *ownerDes;
1655 } else
1656 des = *ownerDes;
1657 if (message != NULL)
1658 xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
1659 else
1660 xmlSchemaPErr(ctxt, ownerElem, error,
1661 "%s: The attribute '%s' is required but missing.\n",
1662 BAD_CAST des, BAD_CAST name);
1663 if (ownerDes == NULL)
1664 FREE_AND_NULL(des);
1665}
1666
William M. Brack2f2a6632004-08-20 23:09:47 +00001667/**
1668 * xmlSchemaCompTypeToString:
1669 * @type: the type of the schema item
1670 *
1671 * Returns the component name of a schema item.
1672 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001673static const char *
1674xmlSchemaCompTypeToString(xmlSchemaTypeType type)
1675{
1676 switch (type) {
1677 case XML_SCHEMA_TYPE_SIMPLE:
1678 return("simple type definition");
1679 case XML_SCHEMA_TYPE_COMPLEX:
1680 return("complex type definition");
1681 case XML_SCHEMA_TYPE_ELEMENT:
1682 return("element declaration");
1683 case XML_SCHEMA_TYPE_ATTRIBUTE:
1684 return("attribute declaration");
1685 case XML_SCHEMA_TYPE_GROUP:
1686 return("model group definition");
1687 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1688 return("attribute group definition");
1689 case XML_SCHEMA_TYPE_NOTATION:
1690 return("notation declaration");
1691 default:
1692 return("Not a schema component");
1693 }
1694}
1695/**
1696 * xmlSchemaPResCompAttrErr:
1697 * @ctxt: the schema validation context
1698 * @error: the error code
1699 * @ownerDes: the designation of the owner
1700 * @ownerItem: the owner as a schema object
1701 * @ownerElem: the owner as an element node
1702 * @name: the name of the attribute holding the QName
1703 * @refName: the referenced local name
1704 * @refURI: the referenced namespace URI
1705 * @message: optional message
1706 *
1707 * Used to report QName attribute values that failed to resolve
1708 * to schema components.
1709 */
1710static void
1711xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
1712 xmlParserErrors error,
1713 xmlChar **ownerDes,
1714 xmlSchemaTypePtr ownerItem,
1715 xmlNodePtr ownerElem,
1716 const char *name,
1717 const xmlChar *refName,
1718 const xmlChar *refURI,
1719 xmlSchemaTypeType refType,
1720 const char *refTypeStr)
1721{
1722 xmlChar *des = NULL, *strA = NULL;
1723
1724 if (ownerDes == NULL)
1725 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
1726 else if (*ownerDes == NULL) {
1727 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
1728 des = *ownerDes;
1729 } else
1730 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001731 if (refTypeStr == NULL)
1732 refTypeStr = xmlSchemaCompTypeToString(refType);
1733 xmlSchemaPErrExt(ctxt, ownerElem, error,
1734 NULL, NULL, NULL,
1735 "%s, attribute '%s': The QName value %s does not resolve to a(n) "
1736 "%s.\n", BAD_CAST des, BAD_CAST name,
1737 xmlSchemaFormatNsUriLocal(&strA, refURI, refName),
1738 BAD_CAST refTypeStr, NULL);
1739 if (ownerDes == NULL)
1740 FREE_AND_NULL(des)
1741 FREE_AND_NULL(strA)
1742}
1743
William M. Brack2f2a6632004-08-20 23:09:47 +00001744/**
1745 * xmlSchemaPCustomAttrErr:
1746 * @ctxt: the schema parser context
1747 * @error: the error code
1748 * @ownerDes: the designation of the owner
1749 * @ownerItem: the owner as a schema object
1750 * @attr: the illegal attribute node
1751 *
1752 * Reports an illegal attribute during the parse.
1753 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001754static void
1755xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00001756 xmlParserErrors error,
1757 xmlChar **ownerDes,
1758 xmlSchemaTypePtr ownerItem,
1759 xmlAttrPtr attr,
1760 const char *msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001761{
1762 xmlChar *des = NULL;
1763
1764 if (ownerDes == NULL)
1765 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
1766 else if (*ownerDes == NULL) {
1767 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
1768 des = *ownerDes;
1769 } else
1770 des = *ownerDes;
1771 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
1772 "%s, attribute '%s': %s.\n",
1773 BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
1774 if (ownerDes == NULL)
1775 FREE_AND_NULL(des);
1776}
1777
1778/**
1779 * xmlSchemaPIllegalAttrErr:
William M. Brack2f2a6632004-08-20 23:09:47 +00001780 * @ctxt: the schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00001781 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00001782 * @ownerDes: the designation of the attribute's owner
1783 * @ownerItem: the attribute's owner item
Daniel Veillardc0826a72004-08-10 14:17:33 +00001784 * @attr: the illegal attribute node
1785 *
William M. Brack2f2a6632004-08-20 23:09:47 +00001786 * Reports an illegal attribute during the parse.
Daniel Veillardc0826a72004-08-10 14:17:33 +00001787 */
1788static void
1789xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
1790 xmlParserErrors error,
1791 xmlChar **ownerDes,
1792 xmlSchemaTypePtr ownerItem,
1793 xmlAttrPtr attr)
1794{
1795 xmlChar *des = NULL, *strA = NULL;
1796
1797 if (ownerDes == NULL)
1798 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
1799 else if (*ownerDes == NULL) {
1800 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
1801 des = *ownerDes;
1802 } else
1803 des = *ownerDes;
1804 xmlSchemaPErr(ctxt, (xmlNodePtr) attr, error,
1805 "%s: The attribute '%s' is not allowed.\n", BAD_CAST des,
1806 xmlSchemaFormatNsPrefixLocal(&strA, attr->ns, attr->name));
1807 if (ownerDes == NULL)
1808 FREE_AND_NULL(des);
1809 FREE_AND_NULL(strA);
1810}
1811
William M. Brack2f2a6632004-08-20 23:09:47 +00001812/**
1813 * xmlSchemaPAquireDes:
1814 * @des: the first designation
1815 * @itemDes: the second designation
1816 * @item: the schema item
1817 * @itemElem: the node of the schema item
1818 *
1819 * Creates a designation for an item.
1820 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001821static void
1822xmlSchemaPAquireDes(xmlChar **des,
1823 xmlChar **itemDes,
1824 xmlSchemaTypePtr item,
1825 xmlNodePtr itemElem)
1826{
1827 if (itemDes == NULL)
1828 xmlSchemaFormatItemForReport(des, NULL, item, itemElem, 1);
1829 else if (*itemDes == NULL) {
1830 xmlSchemaFormatItemForReport(itemDes, NULL, item, itemElem, 1);
1831 *des = *itemDes;
1832 } else
1833 *des = *itemDes;
1834}
1835
William M. Brack2f2a6632004-08-20 23:09:47 +00001836/**
1837 * xmlSchemaPCustomErr:
1838 * @ctxt: the schema parser context
1839 * @error: the error code
1840 * @itemDes: the designation of the schema item
1841 * @item: the schema item
1842 * @itemElem: the node of the schema item
1843 * @message: the error message
1844 * @str1: an optional param for the error message
1845 * @str2: an optional param for the error message
1846 * @str3: an optional param for the error message
1847 *
1848 * Reports an error during parsing.
1849 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001850static void
1851xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
1852 xmlParserErrors error,
1853 xmlChar **itemDes,
1854 xmlSchemaTypePtr item,
1855 xmlNodePtr itemElem,
1856 const char *message,
1857 const xmlChar *str1,
1858 const xmlChar *str2,
1859 const xmlChar *str3)
1860{
1861 xmlChar *des = NULL, *msg = NULL;
1862
1863 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
1864 msg = xmlStrdup(BAD_CAST "%s: ");
1865 msg = xmlStrcat(msg, (const xmlChar *) message);
1866 msg = xmlStrcat(msg, BAD_CAST ".\n");
1867 if ((itemElem == NULL) && (item != NULL))
1868 itemElem = item->node;
1869 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
1870 (const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
1871 if (itemDes == NULL)
1872 FREE_AND_NULL(des);
1873 FREE_AND_NULL(msg);
1874}
1875
William M. Brack2f2a6632004-08-20 23:09:47 +00001876/**
1877 * xmlSchemaPCustomErr:
1878 * @ctxt: the schema parser context
1879 * @error: the error code
1880 * @itemDes: the designation of the schema item
1881 * @item: the schema item
1882 * @itemElem: the node of the schema item
1883 * @message: the error message
1884 * @str1: the optional param for the error message
1885 *
1886 * Reports an error during parsing.
1887 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001888static void
1889xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
1890 xmlParserErrors error,
1891 xmlChar **itemDes,
1892 xmlSchemaTypePtr item,
1893 xmlNodePtr itemElem,
1894 const char *message,
1895 const xmlChar *str1)
1896{
1897 xmlSchemaPCustomErrExt(ctxt, error, itemDes, item, itemElem, message,
1898 str1, NULL, NULL);
1899}
1900
William M. Brack2f2a6632004-08-20 23:09:47 +00001901/**
1902 * xmlSchemaPAttrUseErr:
1903 * @ctxt: the schema parser context
1904 * @error: the error code
1905 * @itemDes: the designation of the schema type
1906 * @item: the schema type
1907 * @itemElem: the node of the schema type
1908 * @attr: the invalid schema attribute
1909 * @message: the error message
1910 * @str1: the optional param for the error message
1911 *
1912 * Reports an attribute use error during parsing.
1913 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001914static void
1915xmlSchemaPAttrUseErr(xmlSchemaParserCtxtPtr ctxt,
1916 xmlParserErrors error,
1917 xmlChar **itemDes,
1918 xmlSchemaTypePtr item,
1919 xmlNodePtr itemElem,
1920 const xmlSchemaAttributePtr attr,
1921 const char *message,
1922 const xmlChar *str1)
1923{
1924 xmlChar *des = NULL, *strA = NULL, *msg = NULL;
1925
1926 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
1927 xmlSchemaFormatNsUriLocal(&strA, xmlSchemaGetAttrTargetNsURI(attr),
1928 xmlSchemaGetAttrName(attr));
1929 msg = xmlStrdup(BAD_CAST "%s, attr. use %s: ");
1930 msg = xmlStrcat(msg, (const xmlChar *) message);
1931 msg = xmlStrcat(msg, BAD_CAST ".\n");
1932 if ((itemElem == NULL) && (item != NULL))
1933 itemElem = item->node;
1934 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
1935 (const char *) msg, BAD_CAST des, BAD_CAST strA, str1, NULL, NULL);
1936 if (itemDes == NULL)
1937 FREE_AND_NULL(des);
1938 FREE_AND_NULL(strA);
1939 xmlFree(msg);
1940}
1941
William M. Brack2f2a6632004-08-20 23:09:47 +00001942/**
1943 * xmlSchemaPIllegalFacetAtomicErr:
1944 * @ctxt: the schema parser context
1945 * @error: the error code
1946 * @itemDes: the designation of the type
1947 * @item: the schema type
1948 * @baseItem: the base type of type
1949 * @facet: the illegal facet
1950 *
1951 * Reports an illegal facet for atomic simple types.
1952 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001953static void
1954xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
1955 xmlParserErrors error,
1956 xmlChar **itemDes,
1957 xmlSchemaTypePtr item,
1958 xmlSchemaTypePtr baseItem,
1959 xmlSchemaFacetPtr facet)
1960{
1961 xmlChar *des = NULL, *strT = NULL;
1962
1963 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
1964 xmlSchemaPErrExt(ctxt, item->node, error, NULL, NULL, NULL,
1965 "%s: The facet '%s' is not allowed on types derived from the "
1966 "type %s.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001967 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type),
Daniel Veillardc0826a72004-08-10 14:17:33 +00001968 xmlSchemaFormatItemForReport(&strT, NULL, baseItem, NULL, 1),
1969 NULL, NULL);
1970 if (itemDes == NULL)
1971 FREE_AND_NULL(des);
1972 FREE_AND_NULL(strT);
1973}
1974
William M. Brack2f2a6632004-08-20 23:09:47 +00001975/**
1976 * xmlSchemaPIllegalFacetListUnionErr:
1977 * @ctxt: the schema parser context
1978 * @error: the error code
1979 * @itemDes: the designation of the schema item involved
1980 * @item: the schema item involved
1981 * @facet: the illegal facet
1982 *
1983 * Reports an illegal facet for <list> and <union>.
1984 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001985static void
1986xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
1987 xmlParserErrors error,
1988 xmlChar **itemDes,
1989 xmlSchemaTypePtr item,
1990 xmlSchemaFacetPtr facet)
1991{
1992 xmlChar *des = NULL, *strT = NULL;
1993
1994 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
1995 xmlSchemaPErr(ctxt, item->node, error,
1996 "%s: The facet '%s' is not allowed.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00001997 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +00001998 if (itemDes == NULL)
1999 FREE_AND_NULL(des);
2000 FREE_AND_NULL(strT);
2001}
2002
2003/**
2004 * xmlSchemaPMutualExclAttrErr:
2005 * @ctxt: the schema validation context
2006 * @error: the error code
2007 * @elemDes: the designation of the parent element node
2008 * @attr: the bad attribute node
2009 * @type: the corresponding type of the attribute node
2010 *
2011 * Reports an illegal attribute.
2012 */
2013static void
2014xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
2015 xmlParserErrors error,
2016 xmlChar **ownerDes,
2017 xmlSchemaTypePtr ownerItem,
2018 xmlAttrPtr attr,
2019 const char *name1,
2020 const char *name2)
2021{
2022 xmlChar *des = NULL;
2023
2024 if (ownerDes == NULL)
2025 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
2026 else if (*ownerDes == NULL) {
2027 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
2028 des = *ownerDes;
2029 } else
2030 des = *ownerDes;
2031 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
2032 "%s: The attributes '%s' and '%s' are mutually exclusive.\n",
2033 BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
2034 if (ownerDes == NULL)
2035 FREE_AND_NULL(des)
2036}
2037
2038/**
2039 * xmlSchemaPSimpleTypeErr:
2040 * @ctxt: the schema validation context
2041 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00002042 * @type: the type specifier
Daniel Veillardc0826a72004-08-10 14:17:33 +00002043 * @ownerDes: the designation of the owner
2044 * @ownerItem: the schema object if existent
2045 * @node: the validated node
2046 * @value: the validated value
2047 *
2048 * Reports a simple type validation error.
2049 * TODO: Should this report the value of an element as well?
2050 */
2051static void
2052xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
2053 xmlParserErrors error,
2054 xmlChar **ownerDes,
2055 xmlSchemaTypePtr ownerItem,
2056 xmlNodePtr node,
William M. Brack2f2a6632004-08-20 23:09:47 +00002057 xmlSchemaTypePtr type,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002058 const char *typeDes,
2059 const xmlChar *value,
2060 const char *message,
2061 const xmlChar *str1,
2062 const xmlChar *str2)
2063{
William M. Brack2f2a6632004-08-20 23:09:47 +00002064 xmlChar *des = NULL, *strA = NULL, *strT = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002065
2066 if (ownerDes == NULL)
2067 xmlSchemaPRequestItemDes(&des, ownerItem, node);
2068 else if (*ownerDes == NULL) {
2069 xmlSchemaPRequestItemDes(ownerDes, ownerItem, node);
2070 des = *ownerDes;
2071 } else
2072 des = *ownerDes;
William M. Brack2f2a6632004-08-20 23:09:47 +00002073 if (type != NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002074 typeDes = (const char *) xmlSchemaFormatItemForReport(&strT, NULL, type, NULL, 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002075 if (message == NULL) {
2076 /*
2077 * Use default messages.
2078 */
2079 if (node->type == XML_ATTRIBUTE_NODE) {
2080 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
2081 "%s, attribute '%s' [%s]: The value '%s' is not "
2082 "valid.\n",
2083 BAD_CAST des, xmlSchemaFormatNsPrefixLocal(&strA, node->ns,
2084 node->name), BAD_CAST typeDes, value, NULL);
2085 } else {
2086 xmlSchemaPErr(ctxt, node, error,
2087 "%s [%s]: The character content is not valid.\n",
2088 BAD_CAST des, BAD_CAST typeDes);
2089 }
2090 } else {
2091 xmlChar *msg;
2092
2093 msg = xmlStrdup(BAD_CAST "%s");
2094 if (node->type == XML_ATTRIBUTE_NODE)
2095 msg = xmlStrcat(msg, BAD_CAST ", attribute '%s'");
2096 msg = xmlStrcat(msg, BAD_CAST " [%s]: ");
2097 msg = xmlStrcat(msg, (const xmlChar *) message);
2098 msg = xmlStrcat(msg, BAD_CAST ".\n");
2099 if (node->type == XML_ATTRIBUTE_NODE) {
2100 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
2101 (const char *) msg,
2102 BAD_CAST des, xmlSchemaFormatNsPrefixLocal(&strA,
2103 node->ns, node->name), BAD_CAST typeDes, str1, str2);
2104 } else {
2105 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
2106 (const char *) msg,
2107 BAD_CAST des, BAD_CAST typeDes, str1, str2, NULL);
2108 }
2109 xmlFree(msg);
2110 }
2111 /* Cleanup. */
2112 FREE_AND_NULL(strA)
2113 FREE_AND_NULL(strT)
2114 if (ownerDes == NULL)
2115 FREE_AND_NULL(des)
2116}
2117
William M. Brack2f2a6632004-08-20 23:09:47 +00002118/**
2119 * xmlSchemaPContentErr:
2120 * @ctxt: the schema parser context
2121 * @error: the error code
2122 * @onwerDes: the designation of the holder of the content
2123 * @ownerItem: the owner item of the holder of the content
2124 * @ownerElem: the node of the holder of the content
2125 * @child: the invalid child node
2126 * @message: the optional error message
2127 * @content: the optional string describing the correct content
2128 *
2129 * Reports an error concerning the content of a schema element.
2130 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002131static void
2132xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
2133 xmlParserErrors error,
2134 xmlChar **ownerDes,
2135 xmlSchemaTypePtr ownerItem,
2136 xmlNodePtr ownerElem,
2137 xmlNodePtr child,
2138 const char *message,
2139 const char *content)
2140{
2141 xmlChar *des = NULL;
2142
2143 if (ownerDes == NULL)
2144 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
2145 else if (*ownerDes == NULL) {
2146 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
2147 des = *ownerDes;
2148 } else
2149 des = *ownerDes;
2150 if (message != NULL)
2151 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2152 "%s: %s.\n",
2153 BAD_CAST des, BAD_CAST message);
2154 else {
2155 if (content != NULL) {
2156 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2157 "%s: The content is not valid. Expected is %s.\n",
2158 BAD_CAST des, BAD_CAST content);
2159 } else {
2160 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2161 "%s: The content is not valid.\n",
2162 BAD_CAST des, NULL);
2163 }
2164 }
2165 if (ownerDes == NULL)
2166 FREE_AND_NULL(des)
2167}
2168
2169/**
2170 * xmlSchemaVIllegalAttrErr:
2171 * @ctxt: the schema validation context
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002172 * @error: the error code
Daniel Veillardc0826a72004-08-10 14:17:33 +00002173 * @attr: the illegal attribute node
2174 *
2175 * Reports an illegal attribute.
2176 */
2177static void
2178xmlSchemaVIllegalAttrErr(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002179 xmlParserErrors error,
William M. Brack2f2a6632004-08-20 23:09:47 +00002180 xmlAttrPtr attr)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002181{
2182 xmlChar *strE = NULL, *strA = NULL;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002183
2184 xmlSchemaVErr(ctxt, (xmlNodePtr) attr,
2185 error,
2186 /* XML_SCHEMAS_ERR_ATTRUNKNOWN, */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002187 "%s: The attribute '%s' is not allowed.\n",
2188 xmlSchemaFormatItemForReport(&strE, NULL, NULL, attr->parent, 0),
2189 xmlSchemaFormatNsPrefixLocal(&strA, attr->ns, attr->name));
2190 FREE_AND_NULL(strE)
2191 FREE_AND_NULL(strA)
2192}
2193
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002194
2195static int
2196xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
2197{
2198 switch (item->type) {
2199 case XML_SCHEMA_TYPE_COMPLEX:
2200 case XML_SCHEMA_TYPE_SIMPLE:
2201 case XML_SCHEMA_TYPE_GROUP:
2202 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
2203 return(1);
2204 break;
2205 case XML_SCHEMA_TYPE_ELEMENT:
2206 if ( ((xmlSchemaElementPtr) item)->flags &
2207 XML_SCHEMAS_ELEM_GLOBAL)
2208 return(1);
2209 break;
2210 case XML_SCHEMA_TYPE_ATTRIBUTE:
2211 if ( ((xmlSchemaAttributePtr) item)->flags &
2212 XML_SCHEMAS_ATTR_GLOBAL)
2213 return(1);
2214 break;
2215 /* Note that attribute groups are always global. */
2216 default:
2217 return(1);
2218 }
2219 return (0);
2220}
2221
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002222
2223static void
2224xmlSchemaStreamVCustomErr(xmlSchemaValidCtxtPtr vctxt,
2225 xmlParserErrors error,
2226 xmlSchemaNodeInfoPtr nodeInfo,
2227 xmlSchemaTypePtr type,
2228 const char *message,
2229 const xmlChar *str1,
2230 const xmlChar *str2)
2231{
2232 xmlChar *msg = NULL, *str = NULL;
2233
2234 msg = xmlStrdup(BAD_CAST "Element '");
2235
2236 if (vctxt->elemInfos[vctxt->depth] != nodeInfo) {
2237 xmlSchemaNodeInfoPtr elemInfo;
2238 /*
2239 * The node info is an attribute info.
2240 */
2241 elemInfo = vctxt->elemInfos[vctxt->depth];
2242 msg = xmlStrcat(msg, xmlSchemaFormatQName(&str,
2243 elemInfo->namespaceName, elemInfo->localName));
2244 msg = xmlStrcat(msg, BAD_CAST "', ");
2245 msg = xmlStrcat(msg, BAD_CAST "attribute '");
2246 }
2247 msg = xmlStrcat(msg, xmlSchemaFormatQName(&str,
2248 nodeInfo->namespaceName, nodeInfo->localName));
2249 msg = xmlStrcat(msg, BAD_CAST "'");
2250
2251 if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
2252 msg = xmlStrcat(msg, BAD_CAST " [");
2253 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str,
2254 NULL, type, NULL, 0));
2255 msg = xmlStrcat(msg, BAD_CAST "]");
2256 }
2257 msg = xmlStrcat(msg, BAD_CAST ": ");
2258
2259 msg = xmlStrcat(msg, (const xmlChar *) message);
2260 msg = xmlStrcat(msg, BAD_CAST ".\n");
2261 xmlSchemaVErr(vctxt, nodeInfo->node, error, (const char *) msg,
2262 str1, str2);
2263 FREE_AND_NULL(msg)
2264 FREE_AND_NULL(str)
2265}
2266
William M. Brack2f2a6632004-08-20 23:09:47 +00002267/**
2268 * xmlSchemaVCustomErr:
2269 * @ctxt: the schema validation context
2270 * @error: the error code
2271 * @node: the validated node
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002272 * @type: the schema type of the validated node
William M. Brack2f2a6632004-08-20 23:09:47 +00002273 * @message: the error message
2274 * @str1: the optional param for the message
2275 *
2276 * Reports a validation error.
2277 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002278static void
2279xmlSchemaVCustomErr(xmlSchemaValidCtxtPtr ctxt,
2280 xmlParserErrors error,
2281 xmlNodePtr node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002282 xmlSchemaTypePtr type,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002283 const char *message,
2284 const xmlChar *str1)
2285{
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002286 xmlChar *msg = NULL, *str = NULL;
2287
2288 if (node == NULL) {
2289 xmlSchemaVErr(ctxt, NULL,
2290 XML_SCHEMAV_INTERNAL,
2291 "Internal error: xmlSchemaVCustomErr, no node "
2292 "given.\n", NULL, NULL);
2293 return;
2294 }
2295 /* TODO: Are the HTML and DOCB doc nodes expected here? */
2296 if (node->type != XML_DOCUMENT_NODE) {
2297 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002298 if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002299 msg = xmlStrcat(msg, BAD_CAST " [");
2300 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
2301 msg = xmlStrcat(msg, BAD_CAST "]");
2302 }
2303 msg = xmlStrcat(msg, BAD_CAST ": ");
2304 } else
2305 msg = xmlStrdup((const xmlChar *) "");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002306 msg = xmlStrcat(msg, (const xmlChar *) message);
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002307 msg = xmlStrcat(msg, BAD_CAST ".\n");
2308 xmlSchemaVErr(ctxt, node, error, (const char *) msg, str1, NULL);
2309 FREE_AND_NULL(msg)
2310 FREE_AND_NULL(str)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002311}
2312
William M. Brack2f2a6632004-08-20 23:09:47 +00002313/**
William M. Brack2f2a6632004-08-20 23:09:47 +00002314 * xmlSchemaVWildcardErr:
2315 * @ctxt: the schema validation context
2316 * @error: the error code
2317 * @node: the validated node
2318 * @wild: the wildcard used
2319 * @message: the error message
2320 *
2321 * Reports an validation-by-wildcard error.
2322 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002323static void
2324xmlSchemaVWildcardErr(xmlSchemaValidCtxtPtr ctxt,
2325 xmlParserErrors error,
2326 xmlNodePtr node,
2327 xmlSchemaWildcardPtr wild,
2328 const char *message)
2329{
2330 xmlChar *des = NULL, *msg = NULL;
2331
2332 xmlSchemaFormatItemForReport(&des, NULL, NULL, node, 0);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00002333 msg = xmlStrdup(BAD_CAST "%s [");
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00002334 msg = xmlStrcat(msg, xmlSchemaWildcardPCToString(wild->processContents));
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002335 msg = xmlStrcat(msg, BAD_CAST " wildcard]: ");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002336 msg = xmlStrcat(msg, (const xmlChar *) message);
2337 msg = xmlStrcat(msg, BAD_CAST ".\n");
2338 xmlSchemaVErr(ctxt, node, error, (const char *) msg, BAD_CAST des, NULL);
2339 FREE_AND_NULL(des);
2340 FREE_AND_NULL(msg);
2341}
2342
2343/**
2344 * xmlSchemaVMissingAttrErr:
2345 * @ctxt: the schema validation context
2346 * @node: the parent element node of the missing attribute node
2347 * @type: the corresponding type of the attribute node
2348 *
2349 * Reports an illegal attribute.
2350 */
2351static void
2352xmlSchemaVMissingAttrErr(xmlSchemaValidCtxtPtr ctxt,
2353 xmlNodePtr elem,
2354 xmlSchemaAttributePtr type)
2355{
2356 const xmlChar *name, *uri;
2357 xmlChar *strE = NULL, *strA = NULL;
2358
2359 if (type->ref != NULL) {
2360 name = type->ref;
2361 uri = type->refNs;
2362 } else {
2363 name = type->name;
2364 uri = type->targetNamespace;
2365 }
2366 xmlSchemaVErr(ctxt, elem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002367 XML_SCHEMAV_CVC_COMPLEX_TYPE_4,
2368 /* XML_SCHEMAS_ERR_MISSING, */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002369 "%s: The attribute %s is required but missing.\n",
2370 xmlSchemaFormatItemForReport(&strE, NULL, NULL, elem, 0),
2371 xmlSchemaFormatNsUriLocal(&strA, uri, name));
2372 FREE_AND_NULL(strE)
2373 FREE_AND_NULL(strA)
2374}
2375
Daniel Veillard4255d502002-04-16 15:50:10 +00002376/************************************************************************
2377 * *
2378 * Allocation functions *
2379 * *
2380 ************************************************************************/
2381
2382/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002383 * xmlSchemaNewSchemaForParserCtxt:
William M. Brack08171912003-12-29 02:52:11 +00002384 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00002385 *
2386 * Allocate a new Schema structure.
2387 *
2388 * Returns the newly allocated structure or NULL in case or error
2389 */
2390static xmlSchemaPtr
2391xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
2392{
2393 xmlSchemaPtr ret;
2394
2395 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
2396 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002397 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002398 return (NULL);
2399 }
2400 memset(ret, 0, sizeof(xmlSchema));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002401 ret->dict = ctxt->dict;
Daniel Veillard500a1de2004-03-22 15:22:58 +00002402 xmlDictReference(ret->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00002403
2404 return (ret);
2405}
2406
2407/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002408 * xmlSchemaNewSchema:
2409 * @ctxt: a schema validation context
2410 *
2411 * Allocate a new Schema structure.
2412 *
2413 * Returns the newly allocated structure or NULL in case or error
2414 */
2415static xmlSchemaAssemblePtr
2416xmlSchemaNewAssemble(void)
2417{
2418 xmlSchemaAssemblePtr ret;
2419
2420 ret = (xmlSchemaAssemblePtr) xmlMalloc(sizeof(xmlSchemaAssemble));
2421 if (ret == NULL) {
2422 /* xmlSchemaPErrMemory(ctxt, "allocating assemble info", NULL); */
2423 return (NULL);
2424 }
2425 memset(ret, 0, sizeof(xmlSchemaAssemble));
2426 ret->items = NULL;
2427 return (ret);
2428}
2429
2430/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002431 * xmlSchemaNewFacet:
Daniel Veillard4255d502002-04-16 15:50:10 +00002432 *
2433 * Allocate a new Facet structure.
2434 *
2435 * Returns the newly allocated structure or NULL in case or error
2436 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00002437xmlSchemaFacetPtr
2438xmlSchemaNewFacet(void)
Daniel Veillard4255d502002-04-16 15:50:10 +00002439{
2440 xmlSchemaFacetPtr ret;
2441
2442 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
2443 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002444 return (NULL);
2445 }
2446 memset(ret, 0, sizeof(xmlSchemaFacet));
2447
2448 return (ret);
2449}
2450
2451/**
2452 * xmlSchemaNewAnnot:
William M. Brack08171912003-12-29 02:52:11 +00002453 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00002454 * @node: a node
2455 *
2456 * Allocate a new annotation structure.
2457 *
2458 * Returns the newly allocated structure or NULL in case or error
2459 */
2460static xmlSchemaAnnotPtr
2461xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
2462{
2463 xmlSchemaAnnotPtr ret;
2464
2465 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
2466 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002467 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
Daniel Veillard4255d502002-04-16 15:50:10 +00002468 return (NULL);
2469 }
2470 memset(ret, 0, sizeof(xmlSchemaAnnot));
2471 ret->content = node;
2472 return (ret);
2473}
2474
2475/**
Daniel Veillardfdc91562002-07-01 21:52:03 +00002476 * xmlSchemaFreeAnnot:
2477 * @annot: a schema type structure
2478 *
2479 * Deallocate a annotation structure
2480 */
2481static void
2482xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
2483{
2484 if (annot == NULL)
2485 return;
2486 xmlFree(annot);
2487}
2488
2489/**
Daniel Veillard1d913862003-11-21 00:28:39 +00002490 * xmlSchemaFreeImport:
2491 * @import: a schema import structure
2492 *
2493 * Deallocate an import structure
2494 */
2495static void
2496xmlSchemaFreeImport(xmlSchemaImportPtr import)
2497{
2498 if (import == NULL)
2499 return;
2500
2501 xmlSchemaFree(import->schema);
William M. Brack2f2a6632004-08-20 23:09:47 +00002502 xmlFreeDoc(import->doc);
Daniel Veillard1d913862003-11-21 00:28:39 +00002503 xmlFree(import);
2504}
2505
2506/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002507 * xmlSchemaFreeInclude:
2508 * @include: a schema include structure
2509 *
2510 * Deallocate an include structure
2511 */
2512static void
2513xmlSchemaFreeInclude(xmlSchemaIncludePtr include)
2514{
2515 if (include == NULL)
2516 return;
2517
2518 xmlFreeDoc(include->doc);
2519 xmlFree(include);
2520}
2521
2522/**
2523 * xmlSchemaFreeIncludeList:
2524 * @includes: a schema include list
2525 *
2526 * Deallocate an include structure
2527 */
2528static void
2529xmlSchemaFreeIncludeList(xmlSchemaIncludePtr includes)
2530{
2531 xmlSchemaIncludePtr next;
2532
2533 while (includes != NULL) {
2534 next = includes->next;
2535 xmlSchemaFreeInclude(includes);
2536 includes = next;
2537 }
2538}
2539
2540/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002541 * xmlSchemaFreeNotation:
2542 * @schema: a schema notation structure
2543 *
2544 * Deallocate a Schema Notation structure.
2545 */
2546static void
2547xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
2548{
2549 if (nota == NULL)
2550 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002551 xmlFree(nota);
2552}
2553
2554/**
2555 * xmlSchemaFreeAttribute:
2556 * @schema: a schema attribute structure
2557 *
2558 * Deallocate a Schema Attribute structure.
2559 */
2560static void
2561xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
2562{
2563 if (attr == NULL)
2564 return;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002565 if (attr->annot != NULL)
2566 xmlSchemaFreeAnnot(attr->annot);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002567 if (attr->defVal != NULL)
2568 xmlSchemaFreeValue(attr->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00002569 xmlFree(attr);
2570}
2571
2572/**
Daniel Veillard3646d642004-06-02 19:19:14 +00002573 * xmlSchemaFreeWildcardNsSet:
2574 * set: a schema wildcard namespace
2575 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00002576 * Deallocates a list of wildcard constraint structures.
Daniel Veillard3646d642004-06-02 19:19:14 +00002577 */
2578static void
2579xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
2580{
2581 xmlSchemaWildcardNsPtr next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002582
Daniel Veillard3646d642004-06-02 19:19:14 +00002583 while (set != NULL) {
2584 next = set->next;
2585 xmlFree(set);
2586 set = next;
2587 }
2588}
2589
2590/**
2591 * xmlSchemaFreeWildcard:
Daniel Veillard01fa6152004-06-29 17:04:39 +00002592 * @wildcard: a wildcard structure
Daniel Veillard3646d642004-06-02 19:19:14 +00002593 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00002594 * Deallocates a wildcard structure.
Daniel Veillard3646d642004-06-02 19:19:14 +00002595 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00002596void
Daniel Veillard3646d642004-06-02 19:19:14 +00002597xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
2598{
2599 if (wildcard == NULL)
2600 return;
2601 if (wildcard->annot != NULL)
2602 xmlSchemaFreeAnnot(wildcard->annot);
2603 if (wildcard->nsSet != NULL)
2604 xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
2605 if (wildcard->negNsSet != NULL)
2606 xmlFree(wildcard->negNsSet);
2607 xmlFree(wildcard);
2608}
2609
2610/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002611 * xmlSchemaFreeAttributeGroup:
2612 * @schema: a schema attribute group structure
2613 *
2614 * Deallocate a Schema Attribute Group structure.
2615 */
2616static void
2617xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attr)
2618{
2619 if (attr == NULL)
2620 return;
Daniel Veillard3646d642004-06-02 19:19:14 +00002621 if (attr->annot != NULL)
2622 xmlSchemaFreeAnnot(attr->annot);
2623 if ((attr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) &&
2624 (attr->attributeWildcard != NULL))
2625 xmlSchemaFreeWildcard(attr->attributeWildcard);
2626
Daniel Veillard4255d502002-04-16 15:50:10 +00002627 xmlFree(attr);
2628}
2629
2630/**
Daniel Veillard3646d642004-06-02 19:19:14 +00002631 * xmlSchemaFreeAttributeUseList:
Daniel Veillard01fa6152004-06-29 17:04:39 +00002632 * @attrUse: an attribute link
Daniel Veillard3646d642004-06-02 19:19:14 +00002633 *
2634 * Deallocate a list of schema attribute uses.
2635 */
2636static void
2637xmlSchemaFreeAttributeUseList(xmlSchemaAttributeLinkPtr attrUse)
2638{
2639 xmlSchemaAttributeLinkPtr next;
2640
2641 while (attrUse != NULL) {
2642 next = attrUse->next;
2643 xmlFree(attrUse);
2644 attrUse = next;
2645 }
2646}
2647
2648/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00002649 * xmlSchemaFreeTypeLinkList:
2650 * @alink: a type link
2651 *
2652 * Deallocate a list of types.
2653 */
2654static void
2655xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
2656{
2657 xmlSchemaTypeLinkPtr next;
2658
2659 while (link != NULL) {
2660 next = link->next;
2661 xmlFree(link);
2662 link = next;
2663 }
2664}
2665
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00002666#ifdef IDC_ENABLED
2667static void
2668xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
2669{
2670 xmlSchemaIDCStateObjPtr next;
2671 while (sto != NULL) {
2672 next = sto->next;
2673 if (sto->history != NULL)
2674 xmlFree(sto->history);
2675 if (sto->xpathCtxt != NULL)
2676 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
2677 xmlFree(sto);
2678 sto = next;
2679 }
2680}
2681
2682/**
2683 * xmlSchemaFreeIDC:
2684 * @idc: a identity-constraint definition
2685 *
2686 * Deallocates an identity-constraint definition.
2687 */
2688static void
2689xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)
2690{
2691 xmlSchemaIDCSelectPtr cur, prev;
2692
2693 if (idcDef == NULL)
2694 return;
2695 if (idcDef->annot != NULL)
2696 xmlSchemaFreeAnnot(idcDef->annot);
2697 if (idcDef->ref != NULL)
2698 xmlFree(idcDef->ref);
2699 /* Selector */
2700 if (idcDef->selector != NULL) {
2701 if (idcDef->selector->xpathComp != NULL)
2702 xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp);
2703 xmlFree(idcDef->selector);
2704 }
2705 /* Fields */
2706 if (idcDef->fields != NULL) {
2707 cur = idcDef->fields;
2708 do {
2709 prev = cur;
2710 cur = cur->next;
2711 if (prev->xpathComp != NULL)
2712 xmlFreePattern((xmlPatternPtr) prev->xpathComp);
2713 xmlFree(prev);
2714 } while (cur != NULL);
2715 }
2716 xmlFree(idcDef);
2717}
2718#endif /* IDC_ENABLED */
2719
Daniel Veillard01fa6152004-06-29 17:04:39 +00002720/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002721 * xmlSchemaFreeElement:
2722 * @schema: a schema element structure
2723 *
2724 * Deallocate a Schema Element structure.
2725 */
2726static void
2727xmlSchemaFreeElement(xmlSchemaElementPtr elem)
2728{
2729 if (elem == NULL)
2730 return;
Daniel Veillard32370232002-10-16 14:08:14 +00002731 if (elem->annot != NULL)
2732 xmlSchemaFreeAnnot(elem->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00002733 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002734 xmlRegFreeRegexp(elem->contModel);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002735 if (elem->defVal != NULL)
2736 xmlSchemaFreeValue(elem->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00002737 xmlFree(elem);
2738}
2739
2740/**
2741 * xmlSchemaFreeFacet:
2742 * @facet: a schema facet structure
2743 *
2744 * Deallocate a Schema Facet structure.
2745 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00002746void
Daniel Veillard4255d502002-04-16 15:50:10 +00002747xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
2748{
2749 if (facet == NULL)
2750 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002751 if (facet->val != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002752 xmlSchemaFreeValue(facet->val);
Daniel Veillard4255d502002-04-16 15:50:10 +00002753 if (facet->regexp != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002754 xmlRegFreeRegexp(facet->regexp);
Daniel Veillardfdc91562002-07-01 21:52:03 +00002755 if (facet->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002756 xmlSchemaFreeAnnot(facet->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00002757 xmlFree(facet);
2758}
2759
2760/**
2761 * xmlSchemaFreeType:
2762 * @type: a schema type structure
2763 *
2764 * Deallocate a Schema Type structure.
2765 */
2766void
2767xmlSchemaFreeType(xmlSchemaTypePtr type)
2768{
2769 if (type == NULL)
2770 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002771 if (type->annot != NULL)
Daniel Veillard32370232002-10-16 14:08:14 +00002772 xmlSchemaFreeAnnot(type->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00002773 if (type->facets != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002774 xmlSchemaFacetPtr facet, next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002775
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002776 facet = type->facets;
2777 while (facet != NULL) {
2778 next = facet->next;
2779 xmlSchemaFreeFacet(facet);
2780 facet = next;
2781 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002782 }
Daniel Veillard3646d642004-06-02 19:19:14 +00002783 if (type->type != XML_SCHEMA_TYPE_BASIC) {
2784 if (type->attributeUses != NULL)
2785 xmlSchemaFreeAttributeUseList(type->attributeUses);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002786 if ((type->attributeWildcard != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +00002787 ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002788 (type->flags & XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD))) {
2789 /*
2790 * NOTE: The only case where an attribute wildcard
2791 * is not owned, is if a complex type inherits it
2792 * from a base type.
2793 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002794 xmlSchemaFreeWildcard(type->attributeWildcard);
2795 }
2796 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00002797 if (type->memberTypes != NULL)
2798 xmlSchemaFreeTypeLinkList(type->memberTypes);
2799 if (type->facetSet != NULL) {
2800 xmlSchemaFacetLinkPtr next, link;
2801
2802 link = type->facetSet;
2803 do {
2804 next = link->next;
2805 xmlFree(link);
2806 link = next;
2807 } while (link != NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002808 }
2809 if (type->contModel != NULL)
2810 xmlRegFreeRegexp(type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00002811 xmlFree(type);
2812}
2813
2814/**
Daniel Veillardb0f397e2003-12-23 23:30:53 +00002815 * xmlSchemaFreeTypeList:
2816 * @type: a schema type structure
2817 *
2818 * Deallocate a Schema Type structure.
2819 */
2820static void
2821xmlSchemaFreeTypeList(xmlSchemaTypePtr type)
2822{
2823 xmlSchemaTypePtr next;
2824
2825 while (type != NULL) {
2826 next = type->redef;
2827 xmlSchemaFreeType(type);
2828 type = next;
2829 }
2830}
2831
2832/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002833 * xmlSchemaFree:
2834 * @schema: a schema structure
2835 *
2836 * Deallocate a Schema structure.
2837 */
2838void
2839xmlSchemaFree(xmlSchemaPtr schema)
2840{
2841 if (schema == NULL)
2842 return;
2843
Daniel Veillard4255d502002-04-16 15:50:10 +00002844 if (schema->notaDecl != NULL)
2845 xmlHashFree(schema->notaDecl,
2846 (xmlHashDeallocator) xmlSchemaFreeNotation);
2847 if (schema->attrDecl != NULL)
2848 xmlHashFree(schema->attrDecl,
2849 (xmlHashDeallocator) xmlSchemaFreeAttribute);
2850 if (schema->attrgrpDecl != NULL)
2851 xmlHashFree(schema->attrgrpDecl,
2852 (xmlHashDeallocator) xmlSchemaFreeAttributeGroup);
2853 if (schema->elemDecl != NULL)
2854 xmlHashFree(schema->elemDecl,
2855 (xmlHashDeallocator) xmlSchemaFreeElement);
2856 if (schema->typeDecl != NULL)
2857 xmlHashFree(schema->typeDecl,
Daniel Veillardb0f397e2003-12-23 23:30:53 +00002858 (xmlHashDeallocator) xmlSchemaFreeTypeList);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00002859 if (schema->groupDecl != NULL)
2860 xmlHashFree(schema->groupDecl,
2861 (xmlHashDeallocator) xmlSchemaFreeType);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00002862#ifdef IDC_ENABLED
2863 if (schema->idcDef != NULL)
2864 xmlHashFree(schema->idcDef,
2865 (xmlHashDeallocator) xmlSchemaFreeIDC);
2866#endif
Daniel Veillard1d913862003-11-21 00:28:39 +00002867 if (schema->schemasImports != NULL)
2868 xmlHashFree(schema->schemasImports,
2869 (xmlHashDeallocator) xmlSchemaFreeImport);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002870 if (schema->includes != NULL) {
2871 xmlSchemaFreeIncludeList((xmlSchemaIncludePtr) schema->includes);
2872 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002873 if (schema->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002874 xmlSchemaFreeAnnot(schema->annot);
Daniel Veillarddda22c12004-01-24 08:31:30 +00002875 if (schema->doc != NULL && !schema->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002876 xmlFreeDoc(schema->doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002877 xmlDictFree(schema->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00002878 xmlFree(schema);
2879}
2880
2881/************************************************************************
2882 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00002883 * Debug functions *
2884 * *
2885 ************************************************************************/
2886
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002887#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002888
Daniel Veillard4255d502002-04-16 15:50:10 +00002889/**
2890 * xmlSchemaElementDump:
2891 * @elem: an element
2892 * @output: the file output
2893 *
2894 * Dump the element
2895 */
2896static void
2897xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002898 const xmlChar * name ATTRIBUTE_UNUSED,
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002899 const xmlChar * namespace ATTRIBUTE_UNUSED,
2900 const xmlChar * context ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00002901{
2902 if (elem == NULL)
2903 return;
2904
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002905 if (elem->flags & XML_SCHEMAS_ELEM_REF) {
2906 fprintf(output, "Particle: %s", name);
2907 fprintf(output, ", term element: %s", elem->ref);
2908 if (elem->refNs != NULL)
2909 fprintf(output, " ns %s", elem->refNs);
2910 } else {
2911 fprintf(output, "Element");
2912 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
2913 fprintf(output, " (global)");
2914 fprintf(output, ": %s ", elem->name);
2915 if (namespace != NULL)
2916 fprintf(output, "ns %s", namespace);
2917 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002918 fprintf(output, "\n");
2919 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002920 fprintf(output, " min %d ", elem->minOccurs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002921 if (elem->maxOccurs >= UNBOUNDED)
2922 fprintf(output, "max: unbounded\n");
2923 else if (elem->maxOccurs != 1)
2924 fprintf(output, "max: %d\n", elem->maxOccurs);
2925 else
2926 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002927 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002928 /*
2929 * Misc other properties.
2930 */
2931 if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
2932 (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
2933 (elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
2934 (elem->flags & XML_SCHEMAS_ELEM_DEFAULT) ||
2935 (elem->id != NULL)) {
2936 fprintf(output, " props: ");
2937 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
2938 fprintf(output, "[fixed] ");
2939 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
2940 fprintf(output, "[default] ");
2941 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
2942 fprintf(output, "[abstract] ");
2943 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
2944 fprintf(output, "[nillable] ");
2945 if (elem->id != NULL)
2946 fprintf(output, "[id: '%s'] ", elem->id);
2947 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002948 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002949 /*
2950 * Default/fixed value.
2951 */
Daniel Veillard4255d502002-04-16 15:50:10 +00002952 if (elem->value != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002953 fprintf(output, " value: '%s'\n", elem->value);
2954 /*
2955 * Type.
2956 */
2957 if (elem->namedType != NULL) {
2958 fprintf(output, " type: %s ", elem->namedType);
2959 if (elem->namedTypeNs != NULL)
2960 fprintf(output, "ns %s\n", elem->namedTypeNs);
2961 else
2962 fprintf(output, "\n");
2963 }
2964 /*
2965 * Substitution group.
2966 */
2967 if (elem->substGroup != NULL) {
2968 fprintf(output, " substitutionGroup: %s ", elem->substGroup);
2969 if (elem->substGroupNs != NULL)
2970 fprintf(output, "ns %s\n", elem->substGroupNs);
2971 else
2972 fprintf(output, "\n");
2973 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002974}
2975
2976/**
2977 * xmlSchemaAnnotDump:
2978 * @output: the file output
2979 * @annot: a annotation
2980 *
2981 * Dump the annotation
2982 */
2983static void
2984xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
2985{
2986 xmlChar *content;
2987
2988 if (annot == NULL)
2989 return;
2990
2991 content = xmlNodeGetContent(annot->content);
2992 if (content != NULL) {
2993 fprintf(output, " Annot: %s\n", content);
2994 xmlFree(content);
2995 } else
2996 fprintf(output, " Annot: empty\n");
2997}
2998
2999/**
3000 * xmlSchemaTypeDump:
3001 * @output: the file output
3002 * @type: a type structure
3003 *
3004 * Dump a SchemaType structure
3005 */
3006static void
3007xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
3008{
3009 if (type == NULL) {
3010 fprintf(output, "Type: NULL\n");
3011 return;
3012 }
3013 fprintf(output, "Type: ");
3014 if (type->name != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003015 fprintf(output, "%s ", type->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003016 else
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003017 fprintf(output, "no name ");
3018 if (type->targetNamespace != NULL)
3019 fprintf(output, "ns %s ", type->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003020 switch (type->type) {
3021 case XML_SCHEMA_TYPE_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003022 fprintf(output, "[basic] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003023 break;
3024 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003025 fprintf(output, "[simple] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003026 break;
3027 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003028 fprintf(output, "[complex] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003029 break;
3030 case XML_SCHEMA_TYPE_SEQUENCE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003031 fprintf(output, "[sequence] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003032 break;
3033 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003034 fprintf(output, "[choice] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003035 break;
3036 case XML_SCHEMA_TYPE_ALL:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003037 fprintf(output, "[all] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003038 break;
3039 case XML_SCHEMA_TYPE_UR:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003040 fprintf(output, "[ur] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003041 break;
3042 case XML_SCHEMA_TYPE_RESTRICTION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003043 fprintf(output, "[restriction] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003044 break;
3045 case XML_SCHEMA_TYPE_EXTENSION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003046 fprintf(output, "[extension] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003047 break;
3048 default:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003049 fprintf(output, "[unknown type %d] ", type->type);
Daniel Veillard4255d502002-04-16 15:50:10 +00003050 break;
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003051 }
3052 fprintf(output, "content: ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003053 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003054 case XML_SCHEMA_CONTENT_UNKNOWN:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003055 fprintf(output, "[unknown] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003056 break;
3057 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003058 fprintf(output, "[empty] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003059 break;
3060 case XML_SCHEMA_CONTENT_ELEMENTS:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003061 fprintf(output, "[element] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003062 break;
3063 case XML_SCHEMA_CONTENT_MIXED:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003064 fprintf(output, "[mixed] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003065 break;
3066 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003067 /* not used. */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003068 break;
3069 case XML_SCHEMA_CONTENT_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003070 fprintf(output, "[basic] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003071 break;
3072 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003073 fprintf(output, "[simple] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003074 break;
3075 case XML_SCHEMA_CONTENT_ANY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003076 fprintf(output, "[any] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003077 break;
Daniel Veillard4255d502002-04-16 15:50:10 +00003078 }
3079 fprintf(output, "\n");
3080 if ((type->minOccurs != 1) || (type->maxOccurs != 1)) {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003081 fprintf(output, " min: %d ", type->minOccurs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003082 if (type->maxOccurs >= UNBOUNDED)
3083 fprintf(output, "max: unbounded\n");
3084 else if (type->maxOccurs != 1)
3085 fprintf(output, "max: %d\n", type->maxOccurs);
3086 else
3087 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00003088 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003089 if (type->base != NULL) {
3090 fprintf(output, " base type: %s", type->base);
3091 if (type->baseNs != NULL)
3092 fprintf(output, " ns %s\n", type->baseNs);
3093 else
3094 fprintf(output, "\n");
3095 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003096 if (type->annot != NULL)
3097 xmlSchemaAnnotDump(output, type->annot);
3098 if (type->subtypes != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003099 xmlSchemaTypePtr sub = type->subtypes;
Daniel Veillard4255d502002-04-16 15:50:10 +00003100
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003101 fprintf(output, " subtypes: ");
3102 while (sub != NULL) {
3103 fprintf(output, "%s ", sub->name);
3104 sub = sub->next;
3105 }
3106 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00003107 }
3108
3109}
3110
3111/**
3112 * xmlSchemaDump:
3113 * @output: the file output
3114 * @schema: a schema structure
3115 *
3116 * Dump a Schema structure.
3117 */
3118void
3119xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
3120{
Daniel Veillardce682bc2004-11-05 17:22:25 +00003121 if (output == NULL)
3122 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003123 if (schema == NULL) {
3124 fprintf(output, "Schemas: NULL\n");
3125 return;
3126 }
3127 fprintf(output, "Schemas: ");
3128 if (schema->name != NULL)
3129 fprintf(output, "%s, ", schema->name);
3130 else
3131 fprintf(output, "no name, ");
3132 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00003133 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003134 else
3135 fprintf(output, "no target namespace");
3136 fprintf(output, "\n");
3137 if (schema->annot != NULL)
3138 xmlSchemaAnnotDump(output, schema->annot);
3139
3140 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
3141 output);
3142 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003143 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00003144}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003145
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003146#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00003147#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003148/**
3149 * xmlSchemaDebugDumpIDCTable:
3150 * @vctxt: the WXS validation context
3151 *
3152 * Displays the current IDC table for debug purposes.
3153 */
3154static void
3155xmlSchemaDebugDumpIDCTable(FILE * output,
3156 const xmlChar *namespaceName,
3157 const xmlChar *localName,
3158 xmlSchemaPSVIIDCBindingPtr bind)
3159{
3160 xmlChar *str = NULL, *value;
3161 xmlSchemaPSVIIDCNodePtr tab;
3162 xmlSchemaPSVIIDCKeyPtr key;
3163 int i, j, res;
3164
3165 fprintf(output, "IDC: TABLES on %s\n",
3166 xmlSchemaFormatNsUriLocal(&str, namespaceName, localName));
3167 FREE_AND_NULL(str)
3168
3169 if (bind == NULL)
3170 return;
3171 do {
3172 fprintf(output, "IDC: BINDING %s\n",
3173 xmlSchemaFormatNsUriLocal(&str, bind->definition->targetNamespace,
3174 bind->definition->name));
3175 FREE_AND_NULL(str)
3176 for (i = 0; i < bind->nbNodes; i++) {
3177 tab = bind->nodeTable[i];
3178 fprintf(output, " ( ");
3179 for (j = 0; j < bind->definition->nbFields; j++) {
3180 key = tab->keys[j];
3181 if ((key != NULL) && (key->compValue != NULL)) {
3182#ifdef IDC_VALUE_SUPPORT
3183 res = xmlSchemaGetCanonValue(key->compValue, &value);
3184#else
3185 value = xmlStrdup(BAD_CAST "dummy-value");
3186 res = 0;
3187#endif
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003188 if (res >= 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003189 fprintf(output, "\"%s\" ", value);
3190 else
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003191 fprintf(output, "CANON-VALUE-FAILED ");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003192 if (res == 0)
3193 FREE_AND_NULL(value)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003194 } else if (key != NULL)
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003195 fprintf(output, "(no val), ");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003196 else
3197 fprintf(output, "(key missing), ");
3198 }
3199 fprintf(output, ")\n");
3200 }
3201 bind = bind->next;
3202 } while (bind != NULL);
3203}
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00003204#endif /* DEBUG_IDC */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003205#endif /* IDC_ENABLED */
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00003206#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +00003207
3208/************************************************************************
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003209 * *
3210 * Utilities *
3211 * *
3212 ************************************************************************/
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003213
Daniel Veillardc0826a72004-08-10 14:17:33 +00003214/**
3215 * xmlSchemaGetPropNode:
3216 * @node: the element node
3217 * @name: the name of the attribute
3218 *
3219 * Seeks an attribute with a name of @name in
3220 * no namespace.
3221 *
3222 * Returns the attribute or NULL if not present.
3223 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003224static xmlAttrPtr
Daniel Veillardc0826a72004-08-10 14:17:33 +00003225xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
Daniel Veillard01fa6152004-06-29 17:04:39 +00003226{
3227 xmlAttrPtr prop;
3228
Daniel Veillardc0826a72004-08-10 14:17:33 +00003229 if ((node == NULL) || (name == NULL))
3230 return(NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003231 prop = node->properties;
3232 while (prop != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00003233 if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
3234 return(prop);
3235 prop = prop->next;
3236 }
3237 return (NULL);
3238}
3239
3240/**
3241 * xmlSchemaGetPropNodeNs:
3242 * @node: the element node
3243 * @uri: the uri
3244 * @name: the name of the attribute
3245 *
3246 * Seeks an attribute with a local name of @name and
3247 * a namespace URI of @uri.
3248 *
3249 * Returns the attribute or NULL if not present.
3250 */
3251static xmlAttrPtr
3252xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
3253{
3254 xmlAttrPtr prop;
3255
3256 if ((node == NULL) || (name == NULL))
3257 return(NULL);
3258 prop = node->properties;
3259 while (prop != NULL) {
3260 if ((prop->ns != NULL) &&
3261 xmlStrEqual(prop->name, BAD_CAST name) &&
3262 xmlStrEqual(prop->ns->href, BAD_CAST uri))
Daniel Veillard01fa6152004-06-29 17:04:39 +00003263 return(prop);
3264 prop = prop->next;
3265 }
3266 return (NULL);
3267}
3268
3269static const xmlChar *
3270xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3271{
3272 xmlChar *val;
3273 const xmlChar *ret;
3274
3275 val = xmlNodeGetContent(node);
3276 if (val == NULL)
3277 return(NULL);
3278 ret = xmlDictLookup(ctxt->dict, val, -1);
3279 xmlFree(val);
3280 return(ret);
3281}
3282
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003283/**
3284 * xmlSchemaGetProp:
3285 * @ctxt: the parser context
3286 * @node: the node
3287 * @name: the property name
3288 *
3289 * Read a attribute value and internalize the string
3290 *
3291 * Returns the string or NULL if not present.
3292 */
3293static const xmlChar *
3294xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
3295 const char *name)
3296{
3297 xmlChar *val;
3298 const xmlChar *ret;
3299
3300 val = xmlGetProp(node, BAD_CAST name);
3301 if (val == NULL)
3302 return(NULL);
3303 ret = xmlDictLookup(ctxt->dict, val, -1);
3304 xmlFree(val);
3305 return(ret);
3306}
3307
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003308/************************************************************************
Daniel Veillard4255d502002-04-16 15:50:10 +00003309 * *
3310 * Parsing functions *
3311 * *
3312 ************************************************************************/
3313
3314/**
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003315 * xmlSchemaGetElem:
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003316 * @schema: the schema context
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003317 * @name: the element name
3318 * @ns: the element namespace
3319 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003320 * Lookup a global element declaration in the schema.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003321 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003322 * Returns the element declaration or NULL if not found.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003323 */
3324static xmlSchemaElementPtr
3325xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003326 const xmlChar * namespace)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003327{
3328 xmlSchemaElementPtr ret;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003329
3330 if ((name == NULL) || (schema == NULL))
3331 return (NULL);
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003332
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003333 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003334 if ((ret != NULL) &&
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003335 (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003336 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00003337 } else
3338 ret = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00003339 /*
3340 * This one was removed, since top level element declarations have
3341 * the target namespace specified in targetNamespace of the <schema>
3342 * information element, even if elementFormDefault is "unqualified".
3343 */
3344
3345 /* else if ((schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003346 if (xmlStrEqual(namespace, schema->targetNamespace))
3347 ret = xmlHashLookup2(schema->elemDecl, name, NULL);
3348 else
3349 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003350 if ((ret != NULL) &&
3351 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003352 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003353 }
William M. Bracke7091952004-05-11 15:09:58 +00003354 */
Daniel Veillard3646d642004-06-02 19:19:14 +00003355
William M. Brack2f2a6632004-08-20 23:09:47 +00003356 /*
3357 * Removed since imported components will be hold by the main schema only.
3358 *
Daniel Veillard3646d642004-06-02 19:19:14 +00003359 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003360 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003361 else
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003362 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003363 if (import != NULL) {
Daniel Veillardf2a12832003-11-24 13:04:35 +00003364 ret = xmlSchemaGetElem(import->schema, name, namespace, level + 1);
Daniel Veillard3646d642004-06-02 19:19:14 +00003365 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
3366 return (ret);
3367 } else
3368 ret = NULL;
3369 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003370 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003371#ifdef DEBUG
3372 if (ret == NULL) {
3373 if (namespace == NULL)
3374 fprintf(stderr, "Unable to lookup type %s", name);
3375 else
3376 fprintf(stderr, "Unable to lookup type %s:%s", name,
3377 namespace);
3378 }
3379#endif
3380 return (ret);
3381}
3382
3383/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003384 * xmlSchemaGetType:
3385 * @schema: the schemas context
3386 * @name: the type name
3387 * @ns: the type namespace
3388 *
3389 * Lookup a type in the schemas or the predefined types
3390 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003391 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +00003392 */
3393static xmlSchemaTypePtr
3394xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003395 const xmlChar * namespace)
3396{
Daniel Veillard4255d502002-04-16 15:50:10 +00003397 xmlSchemaTypePtr ret;
3398
3399 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003400 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003401 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003402 ret = xmlHashLookup2(schema->typeDecl, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003403 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003404 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003405 }
3406 ret = xmlSchemaGetPredefinedType(name, namespace);
Daniel Veillard1d913862003-11-21 00:28:39 +00003407 if (ret != NULL)
3408 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00003409 /*
3410 * Removed, since the imported components will be grafted on the
3411 * main schema only.
Daniel Veillard3646d642004-06-02 19:19:14 +00003412 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003413 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003414 else
Daniel Veillard1d913862003-11-21 00:28:39 +00003415 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003416 if (import != NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00003417 ret = xmlSchemaGetType(import->schema, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003418 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
3419 return (ret);
3420 } else
3421 ret = NULL;
3422 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003423 */
Daniel Veillard4255d502002-04-16 15:50:10 +00003424#ifdef DEBUG
3425 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003426 if (namespace == NULL)
3427 fprintf(stderr, "Unable to lookup type %s", name);
3428 else
3429 fprintf(stderr, "Unable to lookup type %s:%s", name,
3430 namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003431 }
3432#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003433 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003434}
3435
Daniel Veillard3646d642004-06-02 19:19:14 +00003436/**
3437 * xmlSchemaGetAttribute:
3438 * @schema: the context of the schema
3439 * @name: the name of the attribute
3440 * @ns: the target namespace of the attribute
3441 *
3442 * Lookup a an attribute in the schema or imported schemas
3443 *
3444 * Returns the attribute declaration or NULL if not found.
3445 */
3446static xmlSchemaAttributePtr
3447xmlSchemaGetAttribute(xmlSchemaPtr schema, const xmlChar * name,
3448 const xmlChar * namespace)
3449{
3450 xmlSchemaAttributePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00003451
3452 if ((name == NULL) || (schema == NULL))
3453 return (NULL);
3454
3455
3456 ret = xmlHashLookup2(schema->attrDecl, name, namespace);
3457 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL))
3458 return (ret);
3459 else
3460 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00003461 /*
3462 * Removed, since imported components will be hold by the main schema only.
3463 *
Daniel Veillard3646d642004-06-02 19:19:14 +00003464 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003465 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003466 else
3467 import = xmlHashLookup(schema->schemasImports, namespace);
3468 if (import != NULL) {
3469 ret = xmlSchemaGetAttribute(import->schema, name, namespace);
3470 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL)) {
3471 return (ret);
3472 } else
3473 ret = NULL;
3474 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003475 */
Daniel Veillard3646d642004-06-02 19:19:14 +00003476#ifdef DEBUG
3477 if (ret == NULL) {
3478 if (namespace == NULL)
3479 fprintf(stderr, "Unable to lookup attribute %s", name);
3480 else
3481 fprintf(stderr, "Unable to lookup attribute %s:%s", name,
3482 namespace);
3483 }
3484#endif
3485 return (ret);
3486}
3487
3488/**
3489 * xmlSchemaGetAttributeGroup:
3490 * @schema: the context of the schema
3491 * @name: the name of the attribute group
3492 * @ns: the target namespace of the attribute group
3493 *
3494 * Lookup a an attribute group in the schema or imported schemas
3495 *
3496 * Returns the attribute group definition or NULL if not found.
3497 */
3498static xmlSchemaAttributeGroupPtr
3499xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
3500 const xmlChar * namespace)
3501{
3502 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00003503
3504 if ((name == NULL) || (schema == NULL))
3505 return (NULL);
3506
3507
3508 ret = xmlHashLookup2(schema->attrgrpDecl, name, namespace);
3509 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
3510 return (ret);
3511 else
3512 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00003513 /*
3514 * Removed since imported components will be hold by the main schema only.
3515 *
Daniel Veillard3646d642004-06-02 19:19:14 +00003516 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003517 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003518 else
3519 import = xmlHashLookup(schema->schemasImports, namespace);
3520 if (import != NULL) {
3521 ret = xmlSchemaGetAttributeGroup(import->schema, name, namespace);
3522 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
3523 return (ret);
3524 else
3525 ret = NULL;
3526 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003527 */
Daniel Veillard3646d642004-06-02 19:19:14 +00003528#ifdef DEBUG
3529 if (ret == NULL) {
3530 if (namespace == NULL)
3531 fprintf(stderr, "Unable to lookup attribute group %s", name);
3532 else
3533 fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
3534 namespace);
3535 }
3536#endif
3537 return (ret);
3538}
3539
3540/**
3541 * xmlSchemaGetGroup:
3542 * @schema: the context of the schema
3543 * @name: the name of the group
3544 * @ns: the target namespace of the group
3545 *
3546 * Lookup a group in the schema or imported schemas
3547 *
3548 * Returns the group definition or NULL if not found.
3549 */
3550static xmlSchemaTypePtr
3551xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
3552 const xmlChar * namespace)
3553{
3554 xmlSchemaTypePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00003555
3556 if ((name == NULL) || (schema == NULL))
3557 return (NULL);
3558
3559
3560 ret = xmlHashLookup2(schema->groupDecl, name, namespace);
3561 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
3562 return (ret);
3563 else
3564 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00003565 /*
3566 * Removed since imported components will be hold by the main schema only.
3567 *
Daniel Veillard3646d642004-06-02 19:19:14 +00003568 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003569 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003570 else
3571 import = xmlHashLookup(schema->schemasImports, namespace);
3572 if (import != NULL) {
3573 ret = xmlSchemaGetGroup(import->schema, name, namespace);
3574 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
3575 return (ret);
3576 else
3577 ret = NULL;
3578 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003579 */
Daniel Veillard3646d642004-06-02 19:19:14 +00003580#ifdef DEBUG
3581 if (ret == NULL) {
3582 if (namespace == NULL)
3583 fprintf(stderr, "Unable to lookup group %s", name);
3584 else
3585 fprintf(stderr, "Unable to lookup group %s:%s", name,
3586 namespace);
3587 }
3588#endif
3589 return (ret);
3590}
3591
Daniel Veillard4255d502002-04-16 15:50:10 +00003592/************************************************************************
3593 * *
3594 * Parsing functions *
3595 * *
3596 ************************************************************************/
3597
3598#define IS_BLANK_NODE(n) \
3599 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content)))
3600
3601/**
3602 * xmlSchemaIsBlank:
3603 * @str: a string
3604 *
3605 * Check if a string is ignorable
3606 *
3607 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
3608 */
3609static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003610xmlSchemaIsBlank(xmlChar * str)
3611{
Daniel Veillard4255d502002-04-16 15:50:10 +00003612 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003613 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003614 while (*str != 0) {
William M. Brack76e95df2003-10-18 16:20:14 +00003615 if (!(IS_BLANK_CH(*str)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003616 return (0);
3617 str++;
Daniel Veillard4255d502002-04-16 15:50:10 +00003618 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003619 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003620}
3621
3622/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003623 * xmlSchemaAddAssembledItem:
3624 * @ctxt: a schema parser context
3625 * @schema: the schema being built
3626 * @item: the item
3627 *
3628 * Add a item to the schema's list of current items.
3629 * This is used if the schema was already constructed and
3630 * new schemata need to be added to it.
3631 * *WARNING* this interface is highly subject to change.
3632 *
3633 * Returns 0 if suceeds and -1 if an internal error occurs.
3634 */
3635static int
3636xmlSchemaAddAssembledItem(xmlSchemaParserCtxtPtr ctxt,
3637 xmlSchemaTypePtr item)
3638{
3639 static int growSize = 100;
3640 xmlSchemaAssemblePtr ass;
3641
3642 ass = ctxt->assemble;
3643 if (ass->sizeItems < 0) {
3644 /* If disabled. */
3645 return (0);
3646 }
3647 if (ass->sizeItems <= 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003648 ass->items = (void **) xmlMalloc(growSize * sizeof(xmlSchemaTypePtr));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003649 if (ass->items == NULL) {
3650 xmlSchemaPErrMemory(ctxt,
3651 "allocating new item buffer", NULL);
3652 return (-1);
3653 }
3654 ass->sizeItems = growSize;
3655 } else if (ass->sizeItems <= ass->nbItems) {
3656 ass->sizeItems *= 2;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003657 ass->items = (void **) xmlRealloc(ass->items,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003658 ass->sizeItems * sizeof(xmlSchemaTypePtr));
3659 if (ass->items == NULL) {
3660 xmlSchemaPErrMemory(ctxt,
3661 "growing item buffer", NULL);
3662 ass->sizeItems = 0;
3663 return (-1);
3664 }
3665 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003666 /* ass->items[ass->nbItems++] = (void *) item; */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003667 ((xmlSchemaTypePtr *) ass->items)[ass->nbItems++] = (void *) item;
3668 return (0);
3669}
3670
3671/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003672 * xmlSchemaAddNotation:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003673 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003674 * @schema: the schema being built
3675 * @name: the item name
3676 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00003677 * Add an XML schema annotation declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00003678 * *WARNING* this interface is highly subject to change
3679 *
3680 * Returns the new struture or NULL in case of error
3681 */
3682static xmlSchemaNotationPtr
3683xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00003684 const xmlChar *name)
Daniel Veillard4255d502002-04-16 15:50:10 +00003685{
3686 xmlSchemaNotationPtr ret = NULL;
3687 int val;
3688
3689 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3690 return (NULL);
3691
3692 if (schema->notaDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003693 schema->notaDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003694 if (schema->notaDecl == NULL)
3695 return (NULL);
3696
3697 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
3698 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003699 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003700 return (NULL);
3701 }
3702 memset(ret, 0, sizeof(xmlSchemaNotation));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003703 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003704 val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
3705 ret);
3706 if (val != 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00003707 /*
3708 * TODO: This should never happen, since a unique name will be computed.
3709 * If it fails, then an other internal error must have occured.
3710 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003711 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
3712 XML_SCHEMAP_REDEFINED_NOTATION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003713 "Annotation declaration '%s' is already declared.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003714 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003715 xmlFree(ret);
3716 return (NULL);
3717 }
3718 return (ret);
3719}
3720
3721
3722/**
3723 * xmlSchemaAddAttribute:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003724 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003725 * @schema: the schema being built
3726 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003727 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00003728 *
3729 * Add an XML schema Attrribute declaration
3730 * *WARNING* this interface is highly subject to change
3731 *
3732 * Returns the new struture or NULL in case of error
3733 */
3734static xmlSchemaAttributePtr
3735xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003736 const xmlChar * name, const xmlChar * namespace,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003737 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00003738{
3739 xmlSchemaAttributePtr ret = NULL;
3740 int val;
3741
3742 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3743 return (NULL);
3744
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003745#ifdef DEBUG
3746 fprintf(stderr, "Adding attribute %s\n", name);
3747 if (namespace != NULL)
3748 fprintf(stderr, " target namespace %s\n", namespace);
3749#endif
3750
Daniel Veillard4255d502002-04-16 15:50:10 +00003751 if (schema->attrDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003752 schema->attrDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003753 if (schema->attrDecl == NULL)
3754 return (NULL);
3755
3756 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
3757 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003758 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003759 return (NULL);
3760 }
3761 memset(ret, 0, sizeof(xmlSchemaAttribute));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003762 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00003763 ret->targetNamespace = namespace;
Daniel Veillard4255d502002-04-16 15:50:10 +00003764 val = xmlHashAddEntry3(schema->attrDecl, name,
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00003765 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003766 if (val != 0) {
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003767 if (topLevel) {
3768 xmlSchemaPCustomErr(ctxt,
3769 XML_SCHEMAP_REDEFINED_ATTR,
3770 NULL, NULL, node,
3771 "A global attribute declaration with the name '%s' does "
3772 "already exist", name);
3773 xmlFree(ret);
3774 return (NULL);
3775 } else {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003776 char buf[30];
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003777 /*
3778 * Using the ctxt->container for xmlHashAddEntry3 is ambigious
3779 * in the scenario:
3780 * 1. multiple top-level complex types have different target
3781 * namespaces but have the SAME NAME; this can happen if
3782 * schemata are imported
3783 * 2. those complex types contain attributes with an equal name
3784 * 3. those attributes are in no namespace
3785 * We will compute a new context string.
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003786 */
3787 snprintf(buf, 29, "#aCont%d", ctxt->counter++ + 1);
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003788 val = xmlHashAddEntry3(schema->attrDecl, name,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00003789 namespace, xmlDictLookup(ctxt->dict, BAD_CAST buf, -1), ret);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003790
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003791 if (val != 0) {
3792 xmlSchemaPCustomErr(ctxt,
3793 XML_SCHEMAP_INTERNAL,
3794 NULL, NULL, node,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003795 "Internal error: xmlSchemaAddAttribute, "
3796 "a dublicate attribute declaration with the name '%s' "
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003797 "could not be added to the hash.", name);
3798 xmlFree(ret);
3799 return (NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003800 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003801 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003802 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003803 if (ctxt->assemble != NULL)
3804 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003805 return (ret);
3806}
3807
3808/**
3809 * xmlSchemaAddAttributeGroup:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003810 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003811 * @schema: the schema being built
3812 * @name: the item name
3813 *
3814 * Add an XML schema Attrribute Group declaration
3815 *
3816 * Returns the new struture or NULL in case of error
3817 */
3818static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003819xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00003820 xmlSchemaPtr schema, const xmlChar * name,
3821 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003822{
3823 xmlSchemaAttributeGroupPtr ret = NULL;
3824 int val;
3825
3826 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3827 return (NULL);
3828
3829 if (schema->attrgrpDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003830 schema->attrgrpDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003831 if (schema->attrgrpDecl == NULL)
3832 return (NULL);
3833
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003834 ret =
3835 (xmlSchemaAttributeGroupPtr)
3836 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00003837 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003838 xmlSchemaPErrMemory(ctxt, "allocating attribute group", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003839 return (NULL);
3840 }
3841 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003842 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003843 val = xmlHashAddEntry3(schema->attrgrpDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003844 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003845 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003846 xmlSchemaPCustomErr(ctxt,
3847 XML_SCHEMAP_REDEFINED_ATTRGROUP,
3848 NULL, NULL, node,
3849 "A global attribute group definition with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003850 xmlFree(ret);
3851 return (NULL);
3852 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003853 if (ctxt->assemble != NULL)
3854 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003855 return (ret);
3856}
3857
3858/**
3859 * xmlSchemaAddElement:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003860 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003861 * @schema: the schema being built
3862 * @name: the type name
3863 * @namespace: the type namespace
3864 *
3865 * Add an XML schema Element declaration
3866 * *WARNING* this interface is highly subject to change
3867 *
3868 * Returns the new struture or NULL in case of error
3869 */
3870static xmlSchemaElementPtr
3871xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003872 const xmlChar * name, const xmlChar * namespace,
3873 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00003874{
3875 xmlSchemaElementPtr ret = NULL;
3876 int val;
3877
3878 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3879 return (NULL);
3880
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003881#ifdef DEBUG
3882 fprintf(stderr, "Adding element %s\n", name);
3883 if (namespace != NULL)
3884 fprintf(stderr, " target namespace %s\n", namespace);
3885#endif
3886
Daniel Veillard4255d502002-04-16 15:50:10 +00003887 if (schema->elemDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003888 schema->elemDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003889 if (schema->elemDecl == NULL)
3890 return (NULL);
3891
3892 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
3893 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003894 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003895 return (NULL);
3896 }
3897 memset(ret, 0, sizeof(xmlSchemaElement));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003898 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003899 val = xmlHashAddEntry3(schema->elemDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003900 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003901 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003902 if (topLevel) {
3903 xmlSchemaPCustomErr(ctxt,
3904 XML_SCHEMAP_REDEFINED_ELEMENT,
3905 NULL, NULL, node,
3906 "A global element declaration with the name '%s' does "
3907 "already exist", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003908 xmlFree(ret);
3909 return (NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00003910 } else {
3911 char buf[30];
3912
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003913 snprintf(buf, 29, "#eCont%d", ctxt->counter++ + 1);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003914 val = xmlHashAddEntry3(schema->elemDecl, name,
3915 namespace, (xmlChar *) buf, ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00003916 if (val != 0) {
3917 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003918 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00003919 NULL, NULL, node,
3920 "Internal error: xmlSchemaAddElement, "
3921 "a dublicate element declaration with the name '%s' "
3922 "could not be added to the hash.", name);
3923 xmlFree(ret);
3924 return (NULL);
3925 }
3926 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00003927
Daniel Veillard4255d502002-04-16 15:50:10 +00003928 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003929 if (ctxt->assemble != NULL)
3930 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003931 return (ret);
3932}
3933
3934/**
3935 * xmlSchemaAddType:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003936 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003937 * @schema: the schema being built
3938 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003939 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00003940 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00003941 * Add an XML schema item
Daniel Veillard4255d502002-04-16 15:50:10 +00003942 * *WARNING* this interface is highly subject to change
3943 *
3944 * Returns the new struture or NULL in case of error
3945 */
3946static xmlSchemaTypePtr
3947xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003948 const xmlChar * name, const xmlChar * namespace,
3949 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003950{
3951 xmlSchemaTypePtr ret = NULL;
3952 int val;
3953
3954 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3955 return (NULL);
3956
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003957#ifdef DEBUG
3958 fprintf(stderr, "Adding type %s\n", name);
3959 if (namespace != NULL)
3960 fprintf(stderr, " target namespace %s\n", namespace);
3961#endif
3962
Daniel Veillard4255d502002-04-16 15:50:10 +00003963 if (schema->typeDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003964 schema->typeDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003965 if (schema->typeDecl == NULL)
3966 return (NULL);
3967
3968 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
3969 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003970 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003971 return (NULL);
3972 }
3973 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003974 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003975 ret->redef = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003976 val = xmlHashAddEntry2(schema->typeDecl, name, namespace, ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00003977 if (val != 0) {
3978 if (ctxt->includes == 0) {
3979 xmlSchemaPCustomErr(ctxt,
3980 XML_SCHEMAP_REDEFINED_TYPE,
3981 NULL, NULL, node,
3982 "A global type definition with the name '%s' does already exist", name);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003983 xmlFree(ret);
3984 return (NULL);
3985 } else {
3986 xmlSchemaTypePtr prev;
3987
3988 prev = xmlHashLookup2(schema->typeDecl, name, namespace);
3989 if (prev == NULL) {
3990 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003991 XML_ERR_INTERNAL_ERROR,
3992 "Internal error: xmlSchemaAddType, on type "
3993 "'%s'.\n",
3994 name, NULL);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003995 xmlFree(ret);
3996 return (NULL);
3997 }
3998 ret->redef = prev->redef;
3999 prev->redef = ret;
4000 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004001 }
4002 ret->minOccurs = 1;
4003 ret->maxOccurs = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +00004004 ret->attributeUses = NULL;
4005 ret->attributeWildcard = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004006 if (ctxt->assemble != NULL)
4007 xmlSchemaAddAssembledItem(ctxt,ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004008 return (ret);
4009}
4010
4011/**
4012 * xmlSchemaAddGroup:
4013 * @ctxt: a schema validation context
4014 * @schema: the schema being built
4015 * @name: the group name
4016 *
4017 * Add an XML schema Group definition
4018 *
4019 * Returns the new struture or NULL in case of error
4020 */
4021static xmlSchemaTypePtr
4022xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004023 const xmlChar *name, const xmlChar *namespaceName,
4024 xmlNodePtr node)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004025{
4026 xmlSchemaTypePtr ret = NULL;
4027 int val;
4028
4029 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4030 return (NULL);
4031
4032 if (schema->groupDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004033 schema->groupDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004034 if (schema->groupDecl == NULL)
4035 return (NULL);
4036
4037 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
4038 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004039 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004040 return (NULL);
4041 }
4042 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004043 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004044 val =
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004045 xmlHashAddEntry2(schema->groupDecl, name, namespaceName,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004046 ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004047 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004048 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00004049 XML_SCHEMAP_REDEFINED_GROUP,
4050 NULL, NULL, node,
4051 "A global model group definition with the name '%s' does already "
4052 "exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004053 xmlFree(ret);
4054 return (NULL);
4055 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00004056 ret->targetNamespace = namespaceName;
Daniel Veillard4255d502002-04-16 15:50:10 +00004057 ret->minOccurs = 1;
4058 ret->maxOccurs = 1;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004059 if (ctxt->assemble != NULL)
4060 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004061 return (ret);
4062}
4063
Daniel Veillard3646d642004-06-02 19:19:14 +00004064/**
4065 * xmlSchemaNewWildcardNs:
4066 * @ctxt: a schema validation context
4067 *
4068 * Creates a new wildcard namespace constraint.
4069 *
4070 * Returns the new struture or NULL in case of error
4071 */
4072static xmlSchemaWildcardNsPtr
4073xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
4074{
4075 xmlSchemaWildcardNsPtr ret;
4076
4077 ret = (xmlSchemaWildcardNsPtr)
4078 xmlMalloc(sizeof(xmlSchemaWildcardNs));
4079 if (ret == NULL) {
4080 xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
4081 return (NULL);
4082 }
4083 ret->value = NULL;
4084 ret->next = NULL;
4085 return (ret);
4086}
4087
4088/**
4089 * xmlSchemaAddWildcard:
4090 * @ctxt: a schema validation context
Daniel Veillardc0826a72004-08-10 14:17:33 +00004091 * Adds a wildcard. It corresponds to a
4092 * xsd:anyAttribute and is used as storage for namespace
4093 * constraints on a xsd:any.
Daniel Veillard3646d642004-06-02 19:19:14 +00004094 *
4095 * Returns the new struture or NULL in case of error
4096 */
4097static xmlSchemaWildcardPtr
4098xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt)
4099{
4100 xmlSchemaWildcardPtr ret = NULL;
4101
4102 if (ctxt == NULL)
4103 return (NULL);
4104
4105 ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
4106 if (ret == NULL) {
4107 xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
4108 return (NULL);
4109 }
4110 memset(ret, 0, sizeof(xmlSchemaWildcard));
4111 ret->minOccurs = 1;
4112 ret->maxOccurs = 1;
4113
4114 return (ret);
4115}
4116
Daniel Veillard4255d502002-04-16 15:50:10 +00004117/************************************************************************
4118 * *
4119 * Utilities for parsing *
4120 * *
4121 ************************************************************************/
4122
4123/**
4124 * xmlGetQNameProp:
4125 * @ctxt: a schema validation context
4126 * @node: a subtree containing XML Schema informations
4127 * @name: the attribute name
4128 * @namespace: the result namespace if any
4129 *
4130 * Extract a QName Attribute value
4131 *
4132 * Returns the NCName or NULL if not found, and also update @namespace
4133 * with the namespace URI
4134 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004135static const xmlChar *
Daniel Veillard4255d502002-04-16 15:50:10 +00004136xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004137 const char *name, const xmlChar ** namespace)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004138{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004139 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00004140 xmlNsPtr ns;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004141 const xmlChar *ret, *prefix;
4142 int len;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004143 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00004144
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004145 *namespace = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004146 attr = xmlSchemaGetPropNode(node, name);
4147 if (attr == NULL)
4148 return (NULL);
4149 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004150
Daniel Veillard4255d502002-04-16 15:50:10 +00004151 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004152 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004153
Daniel Veillardba0153a2004-04-01 10:42:31 +00004154 if (!strchr((char *) val, ':')) {
Daniel Veillardebcdebd2004-03-05 00:15:50 +00004155 ns = xmlSearchNs(node->doc, node, 0);
4156 if (ns) {
4157 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
4158 return (val);
4159 }
4160 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004161 ret = xmlSplitQName3(val, &len);
4162 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004163 return (val);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004164 }
4165 ret = xmlDictLookup(ctxt->dict, ret, -1);
4166 prefix = xmlDictLookup(ctxt->dict, val, len);
Daniel Veillard4255d502002-04-16 15:50:10 +00004167
4168 ns = xmlSearchNs(node->doc, node, prefix);
4169 if (ns == NULL) {
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004170 xmlSchemaPSimpleTypeErr(ctxt, XML_SCHEMAP_PREFIX_UNDEFINED,
4171 NULL, NULL, (xmlNodePtr) attr,
4172 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, val,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004173 "The QName value '%s' has no corresponding namespace "
4174 "declaration in scope", val, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004175 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004176 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004177 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004178 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004179}
4180
4181/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00004182 * xmlSchemaPValAttrNodeQNameValue:
4183 * @ctxt: a schema parser context
4184 * @schema: the schema context
4185 * @ownerDes: the designation of the parent element
4186 * @ownerItem: the parent as a schema object
4187 * @value: the QName value
4188 * @local: the resulting local part if found, the attribute value otherwise
4189 * @uri: the resulting namespace URI if found
4190 *
4191 * Extracts the local name and the URI of a QName value and validates it.
4192 * This one is intended to be used on attribute values that
4193 * should resolve to schema components.
4194 *
4195 * Returns 0, in case the QName is valid, a positive error code
4196 * if not valid and -1 if an internal error occurs.
4197 */
4198static int
4199xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
4200 xmlSchemaPtr schema,
4201 xmlChar **ownerDes,
4202 xmlSchemaTypePtr ownerItem,
4203 xmlAttrPtr attr,
4204 const xmlChar *value,
4205 const xmlChar **uri,
4206 const xmlChar **prefix,
4207 const xmlChar **local)
4208{
4209 const xmlChar *pref;
4210 xmlNsPtr ns;
4211 int len, ret;
4212
4213 *uri = NULL;
4214 *local = NULL;
4215 if (prefix != 0)
4216 *prefix = NULL;
4217 ret = xmlValidateQName(value, 1);
4218 if (ret > 0) {
4219 xmlSchemaPSimpleTypeErr(ctxt,
4220 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4221 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004222 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
4223 "QName", value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004224 NULL, NULL, NULL);
4225 *local = value;
4226 return (ctxt->err);
4227 } else if (ret < 0)
4228 return (-1);
4229
4230 if (!strchr((char *) value, ':')) {
4231 ns = xmlSearchNs(attr->doc, attr->parent, 0);
4232 if (ns)
4233 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
4234 else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
4235 /*
4236 * This one takes care of included schemas with no
4237 * target namespace.
4238 */
4239 *uri = schema->targetNamespace;
4240 }
4241 *local = value;
4242 return (0);
4243 }
4244 /*
4245 * At this point xmlSplitQName3 has to return a local name.
4246 */
4247 *local = xmlSplitQName3(value, &len);
4248 *local = xmlDictLookup(ctxt->dict, *local, -1);
4249 pref = xmlDictLookup(ctxt->dict, value, len);
4250 if (prefix != 0)
4251 *prefix = pref;
4252 ns = xmlSearchNs(attr->doc, attr->parent, pref);
4253 if (ns == NULL) {
4254 xmlSchemaPSimpleTypeErr(ctxt,
4255 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4256 ownerDes, ownerItem, (xmlNodePtr) attr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004257 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), "QName", value,
4258 "The QName value '%s' has no corresponding namespace "
4259 "declaration in scope", value, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004260 return (ctxt->err);
4261 } else {
4262 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
4263 }
4264 return (0);
4265}
4266
4267/**
4268 * xmlSchemaPValAttrNodeQName:
4269 * @ctxt: a schema parser context
4270 * @schema: the schema context
4271 * @ownerDes: the designation of the owner element
4272 * @ownerItem: the owner as a schema object
4273 * @attr: the attribute node
4274 * @local: the resulting local part if found, the attribute value otherwise
4275 * @uri: the resulting namespace URI if found
4276 *
4277 * Extracts and validates the QName of an attribute value.
4278 * This one is intended to be used on attribute values that
4279 * should resolve to schema components.
4280 *
4281 * Returns 0, in case the QName is valid, a positive error code
4282 * if not valid and -1 if an internal error occurs.
4283 */
4284static int
4285xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
4286 xmlSchemaPtr schema,
4287 xmlChar **ownerDes,
4288 xmlSchemaTypePtr ownerItem,
4289 xmlAttrPtr attr,
4290 const xmlChar **uri,
4291 const xmlChar **prefix,
4292 const xmlChar **local)
4293{
4294 const xmlChar *value;
4295
4296 value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4297 return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
4298 ownerDes, ownerItem, attr, value, uri, prefix, local));
4299}
4300
4301/**
4302 * xmlSchemaPValAttrQName:
4303 * @ctxt: a schema parser context
4304 * @schema: the schema context
4305 * @ownerDes: the designation of the parent element
4306 * @ownerItem: the owner as a schema object
4307 * @ownerElem: the parent node of the attribute
4308 * @name: the name of the attribute
4309 * @local: the resulting local part if found, the attribute value otherwise
4310 * @uri: the resulting namespace URI if found
4311 *
4312 * Extracts and validates the QName of an attribute value.
4313 *
4314 * Returns 0, in case the QName is valid, a positive error code
4315 * if not valid and -1 if an internal error occurs.
4316 */
4317static int
4318xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
4319 xmlSchemaPtr schema,
4320 xmlChar **ownerDes,
4321 xmlSchemaTypePtr ownerItem,
4322 xmlNodePtr ownerElem,
4323 const char *name,
4324 const xmlChar **uri,
4325 const xmlChar **prefix,
4326 const xmlChar **local)
4327{
4328 xmlAttrPtr attr;
4329
4330 attr = xmlSchemaGetPropNode(ownerElem, name);
4331 if (attr == NULL) {
4332 *local = NULL;
4333 *uri = NULL;
4334 return (0);
4335 }
4336 return (xmlSchemaPValAttrNodeQName(ctxt, schema,
4337 ownerDes, ownerItem, attr, uri, prefix, local));
4338}
4339
4340/**
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00004341 * xmlSchemaPValAttrID:
4342 * @ctxt: a schema parser context
4343 * @schema: the schema context
4344 * @ownerDes: the designation of the parent element
4345 * @ownerItem: the owner as a schema object
4346 * @ownerElem: the parent node of the attribute
4347 * @name: the name of the attribute
4348 *
4349 * Extracts and validates the ID of an attribute value.
4350 *
4351 * Returns 0, in case the ID is valid, a positive error code
4352 * if not valid and -1 if an internal error occurs.
4353 */
4354static int
4355xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,
4356 xmlChar **ownerDes,
4357 xmlSchemaTypePtr ownerItem,
4358 xmlNodePtr ownerElem,
4359 const xmlChar *name)
4360{
4361 int ret;
4362 xmlChar *value;
4363 xmlAttrPtr attr;
4364
4365 value = xmlGetNoNsProp(ownerElem, name);
4366 if (value == NULL)
4367 return (0);
4368
4369 attr = xmlSchemaGetPropNode(ownerElem, (const char *) name);
4370 if (attr == NULL)
4371 return (-1);
4372
4373 ret = xmlValidateNCName(BAD_CAST value, 1);
4374 if (ret == 0) {
4375 /*
4376 * NOTE: the IDness might have already be declared in the DTD
4377 */
4378 if (attr->atype != XML_ATTRIBUTE_ID) {
4379 xmlIDPtr res;
4380 xmlChar *strip;
4381
4382 /*
4383 * TODO: Use xmlSchemaStrip here; it's not exported at this
4384 * moment.
4385 */
4386 strip = xmlSchemaCollapseString(BAD_CAST value);
4387 if (strip != NULL)
4388 value = strip;
4389 res = xmlAddID(NULL, ownerElem->doc, BAD_CAST value, attr);
4390 if (res == NULL) {
4391 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
4392 xmlSchemaPSimpleTypeErr(ctxt,
4393 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4394 ownerDes, ownerItem, (xmlNodePtr) attr,
4395 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00004396 NULL, NULL, "The ID '%s' is already defined",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00004397 BAD_CAST value, NULL);
4398 } else
4399 attr->atype = XML_ATTRIBUTE_ID;
4400 if (strip != NULL)
4401 xmlFree(strip);
4402 }
4403 } else if (ret > 0) {
4404 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
4405 xmlSchemaPSimpleTypeErr(ctxt,
4406 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4407 ownerDes, ownerItem, (xmlNodePtr) attr,
4408 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
4409 NULL, BAD_CAST value, NULL, NULL, NULL);
4410 }
4411 xmlFree(value);
4412
4413 return (ret);
4414}
4415
4416/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004417 * xmlGetMaxOccurs:
4418 * @ctxt: a schema validation context
4419 * @node: a subtree containing XML Schema informations
4420 *
4421 * Get the maxOccurs property
4422 *
4423 * Returns the default if not found, or the value
4424 */
4425static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004426xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
4427 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004428{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004429 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00004430 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004431 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00004432
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004433 attr = xmlSchemaGetPropNode(node, "maxOccurs");
4434 if (attr == NULL)
4435 return (def);
4436 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00004437
4438 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004439 if (max != UNBOUNDED) {
4440 xmlSchemaPSimpleTypeErr(ctxt,
4441 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4442 /* XML_SCHEMAP_INVALID_MINOCCURS, */
4443 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
4444 val, NULL, NULL, NULL);
4445 return (def);
4446 } else
4447 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00004448 }
4449
4450 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00004451 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004452 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004453 if (*cur == 0) {
4454 xmlSchemaPSimpleTypeErr(ctxt,
4455 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4456 /* XML_SCHEMAP_INVALID_MINOCCURS, */
4457 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
4458 val, NULL, NULL, NULL);
4459 return (def);
4460 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004461 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004462 ret = ret * 10 + (*cur - '0');
4463 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00004464 }
William M. Brack76e95df2003-10-18 16:20:14 +00004465 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004466 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004467 /*
4468 * TODO: Restrict the maximal value to Integer.
4469 */
4470 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
4471 xmlSchemaPSimpleTypeErr(ctxt,
4472 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4473 /* XML_SCHEMAP_INVALID_MINOCCURS, */
4474 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
4475 val, NULL, NULL, NULL);
4476 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00004477 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004478 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004479}
4480
4481/**
4482 * xmlGetMinOccurs:
4483 * @ctxt: a schema validation context
4484 * @node: a subtree containing XML Schema informations
4485 *
4486 * Get the minOccurs property
4487 *
4488 * Returns the default if not found, or the value
4489 */
4490static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004491xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
4492 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004493{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004494 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00004495 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004496 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00004497
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004498 attr = xmlSchemaGetPropNode(node, "minOccurs");
4499 if (attr == NULL)
4500 return (def);
4501 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00004502 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00004503 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004504 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004505 if (*cur == 0) {
4506 xmlSchemaPSimpleTypeErr(ctxt,
4507 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4508 /* XML_SCHEMAP_INVALID_MINOCCURS, */
4509 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
4510 val, NULL, NULL, NULL);
4511 return (def);
4512 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004513 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004514 ret = ret * 10 + (*cur - '0');
4515 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00004516 }
William M. Brack76e95df2003-10-18 16:20:14 +00004517 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004518 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004519 /*
4520 * TODO: Restrict the maximal value to Integer.
4521 */
4522 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
4523 xmlSchemaPSimpleTypeErr(ctxt,
4524 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4525 /* XML_SCHEMAP_INVALID_MINOCCURS, */
4526 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
4527 val, NULL, NULL, NULL);
4528 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00004529 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004530 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004531}
4532
4533/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004534 * xmlSchemaPGetBoolNodeValue:
4535 * @ctxt: a schema validation context
4536 * @ownerDes: owner designation
4537 * @ownerItem: the owner as a schema item
4538 * @node: the node holding the value
4539 *
4540 * Converts a boolean string value into 1 or 0.
4541 *
4542 * Returns 0 or 1.
4543 */
4544static int
4545xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
4546 xmlChar **ownerDes,
4547 xmlSchemaTypePtr ownerItem,
4548 xmlNodePtr node)
4549{
4550 xmlChar *value = NULL;
4551 int res = 0;
4552
4553 value = xmlNodeGetContent(node);
4554 /*
4555 * 3.2.2.1 Lexical representation
4556 * An instance of a datatype that is defined as ·boolean·
4557 * can have the following legal literals {true, false, 1, 0}.
4558 */
4559 if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
4560 res = 1;
4561 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
4562 res = 0;
4563 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
4564 res = 1;
4565 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
4566 res = 0;
4567 else {
4568 xmlSchemaPSimpleTypeErr(ctxt,
4569 XML_SCHEMAP_INVALID_BOOLEAN,
4570 ownerDes, ownerItem, node,
4571 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
4572 "(1 | 0 | true | false)", BAD_CAST value,
4573 NULL, NULL, NULL);
4574 }
4575 if (value != NULL)
4576 xmlFree(value);
4577 return (res);
4578}
4579
4580/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004581 * xmlGetBooleanProp:
4582 * @ctxt: a schema validation context
4583 * @node: a subtree containing XML Schema informations
4584 * @name: the attribute name
4585 * @def: the default value
4586 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00004587 * Evaluate if a boolean property is set
Daniel Veillard4255d502002-04-16 15:50:10 +00004588 *
4589 * Returns the default if not found, 0 if found to be false,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004590 * 1 if found to be true
Daniel Veillard4255d502002-04-16 15:50:10 +00004591 */
4592static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00004593xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
4594 xmlChar **ownerDes,
4595 xmlSchemaTypePtr ownerItem,
4596 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004597 const char *name, int def)
4598{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004599 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00004600
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004601 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004602 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004603 return (def);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004604 /*
4605 * 3.2.2.1 Lexical representation
4606 * An instance of a datatype that is defined as ·boolean·
4607 * can have the following legal literals {true, false, 1, 0}.
4608 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004609 if (xmlStrEqual(val, BAD_CAST "true"))
4610 def = 1;
4611 else if (xmlStrEqual(val, BAD_CAST "false"))
4612 def = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004613 else if (xmlStrEqual(val, BAD_CAST "1"))
4614 def = 1;
4615 else if (xmlStrEqual(val, BAD_CAST "0"))
4616 def = 0;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00004617 else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004618 xmlSchemaPSimpleTypeErr(ctxt,
4619 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00004620 ownerDes, ownerItem,
4621 (xmlNodePtr) xmlSchemaGetPropNode(node, name),
William M. Brack2f2a6632004-08-20 23:09:47 +00004622 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
4623 "(1 | 0 | true | false)", val, NULL, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004624 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004625 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00004626}
4627
4628/************************************************************************
4629 * *
4630 * Shema extraction from an Infoset *
4631 * *
4632 ************************************************************************/
4633static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
4634 ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00004635 xmlNodePtr node,
4636 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004637static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
4638 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00004639 xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00004640 xmlNodePtr node,
4641 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004642static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
4643 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00004644 xmlSchemaPtr schema,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00004645 xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00004646static xmlSchemaTypePtr xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt,
4647 xmlSchemaPtr schema,
4648 xmlNodePtr node);
4649static xmlSchemaTypePtr xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt,
4650 xmlSchemaPtr schema,
4651 xmlNodePtr node);
4652static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
4653 ctxt,
4654 xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00004655 xmlNodePtr node,
4656 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00004657static xmlSchemaAttributeGroupPtr
4658xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00004659 xmlSchemaPtr schema, xmlNodePtr node,
4660 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00004661static xmlSchemaTypePtr xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt,
4662 xmlSchemaPtr schema,
4663 xmlNodePtr node);
4664static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
4665 xmlSchemaPtr schema,
4666 xmlNodePtr node);
Daniel Veillard3646d642004-06-02 19:19:14 +00004667static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004668xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
4669 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00004670
4671/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004672 * xmlSchemaPValAttrNodeValue:
Daniel Veillard01fa6152004-06-29 17:04:39 +00004673 *
4674 * @ctxt: a schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00004675 * @ownerDes: the designation of the parent element
4676 * @ownerItem: the schema object owner if existent
4677 * @attr: the schema attribute node being validated
4678 * @value: the value
4679 * @type: the built-in type to be validated against
Daniel Veillard01fa6152004-06-29 17:04:39 +00004680 *
4681 * Validates a value against the given built-in type.
4682 * This one is intended to be used internally for validation
4683 * of schema attribute values during parsing of the schema.
4684 *
4685 * Returns 0 if the value is valid, a positive error code
4686 * number otherwise and -1 in case of an internal or API error.
4687 */
4688static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00004689xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr ctxt,
4690 xmlChar **ownerDes,
4691 xmlSchemaTypePtr ownerItem,
4692 xmlAttrPtr attr,
4693 const xmlChar *value,
4694 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +00004695{
Daniel Veillard01fa6152004-06-29 17:04:39 +00004696
Daniel Veillardc0826a72004-08-10 14:17:33 +00004697 int ret = 0;
4698
4699 /*
4700 * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
4701 * one is really meant to be used internally, so better not.
4702 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00004703 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00004704 return (-1);
4705 if (type->type != XML_SCHEMA_TYPE_BASIC) {
4706 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004707 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004708 "Internal error: xmlSchemaPValAttrNodeValue, the given "
Daniel Veillardc0826a72004-08-10 14:17:33 +00004709 "type '%s' is not a built-in type.\n",
4710 type->name, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00004711 return (-1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004712 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00004713 switch (type->builtInType) {
4714 case XML_SCHEMAS_NCNAME:
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004715 case XML_SCHEMAS_QNAME:
4716 case XML_SCHEMAS_ANYURI:
4717 case XML_SCHEMAS_TOKEN:
4718 case XML_SCHEMAS_LANGUAGE:
4719 ret = xmlSchemaValPredefTypeNode(type, value, NULL, (xmlNodePtr) attr);
4720 break;
4721
4722 /*
4723 case XML_SCHEMAS_NCNAME:
Daniel Veillard01fa6152004-06-29 17:04:39 +00004724 ret = xmlValidateNCName(value, 1);
4725 break;
4726 case XML_SCHEMAS_QNAME:
Daniel Veillardc0826a72004-08-10 14:17:33 +00004727 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004728 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004729 "Internal error: xmlSchemaPvalueAttrNode, use "
4730 "the function xmlSchemaExtractSchemaQNamePropvalueidated "
4731 "for extracting QName valueues instead.\n",
4732 NULL, NULL);
4733 return (-1);
4734 case XML_SCHEMAS_ANYURI:
4735 if (value != NULL) {
4736 xmlURIPtr uri = xmlParseURI((const char *) value);
4737 if (uri == NULL)
4738 ret = 1;
4739 else
4740 xmlFreeURI(uri);
Daniel Veillard01fa6152004-06-29 17:04:39 +00004741 }
4742 break;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004743 case XML_SCHEMAS_TOKEN: {
4744 const xmlChar *cur = value;
4745
4746 if (IS_BLANK_CH(*cur)) {
4747 ret = 1;
4748 } else while (*cur != 0) {
4749 if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) {
4750 ret = 1;
4751 break;
4752 } else if (*cur == ' ') {
4753 cur++;
4754 if ((*cur == 0) || (*cur == ' ')) {
4755 ret = 1;
4756 break;
4757 }
4758 } else {
4759 cur++;
4760 }
4761 }
4762 }
4763 break;
4764 case XML_SCHEMAS_LANGUAGE:
4765 if (xmlCheckLanguageID(value) != 1)
4766 ret = 1;
4767 break;
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004768 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00004769 default: {
4770 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004771 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004772 "Internal error: xmlSchemaPValAttrNodeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +00004773 "valueidation using the type '%s' is not implemented "
4774 "yet.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +00004775 type->name, NULL);
4776 return (-1);
4777 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004778 }
4779 /*
4780 * TODO: Should we use the S4S error codes instead?
4781 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004782 if (ret < 0) {
4783 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
4784 XML_SCHEMAP_INTERNAL,
4785 "Internal error: xmlSchemaPValAttrNodeValue, "
4786 "failed to validate a schema attribute value.\n",
4787 NULL, NULL);
4788 return (-1);
4789 } else if (ret > 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004790 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
4791 xmlSchemaPSimpleTypeErr(ctxt,
4792 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2,
4793 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004794 type, NULL, value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004795 NULL, NULL, NULL);
4796 return(XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2);
4797 } else {
4798 xmlSchemaPSimpleTypeErr(ctxt,
4799 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
4800 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004801 type, NULL, value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004802 NULL, NULL, NULL);
4803 return(XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
4804 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00004805 }
4806 return (ret);
4807}
4808
4809/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00004810 * xmlSchemaPValAttrNode:
4811 *
4812 * @ctxt: a schema parser context
4813 * @ownerDes: the designation of the parent element
4814 * @ownerItem: the schema object owner if existent
4815 * @attr: the schema attribute node being validated
4816 * @type: the built-in type to be validated against
4817 * @value: the resulting value if any
4818 *
4819 * Extracts and validates a value against the given built-in type.
4820 * This one is intended to be used internally for validation
4821 * of schema attribute values during parsing of the schema.
4822 *
4823 * Returns 0 if the value is valid, a positive error code
4824 * number otherwise and -1 in case of an internal or API error.
4825 */
4826static int
4827xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
4828 xmlChar **ownerDes,
4829 xmlSchemaTypePtr ownerItem,
4830 xmlAttrPtr attr,
4831 xmlSchemaTypePtr type,
4832 const xmlChar **value)
4833{
4834 const xmlChar *val;
4835
4836 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
4837 return (-1);
4838
4839 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4840 if (value != NULL)
4841 *value = val;
4842
4843 return (xmlSchemaPValAttrNodeValue(ctxt, ownerDes, ownerItem, attr,
4844 val, type));
4845}
4846
4847/**
4848 * xmlSchemaPValAttr:
4849 *
4850 * @ctxt: a schema parser context
4851 * @node: the element node of the attribute
4852 * @ownerDes: the designation of the parent element
4853 * @ownerItem: the schema object owner if existent
4854 * @ownerElem: the owner element node
4855 * @name: the name of the schema attribute node
4856 * @type: the built-in type to be validated against
4857 * @value: the resulting value if any
4858 *
4859 * Extracts and validates a value against the given built-in type.
4860 * This one is intended to be used internally for validation
4861 * of schema attribute values during parsing of the schema.
4862 *
4863 * Returns 0 if the value is valid, a positive error code
4864 * number otherwise and -1 in case of an internal or API error.
4865 */
4866static int
4867xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
4868 xmlChar **ownerDes,
4869 xmlSchemaTypePtr ownerItem,
4870 xmlNodePtr ownerElem,
4871 const char *name,
4872 xmlSchemaTypePtr type,
4873 const xmlChar **value)
4874{
4875 xmlAttrPtr attr;
4876
4877 if ((ctxt == NULL) || (type == NULL)) {
4878 if (value != NULL)
4879 *value = NULL;
4880 return (-1);
4881 }
4882 if (type->type != XML_SCHEMA_TYPE_BASIC) {
4883 if (value != NULL)
4884 *value = NULL;
4885 xmlSchemaPErr(ctxt, ownerElem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004886 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004887 "Internal error: xmlSchemaPValAttr, the given "
4888 "type '%s' is not a built-in type.\n",
4889 type->name, NULL);
4890 return (-1);
4891 }
4892 attr = xmlSchemaGetPropNode(ownerElem, name);
4893 if (attr == NULL) {
4894 if (value != NULL)
4895 *value = NULL;
4896 return (0);
4897 }
4898 return (xmlSchemaPValAttrNode(ctxt, ownerDes, ownerItem, attr,
4899 type, value));
4900}
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00004901
4902static int
4903xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,
4904 xmlSchemaPtr schema,
4905 xmlNodePtr node,
4906 xmlSchemaTypePtr item,
4907 const xmlChar *namespaceName)
4908{
4909 if (xmlStrEqual(schema->targetNamespace, namespaceName))
4910 return (1);
4911 if (pctxt->localImports != NULL) {
4912 int i;
4913 for (i = 0; i < pctxt->nbLocalImports; i++)
4914 if (xmlStrEqual(namespaceName, pctxt->localImports[i]))
4915 return (1);
4916 }
4917 if (namespaceName == NULL)
4918 xmlSchemaPCustomErr(pctxt, XML_SCHEMAP_SRC_RESOLVE,
4919 NULL, item, node, "References from this schema to components in no "
4920 "namespace are not valid, since not indicated by an import "
4921 "statement", NULL);
4922 else
4923 xmlSchemaPCustomErr(pctxt, XML_SCHEMAP_SRC_RESOLVE,
4924 NULL, item, node, "References from this schema to components in the "
4925 "namespace '%s' are not valid, since not indicated by an import "
4926 "statement", namespaceName);
4927 return (0);
4928}
4929
Daniel Veillardc0826a72004-08-10 14:17:33 +00004930/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004931 * xmlSchemaParseAttrDecls:
4932 * @ctxt: a schema validation context
4933 * @schema: the schema being built
4934 * @node: a subtree containing XML Schema informations
4935 * @type: the hosting type
4936 *
4937 * parse a XML schema attrDecls declaration corresponding to
4938 * <!ENTITY % attrDecls
4939 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
4940 */
4941static xmlNodePtr
4942xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4943 xmlNodePtr child, xmlSchemaTypePtr type)
4944{
4945 xmlSchemaAttributePtr lastattr, attr;
4946
4947 lastattr = NULL;
4948 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004949 (IS_SCHEMA(child, "attributeGroup"))) {
4950 attr = NULL;
4951 if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00004952 attr = xmlSchemaParseAttribute(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004953 } else if (IS_SCHEMA(child, "attributeGroup")) {
4954 attr = (xmlSchemaAttributePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00004955 xmlSchemaParseAttributeGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004956 }
4957 if (attr != NULL) {
4958 if (lastattr == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00004959 if (type->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
4960 ((xmlSchemaAttributeGroupPtr) type)->attributes = attr;
4961 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004962 type->attributes = attr;
4963 lastattr = attr;
4964 } else {
4965 lastattr->next = attr;
4966 lastattr = attr;
4967 }
4968 }
4969 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004970 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004971 return (child);
Daniel Veillard4255d502002-04-16 15:50:10 +00004972}
4973
4974/**
4975 * xmlSchemaParseAnnotation:
4976 * @ctxt: a schema validation context
4977 * @schema: the schema being built
4978 * @node: a subtree containing XML Schema informations
4979 *
4980 * parse a XML schema Attrribute declaration
4981 * *WARNING* this interface is highly subject to change
4982 *
William M. Bracke7091952004-05-11 15:09:58 +00004983 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00004984 * 1 in case of success.
4985 */
4986static xmlSchemaAnnotPtr
4987xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4988 xmlNodePtr node)
4989{
4990 xmlSchemaAnnotPtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004991 xmlNodePtr child = NULL;
4992 xmlAttrPtr attr;
4993 int barked = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00004994
Daniel Veillardc0826a72004-08-10 14:17:33 +00004995 /*
4996 * INFO: S4S completed.
4997 */
4998 /*
4999 * id = ID
5000 * {any attributes with non-schema namespace . . .}>
5001 * Content: (appinfo | documentation)*
5002 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005003 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5004 return (NULL);
5005 ret = xmlSchemaNewAnnot(ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005006 attr = node->properties;
5007 while (attr != NULL) {
5008 if (((attr->ns == NULL) &&
5009 (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
5010 ((attr->ns != NULL) &&
5011 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
5012
5013 xmlSchemaPIllegalAttrErr(ctxt,
5014 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5015 NULL, NULL, attr);
5016 }
5017 attr = attr->next;
5018 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005019 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00005020 /*
5021 * And now for the children...
5022 */
5023 child = node->children;
5024 while (child != NULL) {
5025 if (IS_SCHEMA(child, "appinfo")) {
5026 /* TODO: make available the content of "appinfo". */
5027 /*
5028 * source = anyURI
5029 * {any attributes with non-schema namespace . . .}>
5030 * Content: ({any})*
5031 */
5032 attr = child->properties;
5033 while (attr != NULL) {
5034 if (((attr->ns == NULL) &&
5035 (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
5036 ((attr->ns != NULL) &&
5037 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005038
Daniel Veillardc0826a72004-08-10 14:17:33 +00005039 xmlSchemaPIllegalAttrErr(ctxt,
5040 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5041 NULL, NULL, attr);
5042 }
5043 attr = attr->next;
5044 }
5045 xmlSchemaPValAttr(ctxt, NULL, NULL, child, "source",
5046 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
5047 child = child->next;
5048 } else if (IS_SCHEMA(child, "documentation")) {
5049 /* TODO: make available the content of "documentation". */
5050 /*
5051 * source = anyURI
5052 * {any attributes with non-schema namespace . . .}>
5053 * Content: ({any})*
5054 */
5055 attr = child->properties;
5056 while (attr != NULL) {
5057 if (attr->ns == NULL) {
5058 if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
5059 xmlSchemaPIllegalAttrErr(ctxt,
5060 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5061 NULL, NULL, attr);
5062 }
5063 } else {
5064 if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
5065 (xmlStrEqual(attr->name, BAD_CAST "lang") &&
5066 (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
5067
5068 xmlSchemaPIllegalAttrErr(ctxt,
5069 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5070 NULL, NULL, attr);
5071 }
5072 }
5073 attr = attr->next;
5074 }
5075 /*
5076 * Attribute "xml:lang".
5077 */
5078 attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
5079 if (attr != NULL)
5080 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
5081 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
5082 child = child->next;
5083 } else {
5084 if (!barked)
5085 xmlSchemaPContentErr(ctxt,
5086 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5087 NULL, NULL, node, child, NULL, "(appinfo | documentation)*");
5088 barked = 1;
5089 child = child->next;
5090 }
5091 }
5092
Daniel Veillard4255d502002-04-16 15:50:10 +00005093 return (ret);
5094}
5095
5096/**
5097 * xmlSchemaParseFacet:
5098 * @ctxt: a schema validation context
5099 * @schema: the schema being built
5100 * @node: a subtree containing XML Schema informations
5101 *
5102 * parse a XML schema Facet declaration
5103 * *WARNING* this interface is highly subject to change
5104 *
5105 * Returns the new type structure or NULL in case of error
5106 */
5107static xmlSchemaFacetPtr
5108xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005109 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005110{
5111 xmlSchemaFacetPtr facet;
5112 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005113 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00005114
5115 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5116 return (NULL);
5117
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00005118 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005119 if (facet == NULL) {
5120 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
5121 return (NULL);
5122 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005123 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005124 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00005125 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005126 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
5127 "Facet %s has no value\n", node->name, NULL);
5128 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00005129 return (NULL);
5130 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005131 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005132 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005133 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005134 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005135 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005136 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005137 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005138 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005139 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005140 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005141 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005142 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005143 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005144 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005145 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005146 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005147 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005148 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005149 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005150 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005151 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005152 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
5153 } else if (IS_SCHEMA(node, "minLength")) {
5154 facet->type = XML_SCHEMA_FACET_MINLENGTH;
5155 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005156 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
5157 "Unknown facet type %s\n", node->name, NULL);
5158 xmlSchemaFreeFacet(facet);
5159 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005160 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005161 xmlSchemaPValAttrID(ctxt, NULL,
5162 (xmlSchemaTypePtr) facet, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00005163 facet->value = value;
Daniel Veillard01fa6152004-06-29 17:04:39 +00005164 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
5165 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
5166 const xmlChar *fixed;
5167
5168 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
5169 if (fixed != NULL) {
5170 if (xmlStrEqual(fixed, BAD_CAST "true"))
5171 facet->fixed = 1;
5172 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005173 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005174 child = node->children;
5175
5176 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005177 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5178 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005179 }
5180 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005181 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
5182 "Facet %s has unexpected child content\n",
5183 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005184 }
5185 return (facet);
5186}
5187
5188/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005189 * xmlSchemaParseWildcardNs:
5190 * @ctxt: a schema parser context
5191 * @wildc: the wildcard, already created
5192 * @node: a subtree containing XML Schema informations
5193 *
5194 * Parses the attribute "processContents" and "namespace"
5195 * of a xsd:anyAttribute and xsd:any.
5196 * *WARNING* this interface is highly subject to change
5197 *
5198 * Returns 0 if everything goes fine, a positive error code
5199 * if something is not valid and -1 if an internal error occurs.
5200 */
5201static int
5202xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
5203 xmlSchemaPtr schema,
5204 xmlSchemaWildcardPtr wildc,
5205 xmlNodePtr node)
5206{
5207 const xmlChar *pc, *ns, *dictnsItem;
5208 int ret = 0;
5209 xmlChar *nsItem;
5210 xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
5211 xmlAttrPtr attr;
5212
5213 pc = xmlSchemaGetProp(ctxt, node, "processContents");
5214 if ((pc == NULL)
5215 || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
5216 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
5217 } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
5218 wildc->processContents = XML_SCHEMAS_ANY_SKIP;
5219 } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
5220 wildc->processContents = XML_SCHEMAS_ANY_LAX;
5221 } else {
5222 xmlSchemaPSimpleTypeErr(ctxt,
5223 XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD,
5224 NULL, NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00005225 NULL, "(strict | skip | lax)", pc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005226 NULL, NULL, NULL);
5227 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
5228 ret = XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD;
5229 }
5230 /*
5231 * Build the namespace constraints.
5232 */
5233 attr = xmlSchemaGetPropNode(node, "namespace");
5234 ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5235 if ((ns == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
5236 wildc->any = 1;
5237 else if (xmlStrEqual(ns, BAD_CAST "##other")) {
5238 wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
5239 if (wildc->negNsSet == NULL) {
5240 return (-1);
5241 }
5242 wildc->negNsSet->value = schema->targetNamespace;
5243 } else {
5244 const xmlChar *end, *cur;
5245
5246 cur = ns;
5247 do {
5248 while (IS_BLANK_CH(*cur))
5249 cur++;
5250 end = cur;
5251 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
5252 end++;
5253 if (end == cur)
5254 break;
5255 nsItem = xmlStrndup(cur, end - cur);
5256 if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
5257 (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
5258 xmlSchemaPSimpleTypeErr(ctxt,
5259 XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
5260 NULL, NULL, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005261 NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005262 "((##any | ##other) | List of (anyURI | "
5263 "(##targetNamespace | ##local)))",
5264 nsItem, NULL, NULL, NULL);
5265 ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
5266 } else {
5267 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
5268 dictnsItem = schema->targetNamespace;
5269 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
5270 dictnsItem = NULL;
5271 } else {
5272 /*
5273 * Validate the item (anyURI).
5274 */
5275 xmlSchemaPValAttrNodeValue(ctxt, NULL, NULL, attr,
5276 nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
5277 dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
5278 }
5279 /*
5280 * Avoid dublicate namespaces.
5281 */
5282 tmp = wildc->nsSet;
5283 while (tmp != NULL) {
5284 if (dictnsItem == tmp->value)
5285 break;
5286 tmp = tmp->next;
5287 }
5288 if (tmp == NULL) {
5289 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
5290 if (tmp == NULL) {
5291 xmlFree(nsItem);
5292 return (-1);
5293 }
5294 tmp->value = dictnsItem;
5295 tmp->next = NULL;
5296 if (wildc->nsSet == NULL)
5297 wildc->nsSet = tmp;
5298 else
5299 lastNs->next = tmp;
5300 lastNs = tmp;
5301 }
5302
5303 }
5304 xmlFree(nsItem);
5305 cur = end;
5306 } while (*cur != 0);
5307 }
5308 return (ret);
5309}
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005310
5311static int
5312xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
5313 xmlSchemaTypePtr item,
5314 xmlNodePtr node,
5315 int minOccurs,
5316 int maxOccurs) {
5317
5318 if (maxOccurs != UNBOUNDED) {
5319 /*
5320 * TODO: Maby we should better not create the particle,
5321 * if min/max is invalid, since it could confuse the build of the
5322 * content model.
5323 */
5324 /*
5325 * 3.9.6 Schema Component Constraint: Particle Correct
5326 *
5327 */
5328 if (maxOccurs < 1) {
5329 /*
5330 * 2.2 {max occurs} must be greater than or equal to 1.
5331 */
5332 xmlSchemaPCustomAttrErr(ctxt,
5333 XML_SCHEMAP_P_PROPS_CORRECT_2_2,
5334 NULL, item, xmlSchemaGetPropNode(node, "maxOccurs"),
5335 "The value must be greater than or equal to 1");
5336 return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
5337 } else if (minOccurs > maxOccurs) {
5338 /*
5339 * 2.1 {min occurs} must not be greater than {max occurs}.
5340 */
5341 xmlSchemaPCustomAttrErr(ctxt,
5342 XML_SCHEMAP_P_PROPS_CORRECT_2_1,
5343 NULL, item, xmlSchemaGetPropNode(node, "minOccurs"),
5344 "The value must not be greater than the value of 'maxOccurs'");
5345 return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
5346 }
5347 }
5348 return (0);
5349}
5350
Daniel Veillardc0826a72004-08-10 14:17:33 +00005351/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005352 * xmlSchemaParseAny:
5353 * @ctxt: a schema validation context
5354 * @schema: the schema being built
5355 * @node: a subtree containing XML Schema informations
5356 *
5357 * parse a XML schema Any declaration
5358 * *WARNING* this interface is highly subject to change
5359 *
5360 * Returns the new type structure or NULL in case of error
5361 */
5362static xmlSchemaTypePtr
5363xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5364 xmlNodePtr node)
5365{
5366 xmlSchemaTypePtr type;
5367 xmlNodePtr child = NULL;
5368 xmlChar name[30];
Daniel Veillardc0826a72004-08-10 14:17:33 +00005369 xmlSchemaWildcardPtr wildc;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005370 int minOccurs, maxOccurs;
Daniel Veillard4255d502002-04-16 15:50:10 +00005371
5372 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5373 return (NULL);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005374 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
5375 "(nonNegativeInteger | unbounded)");
5376 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
5377 "nonNegativeInteger");
5378 if ((minOccurs == 0) && (maxOccurs == 0))
5379 return (NULL);
5380
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005381 snprintf((char *) name, 30, "#any%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00005382 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005383 if (type == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005384 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005385 type->node = node;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005386 type->type = XML_SCHEMA_TYPE_ANY;
5387
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005388 /*
5389 * TODO: Use a particle component here.
5390 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00005391 wildc = xmlSchemaAddWildcard(ctxt);
5392 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005393 * Check min/max sanity.
5394 */
5395 type->maxOccurs = maxOccurs;
5396 type->minOccurs = minOccurs;
5397 xmlSchemaPCheckParticleCorrect_2(ctxt, type,
5398 node, type->minOccurs, type->maxOccurs);
5399 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005400 * This is not nice, since it is won't be used as a attribute wildcard,
5401 * but better than adding a field to the structure.
5402 */
5403 type->attributeWildcard = wildc;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005404 xmlSchemaParseWildcardNs(ctxt, schema, wildc, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005405 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00005406 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005407 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5408 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005409 }
5410 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005411 xmlSchemaPErr2(ctxt, node, child,
5412 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
5413 "Sequence %s has unexpected content\n", type->name,
5414 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005415 }
5416
5417 return (type);
5418}
5419
5420/**
5421 * xmlSchemaParseNotation:
5422 * @ctxt: a schema validation context
5423 * @schema: the schema being built
5424 * @node: a subtree containing XML Schema informations
5425 *
5426 * parse a XML schema Notation declaration
5427 *
5428 * Returns the new structure or NULL in case of error
5429 */
5430static xmlSchemaNotationPtr
5431xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005432 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005433{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005434 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00005435 xmlSchemaNotationPtr ret;
5436 xmlNodePtr child = NULL;
5437
5438 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5439 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005440 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00005441 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005442 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
5443 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005444 return (NULL);
5445 }
5446 ret = xmlSchemaAddNotation(ctxt, schema, name);
5447 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005448 return (NULL);
5449 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005450 ret->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00005451
5452 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
5453 node, BAD_CAST "id");
5454
5455 if (IS_SCHEMA(child, "annotation")) {
5456 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5457 child = child->next;
5458 }
5459
Daniel Veillard4255d502002-04-16 15:50:10 +00005460 child = node->children;
5461 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005462 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5463 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005464 }
5465 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005466 xmlSchemaPErr2(ctxt, node, child,
5467 XML_SCHEMAP_UNKNOWN_NOTATION_CHILD,
5468 "notation %s has unexpected content\n", name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005469 }
5470
5471 return (ret);
5472}
5473
5474/**
5475 * xmlSchemaParseAnyAttribute:
5476 * @ctxt: a schema validation context
5477 * @schema: the schema being built
5478 * @node: a subtree containing XML Schema informations
5479 *
5480 * parse a XML schema AnyAttrribute declaration
5481 * *WARNING* this interface is highly subject to change
5482 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005483 * Returns a wildcard or NULL.
Daniel Veillard4255d502002-04-16 15:50:10 +00005484 */
Daniel Veillard3646d642004-06-02 19:19:14 +00005485static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005486xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
5487 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005488{
Daniel Veillard3646d642004-06-02 19:19:14 +00005489 xmlSchemaWildcardPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00005490 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005491 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005492
5493 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5494 return (NULL);
5495
Daniel Veillard3646d642004-06-02 19:19:14 +00005496 ret = xmlSchemaAddWildcard(ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00005497 if (ret == NULL) {
5498 return (NULL);
5499 }
William M. Bracke7091952004-05-11 15:09:58 +00005500 ret->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005501 /*
5502 * Check for illegal attributes.
5503 */
5504 attr = node->properties;
5505 while (attr != NULL) {
5506 if (attr->ns == NULL) {
5507 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5508 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
5509 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
5510 xmlSchemaPIllegalAttrErr(ctxt,
5511 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5512 NULL, NULL, attr);
5513 }
5514 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5515 xmlSchemaPIllegalAttrErr(ctxt,
5516 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5517 NULL, NULL, attr);
5518 }
5519 attr = attr->next;
5520 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005521 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
5522 node, BAD_CAST "id");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005523 /*
5524 * Parse the namespace list.
5525 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00005526 if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0) {
5527 xmlSchemaFreeWildcard(ret);
5528 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005529 }
5530 /*
5531 * And now for the children...
5532 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005533 child = node->children;
5534 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005535 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5536 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005537 }
5538 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005539 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005540 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5541 NULL, NULL, node, child,
5542 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005543 }
5544
5545 return (ret);
5546}
5547
5548
5549/**
5550 * xmlSchemaParseAttribute:
5551 * @ctxt: a schema validation context
5552 * @schema: the schema being built
5553 * @node: a subtree containing XML Schema informations
5554 *
5555 * parse a XML schema Attrribute declaration
5556 * *WARNING* this interface is highly subject to change
5557 *
William M. Bracke7091952004-05-11 15:09:58 +00005558 * Returns the attribute declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00005559 */
5560static xmlSchemaAttributePtr
5561xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00005562 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005563{
Daniel Veillardc0826a72004-08-10 14:17:33 +00005564 const xmlChar *name, *attrValue;
5565 xmlChar *repName = NULL; /* The reported designation. */
Daniel Veillard4255d502002-04-16 15:50:10 +00005566 xmlSchemaAttributePtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005567 xmlNodePtr child = NULL;
5568 xmlAttrPtr attr, nameAttr;
5569 int isRef = 0;
William M. Bracke7091952004-05-11 15:09:58 +00005570
5571 /*
5572 * Note that the w3c spec assumes the schema to be validated with schema
5573 * for schemas beforehand.
5574 *
5575 * 3.2.3 Constraints on XML Representations of Attribute Declarations
William M. Bracke7091952004-05-11 15:09:58 +00005576 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005577
5578 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5579 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005580 attr = xmlSchemaGetPropNode(node, "ref");
5581 nameAttr = xmlSchemaGetPropNode(node, "name");
5582
5583 if ((attr == NULL) && (nameAttr == NULL)) {
5584 /*
5585 * 3.2.3 : 3.1
5586 * One of ref or name must be present, but not both
5587 */
5588 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
5589 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, node, NULL,
5590 "One of the attributes 'ref' or 'name' must be present");
5591 return (NULL);
5592 }
5593 if ((topLevel) || (attr == NULL)) {
5594 if (nameAttr == NULL) {
5595 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
5596 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, node,
5597 "name", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005598 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005599 }
5600 } else
5601 isRef = 1;
5602
5603 if (isRef) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005604 char buf[50];
Daniel Veillardc0826a72004-08-10 14:17:33 +00005605 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix = NULL;
5606
5607 /*
5608 * Parse as attribute reference.
5609 */
5610 if (xmlSchemaPValAttrNodeQName(ctxt, schema,
5611 (xmlChar **) &xmlSchemaElemDesAttrRef, NULL, attr, &refNs,
5612 &refPrefix, &ref) != 0) {
5613 return (NULL);
5614 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005615 snprintf(buf, 49, "#aRef%d", ctxt->counter++ + 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005616 name = (const xmlChar *) buf;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005617 ret = xmlSchemaAddAttribute(ctxt, schema, name, NULL, node, 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005618 if (ret == NULL) {
5619 if (repName != NULL)
5620 xmlFree(repName);
5621 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005622 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005623 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
5624 ret->node = node;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005625 ret->refNs = refNs;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005626 ret->refPrefix = refPrefix;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005627 ret->ref = ref;
5628 xmlSchemaCheckReference(ctxt, schema, node, (xmlSchemaTypePtr) ret, refNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005629 /*
5630 xmlSchemaFormatTypeRep(&repName, (xmlSchemaTypePtr) ret, NULL, NULL);
5631 */
5632 if (nameAttr != NULL)
5633 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
5634 &repName, (xmlSchemaTypePtr) ret, nameAttr,
5635 "ref", "name");
5636 /*
5637 * Check for illegal attributes.
5638 */
5639 attr = node->properties;
5640 while (attr != NULL) {
5641 if (attr->ns == NULL) {
5642 if (xmlStrEqual(attr->name, BAD_CAST "type") ||
5643 xmlStrEqual(attr->name, BAD_CAST "form")) {
5644 /*
5645 * 3.2.3 : 3.2
5646 * If ref is present, then all of <simpleType>,
5647 * form and type must be absent.
5648 */
5649 xmlSchemaPIllegalAttrErr(ctxt,
5650 XML_SCHEMAP_SRC_ATTRIBUTE_3_2, &repName,
5651 (xmlSchemaTypePtr) ret, attr);
5652 } else if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
5653 (!xmlStrEqual(attr->name, BAD_CAST "use")) &&
5654 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5655 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
5656 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
5657 (!xmlStrEqual(attr->name, BAD_CAST "default"))) {
5658 xmlSchemaPIllegalAttrErr(ctxt,
5659 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5660 &repName, (xmlSchemaTypePtr) ret, attr);
5661 }
5662 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5663 xmlSchemaPIllegalAttrErr(ctxt,
5664 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5665 &repName, (xmlSchemaTypePtr) ret, attr);
5666 }
5667 attr = attr->next;
5668 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005669 } else {
William M. Bracke7091952004-05-11 15:09:58 +00005670 const xmlChar *ns = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005671
5672 /*
5673 * Parse as attribute declaration.
5674 */
5675 if (xmlSchemaPValAttrNode(ctxt,
5676 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, nameAttr,
5677 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
5678 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005679 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005680 /*
5681 xmlSchemaFormatTypeRep(&repName, NULL, xmlSchemaElemDesAttrDecl, name);
5682 */
5683 /*
5684 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
5685 */
5686 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
5687 xmlSchemaPSimpleTypeErr(ctxt,
5688 XML_SCHEMAP_NO_XMLNS,
5689 &repName, NULL, (xmlNodePtr) nameAttr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005690 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), "NCName", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005691 "The value must not match 'xmlns'",
5692 NULL, NULL);
5693 if (repName != NULL)
5694 xmlFree(repName);
5695 return (NULL);
5696 }
5697 /*
5698 * Evaluate the target namespace
5699 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005700 if (topLevel) {
5701 ns = schema->targetNamespace;
5702 } else {
5703 attr = xmlSchemaGetPropNode(node, "form");
5704 if (attr != NULL) {
5705 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5706 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
5707 ns = schema->targetNamespace;
5708 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
5709 xmlSchemaPSimpleTypeErr(ctxt,
5710 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5711 &repName, NULL, (xmlNodePtr) attr,
5712 NULL, "(qualified | unqualified)",
5713 attrValue, NULL, NULL, NULL);
5714 }
5715 } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
5716 ns = schema->targetNamespace;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005717 }
5718 ret = xmlSchemaAddAttribute(ctxt, schema, name, ns, node, topLevel);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005719 if (ret == NULL) {
5720 if (repName != NULL)
5721 xmlFree(repName);
Daniel Veillard3646d642004-06-02 19:19:14 +00005722 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005723 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005724 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005725 ret->node = node;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005726 if (topLevel)
5727 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
5728 /*
5729 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
5730 */
5731 if (xmlStrEqual(ret->targetNamespace, xmlSchemaInstanceNs)) {
5732 xmlSchemaPCustomErr(ctxt,
5733 XML_SCHEMAP_NO_XSI,
5734 &repName, (xmlSchemaTypePtr) ret, node,
5735 "The target namespace must not match '%s'",
5736 xmlSchemaInstanceNs);
5737 }
5738 /*
5739 * Check for illegal attributes.
5740 */
5741 attr = node->properties;
5742 while (attr != NULL) {
5743 if (attr->ns == NULL) {
5744 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5745 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
5746 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
5747 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
5748 (!xmlStrEqual(attr->name, BAD_CAST "type"))) {
5749 if ((topLevel) ||
5750 ((!xmlStrEqual(attr->name, BAD_CAST "form")) &&
5751 (!xmlStrEqual(attr->name, BAD_CAST "use")))) {
5752 xmlSchemaPIllegalAttrErr(ctxt,
5753 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5754 &repName, (xmlSchemaTypePtr) ret, attr);
5755 }
5756 }
5757 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5758 xmlSchemaPIllegalAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5759 &repName, (xmlSchemaTypePtr) ret, attr);
5760 }
5761 attr = attr->next;
5762 }
5763 xmlSchemaPValAttrQName(ctxt, schema, &repName, (xmlSchemaTypePtr) ret,
5764 node, "type", &ret->typeNs, NULL, &ret->typeName);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005765 }
5766 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
5767 node, BAD_CAST "id");
William M. Bracke7091952004-05-11 15:09:58 +00005768 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005769 * Attribute "fixed".
William M. Bracke7091952004-05-11 15:09:58 +00005770 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00005771 ret->defValue = xmlSchemaGetProp(ctxt, node, "fixed");
5772 if (ret->defValue != NULL)
5773 ret->flags |= XML_SCHEMAS_ATTR_FIXED;
5774 /*
5775 * Attribute "default".
5776 */
5777 attr = xmlSchemaGetPropNode(node, "default");
5778 if (attr != NULL) {
5779 /*
5780 * 3.2.3 : 1
5781 * default and fixed must not both be present.
5782 */
5783 if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
5784 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
5785 &repName, (xmlSchemaTypePtr) ret, attr, "default", "fixed");
5786 } else
5787 ret->defValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5788 }
5789 if (topLevel == 0) {
5790 /*
5791 * Attribute "use".
5792 */
5793 attr = xmlSchemaGetPropNode(node, "use");
5794 if (attr != NULL) {
5795 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5796 if (xmlStrEqual(attrValue, BAD_CAST "optional"))
5797 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
5798 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
5799 ret->occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
5800 else if (xmlStrEqual(attrValue, BAD_CAST "required"))
5801 ret->occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
5802 else
5803 xmlSchemaPSimpleTypeErr(ctxt,
5804 XML_SCHEMAP_INVALID_ATTR_USE,
5805 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005806 NULL, "(optional | prohibited | required)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00005807 attrValue, NULL, NULL, NULL);
5808 } else
5809 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
5810 /*
5811 * 3.2.3 : 2
5812 * If default and use are both present, use must have
5813 * the actual value optional.
5814 */
5815 if ((ret->occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
5816 (ret->defValue != NULL) &&
5817 ((ret->flags & XML_SCHEMAS_ATTR_FIXED) == 0)) {
5818 xmlSchemaPSimpleTypeErr(ctxt,
5819 XML_SCHEMAP_SRC_ATTRIBUTE_2,
5820 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005821 NULL, "(optional | prohibited | required)", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005822 "The value must be 'optional' if the attribute "
5823 "'default' is present as well", NULL, NULL);
5824 }
5825 }
5826 /*
5827 * And now for the children...
5828 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005829 child = node->children;
5830 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005831 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5832 child = child->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005833 }
5834 if (isRef) {
5835 if (child != NULL) {
5836 if (IS_SCHEMA(child, "simpleType"))
5837 /*
5838 * 3.2.3 : 3.2
5839 * If ref is present, then all of <simpleType>,
5840 * form and type must be absent.
5841 */
5842 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
5843 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
5844 "(annotation?)");
5845 else
5846 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5847 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
5848 "(annotation?)");
5849 }
5850 } else {
5851 if (IS_SCHEMA(child, "simpleType")) {
5852 if (ret->typeName != NULL) {
5853 /*
5854 * 3.2.3 : 4
5855 * type and <simpleType> must not both be present.
5856 */
5857 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
5858 &repName, (xmlSchemaTypePtr) ret, node, child,
5859 "The attribute 'type' and the <simpleType> child "
5860 "are mutually exclusive", NULL);
5861 } else
5862 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
5863 child = child->next;
5864 }
5865 if (child != NULL)
5866 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5867 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
5868 "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005869 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005870 /*
5871 * Cleanup.
5872 */
5873 if (repName != NULL)
5874 xmlFree(repName);
Daniel Veillard4255d502002-04-16 15:50:10 +00005875 return (ret);
5876}
5877
5878/**
5879 * xmlSchemaParseAttributeGroup:
5880 * @ctxt: a schema validation context
5881 * @schema: the schema being built
5882 * @node: a subtree containing XML Schema informations
5883 *
5884 * parse a XML schema Attribute Group declaration
5885 * *WARNING* this interface is highly subject to change
5886 *
5887 * Returns the attribute group or NULL in case of error.
5888 */
5889static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005890xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00005891 xmlSchemaPtr schema, xmlNodePtr node,
5892 int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005893{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005894 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00005895 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00005896 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005897 const xmlChar *oldcontainer;
5898 xmlAttrPtr attr, nameAttr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005899
5900 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5901 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005902
5903 nameAttr = xmlSchemaGetPropNode(node, "name");
5904 attr = xmlSchemaGetPropNode(node, "ref");
5905 if ((topLevel) || (attr == NULL)) {
5906 /*
5907 * Parse as an attribute group definition.
5908 * Note that those are allowed at top level only.
5909 */
5910 if (nameAttr == NULL) {
5911 xmlSchemaPMissingAttrErr(ctxt,
5912 XML_SCHEMAP_S4S_ATTR_MISSING,
5913 NULL, NULL, node, "name", NULL);
5914 return (NULL);
5915 }
5916 name = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) nameAttr);
5917 /*
5918 * The name is crucial, exit if invalid.
5919 */
5920 if (xmlSchemaPValAttrNode(ctxt,
5921 NULL, NULL, nameAttr,
5922 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
5923 return (NULL);
5924 }
5925 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
5926 if (ret == NULL)
5927 return (NULL);
5928 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
5929 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
5930 ret->node = node;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005931 ret->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005932 } else {
5933 char buf[50];
5934 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix;
5935
5936 /*
5937 * Parse as an attribute group definition reference.
5938 */
5939 if (attr == NULL) {
5940 xmlSchemaPMissingAttrErr(ctxt,
5941 XML_SCHEMAP_S4S_ATTR_MISSING,
5942 NULL, NULL, node, "ref", NULL);
5943 }
5944 xmlSchemaPValAttrNodeQName(ctxt, schema,
5945 NULL, NULL, attr, &refNs, &refPrefix, &ref);
5946
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005947 snprintf(buf, 49, "#agRef%d", ctxt->counter++ + 1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005948 name = (const xmlChar *) buf;
5949 if (name == NULL) {
5950 xmlSchemaPErrMemory(ctxt, "creating internal name for an "
5951 "attribute group definition reference", node);
5952 return (NULL);
5953 }
5954 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
5955 if (ret == NULL)
5956 return (NULL);
5957 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
5958 ret->ref = ref;
5959 ret->refNs = refNs;
5960 /* TODO: Is @refPrefix currently used? */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005961 ret->refPrefix = refPrefix;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005962 ret->node = node;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005963 xmlSchemaCheckReference(ctxt, schema, node, (xmlSchemaTypePtr) ret, refNs);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005964 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005965 /*
5966 * Check for illegal attributes.
5967 */
5968 attr = node->properties;
5969 while (attr != NULL) {
5970 if (attr->ns == NULL) {
5971 if ((((topLevel == 0) && (!xmlStrEqual(attr->name, BAD_CAST "ref"))) ||
5972 (topLevel && (!xmlStrEqual(attr->name, BAD_CAST "name")))) &&
5973 (!xmlStrEqual(attr->name, BAD_CAST "id")))
5974 {
5975 xmlSchemaPIllegalAttrErr(ctxt,
5976 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5977 NULL, NULL, attr);
5978 }
5979 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5980 xmlSchemaPIllegalAttrErr(ctxt,
5981 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5982 NULL, NULL, attr);
5983 }
5984 attr = attr->next;
5985 }
5986 /* TODO: Validate "id" ? */
5987 /*
5988 * And now for the children...
5989 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005990 oldcontainer = ctxt->container;
Daniel Veillard4255d502002-04-16 15:50:10 +00005991 ctxt->container = name;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005992 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00005993 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005994 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5995 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005996 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005997 if (topLevel) {
5998 child = xmlSchemaParseAttrDecls(ctxt, schema, child, (xmlSchemaTypePtr) ret);
5999 if (IS_SCHEMA(child, "anyAttribute")) {
6000 ret->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
6001 child = child->next;
6002 }
6003 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006004 if (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006005 xmlSchemaPContentErr(ctxt,
6006 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6007 NULL, NULL, node, child, NULL,
6008 "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006009 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006010 ctxt->container = oldcontainer;
6011 return (ret);
6012}
6013
6014/**
William M. Brack2f2a6632004-08-20 23:09:47 +00006015 * xmlSchemaPValAttrFormDefault:
6016 * @value: the value
6017 * @flags: the flags to be modified
6018 * @flagQualified: the specific flag for "qualified"
6019 *
6020 * Returns 0 if the value is valid, 1 otherwise.
6021 */
6022static int
6023xmlSchemaPValAttrFormDefault(const xmlChar *value,
6024 int *flags,
6025 int flagQualified)
6026{
6027 if (xmlStrEqual(value, BAD_CAST "qualified")) {
6028 if ((*flags & flagQualified) == 0)
6029 *flags |= flagQualified;
6030 } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
6031 return (1);
6032
6033 return (0);
6034}
6035
6036/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00006037 * xmlSchemaPValAttrBlockFinal:
6038 * @value: the value
6039 * @flags: the flags to be modified
6040 * @flagAll: the specific flag for "#all"
6041 * @flagExtension: the specific flag for "extension"
6042 * @flagRestriction: the specific flag for "restriction"
6043 * @flagSubstitution: the specific flag for "substitution"
6044 * @flagList: the specific flag for "list"
6045 * @flagUnion: the specific flag for "union"
6046 *
6047 * Validates the value of the attribute "final" and "block". The value
6048 * is converted into the specified flag values and returned in @flags.
6049 *
6050 * Returns 0 if the value is valid, 1 otherwise.
6051 */
6052
6053static int
6054xmlSchemaPValAttrBlockFinal(const xmlChar *value,
6055 int *flags,
6056 int flagAll,
6057 int flagExtension,
6058 int flagRestriction,
6059 int flagSubstitution,
6060 int flagList,
6061 int flagUnion)
6062{
6063 int ret = 0;
6064
6065 /*
6066 * TODO: This does not check for dublicate entries.
6067 */
William M. Brack2f2a6632004-08-20 23:09:47 +00006068 if (value == NULL)
6069 return (1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006070 if (xmlStrEqual(value, BAD_CAST "#all")) {
6071 if (flagAll != -1)
6072 *flags |= flagAll;
6073 else {
6074 if (flagExtension != -1)
6075 *flags |= flagExtension;
6076 if (flagRestriction != -1)
6077 *flags |= flagRestriction;
6078 if (flagSubstitution != -1)
6079 *flags |= flagSubstitution;
6080 if (flagList != -1)
6081 *flags |= flagList;
6082 if (flagUnion != -1)
6083 *flags |= flagUnion;
6084 }
6085 } else {
6086 const xmlChar *end, *cur = value;
6087 xmlChar *item;
6088
6089 do {
6090 while (IS_BLANK_CH(*cur))
6091 cur++;
6092 end = cur;
6093 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
6094 end++;
6095 if (end == cur)
6096 break;
6097 item = xmlStrndup(cur, end - cur);
6098 if (xmlStrEqual(item, BAD_CAST "extension")) {
6099 if (flagExtension != -1) {
6100 if ((*flags & flagExtension) == 0)
6101 *flags |= flagExtension;
6102 } else
6103 ret = 1;
6104 } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
6105 if (flagRestriction != -1) {
6106 if ((*flags & flagRestriction) == 0)
6107 *flags |= flagRestriction;
6108 } else
6109 ret = 1;
6110 } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
6111 if (flagSubstitution != -1) {
6112 if ((*flags & flagSubstitution) == 0)
6113 *flags |= flagSubstitution;
6114 } else
6115 ret = 1;
6116 } else if (xmlStrEqual(item, BAD_CAST "list")) {
6117 if (flagList != -1) {
6118 if ((*flags & flagList) == 0)
6119 *flags |= flagList;
6120 } else
6121 ret = 1;
6122 } else if (xmlStrEqual(item, BAD_CAST "union")) {
6123 if (flagUnion != -1) {
6124 if ((*flags & flagUnion) == 0)
6125 *flags |= flagUnion;
6126 } else
6127 ret = 1;
6128 } else
6129 ret = 1;
6130 if (item != NULL)
6131 xmlFree(item);
6132 cur = end;
6133 } while ((ret == 0) && (*cur != 0));
6134 }
6135
6136 return (ret);
6137}
6138
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006139#ifdef IDC_ENABLED
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006140static int
6141xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006142 xmlSchemaIDCPtr idc,
6143 xmlSchemaIDCSelectPtr selector,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006144 xmlAttrPtr attr,
6145 int isField)
6146{
6147 xmlNodePtr node;
6148
6149 /*
6150 * c-selector-xpath:
6151 * Schema Component Constraint: Selector Value OK
6152 *
6153 * TODO: 1 The {selector} must be a valid XPath expression, as defined
6154 * in [XPath].
6155 */
6156 if (selector == NULL) {
6157 xmlSchemaPErr(ctxt, idc->node,
6158 XML_SCHEMAP_INTERNAL,
6159 "Internal error: xmlSchemaCheckCSelectorXPath, "
6160 "the selector is not specified.\n", NULL, NULL);
6161 return (-1);
6162 }
6163 if (attr == NULL)
6164 node = idc->node;
6165 else
6166 node = (xmlNodePtr) attr;
6167 if (selector->xpath == NULL) {
6168 xmlSchemaPCustomErr(ctxt,
6169 /* TODO: Adjust error code. */
6170 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6171 NULL, NULL, node,
6172 "The XPath expression of the selector is not valid", NULL);
6173 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
6174 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006175 const xmlChar **nsArray = NULL;
6176 xmlNsPtr *nsList = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006177 /*
6178 * Compile the XPath expression.
6179 */
6180 /*
6181 * TODO: We need the array of in-scope namespaces for compilation.
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006182 * TODO: Call xmlPatterncompile with different options for selector/
6183 * field.
6184 */
6185 nsList = xmlGetNsList(attr->doc, attr->parent);
6186 /*
6187 * Build an array of prefixes and namespaces.
6188 */
6189 if (nsList != NULL) {
6190 int i, count = 0;
6191 xmlNsPtr ns;
6192
6193 for (i = 0; nsList[i] != NULL; i++)
6194 count++;
6195
6196 nsArray = (const xmlChar **) xmlMalloc(
6197 (count * 2 + 1) * sizeof(const xmlChar *));
6198 if (nsArray == NULL) {
6199 xmlSchemaPErrMemory(ctxt, "allocating a namespace array",
6200 NULL);
6201 return (-1);
6202 }
6203 for (i = 0; i < count; i++) {
6204 ns = nsList[i];
6205 nsArray[2 * i] = nsList[i]->href;
6206 nsArray[2 * i + 1] = nsList[i]->prefix;
6207 }
6208 nsArray[count * 2] = NULL;
6209 xmlFree(nsList);
6210 }
6211 if (isField)
6212 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik285ebab2005-03-04 18:04:59 +00006213 NULL, 1, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006214 else
6215 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik285ebab2005-03-04 18:04:59 +00006216 NULL, 1, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006217 if (nsArray != NULL)
6218 xmlFree((xmlChar **) nsArray);
6219
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006220#ifdef IDC_XPATH_SUPPORT
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00006221 if (selector->xpathComp == NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006222 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00006223 /* TODO: Adjust error code? */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006224 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6225 NULL, NULL, node,
6226 "The XPath expression '%s' could not be "
6227 "compiled", selector->xpath);
6228 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
6229 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00006230#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006231 }
6232 return (0);
6233}
6234
6235/**
6236 * xmlSchemaAssignAnnotation:
6237 * @item: the schema component
6238 * @annot: the annotation
6239 *
6240 * Adds the annotation to the given schema component.
6241 *
6242 * Returns the given annotaion.
6243 */
6244static xmlSchemaAnnotPtr
6245xmlSchemaAssignAnnotation(xmlSchemaBasicItemPtr item,
6246 xmlSchemaAnnotPtr annot)
6247{
6248 xmlSchemaAnnotPtr cur = item->annot;
6249
6250 if (item->annot == NULL) {
6251 item->annot = annot;
6252 return (annot);
6253 }
6254 cur = item->annot;
6255 if (cur->next != NULL) {
6256 cur = cur->next;
6257 }
6258 cur->next = annot;
6259 return (annot);
6260}
6261
6262/**
6263 * xmlSchemaParseIDCSelectorAndField:
6264 * @ctxt: a schema validation context
6265 * @schema: the schema being built
6266 * @node: a subtree containing XML Schema informations
6267 *
6268 * Parses a XML Schema identity-contraint definition's
6269 * <selector> and <field> elements.
6270 *
6271 * Returns the parsed identity-constraint definition.
6272 */
6273static xmlSchemaIDCSelectPtr
6274xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
6275 xmlSchemaPtr schema,
6276 xmlSchemaIDCPtr idc,
6277 xmlNodePtr node,
6278 int isField)
6279{
6280 xmlSchemaIDCSelectPtr item;
6281 xmlNodePtr child = NULL;
6282 xmlAttrPtr attr;
6283
6284 /*
6285 * Check for illegal attributes.
6286 */
6287 attr = node->properties;
6288 while (attr != NULL) {
6289 if (attr->ns == NULL) {
6290 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6291 (!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
6292 xmlSchemaPIllegalAttrErr(ctxt,
6293 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6294 NULL, NULL, attr);
6295 }
6296 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6297 xmlSchemaPIllegalAttrErr(ctxt,
6298 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6299 NULL, NULL, attr);
6300 }
6301 attr = attr->next;
6302 }
6303 /*
6304 * Create the item.
6305 */
6306 item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
6307 if (item == NULL) {
6308 xmlSchemaPErrMemory(ctxt,
6309 "allocating a 'selector' of an identity-constraint definition",
6310 NULL);
6311 return (NULL);
6312 }
6313 memset(item, 0, sizeof(xmlSchemaIDCSelect));
6314 /*
6315 * Attribute "xpath" (mandatory).
6316 */
6317 attr = xmlSchemaGetPropNode(node, "xpath");
6318 if (attr == NULL) {
6319 xmlSchemaPMissingAttrErr(ctxt,
6320 XML_SCHEMAP_S4S_ATTR_MISSING,
6321 NULL, NULL, node,
6322 "name", NULL);
6323 } else {
6324 item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6325 /*
6326 * URGENT TODO: "field"s have an other syntax than "selector"s.
6327 */
6328
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006329 if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr,
6330 isField) == -1) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006331 xmlSchemaPErr(ctxt,
6332 (xmlNodePtr) attr,
6333 XML_SCHEMAP_INTERNAL,
6334 "Internal error: xmlSchemaParseIDCSelectorAndField, "
6335 "validating the XPath expression of a IDC selector.\n",
6336 NULL, NULL);
6337 }
6338
6339 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00006340 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006341 /*
6342 * And now for the children...
6343 */
6344 child = node->children;
6345 if (IS_SCHEMA(child, "annotation")) {
6346 /*
6347 * Add the annotation to the parent IDC.
6348 */
6349 xmlSchemaAssignAnnotation((xmlSchemaBasicItemPtr) idc,
6350 xmlSchemaParseAnnotation(ctxt, schema, child));
6351 child = child->next;
6352 }
6353 if (child != NULL) {
6354 xmlSchemaPContentErr(ctxt,
6355 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6356 NULL, NULL, node, child,
6357 NULL, "(annotation?)");
6358 }
6359
6360 return (item);
6361}
6362
6363/**
6364 * xmlSchemaParseIDC:
6365 * @ctxt: a schema validation context
6366 * @schema: the schema being built
6367 * @node: a subtree containing XML Schema informations
6368 *
6369 * Parses a XML Schema identity-contraint definition.
6370 *
6371 * Returns the parsed identity-constraint definition.
6372 */
6373static xmlSchemaIDCPtr
6374xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
6375 xmlSchemaPtr schema,
6376 xmlNodePtr node,
6377 xmlSchemaTypeType idcCategory,
6378 const xmlChar *targetNamespace)
6379{
6380 xmlSchemaIDCPtr item = NULL;
6381 xmlNodePtr child = NULL;
6382 xmlAttrPtr attr;
6383 const xmlChar *name = NULL;
6384 xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
6385 int resAdd;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00006386
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006387 /*
6388 * Check for illegal attributes.
6389 */
6390 attr = node->properties;
6391 while (attr != NULL) {
6392 if (attr->ns == NULL) {
6393 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6394 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
6395 ((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
6396 (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
6397 xmlSchemaPIllegalAttrErr(ctxt,
6398 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6399 NULL, NULL, attr);
6400 }
6401 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6402 xmlSchemaPIllegalAttrErr(ctxt,
6403 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6404 NULL, NULL, attr);
6405 }
6406 attr = attr->next;
6407 }
6408 /*
6409 * Attribute "name" (mandatory).
6410 */
6411 attr = xmlSchemaGetPropNode(node, "name");
6412 if (attr == NULL) {
6413 xmlSchemaPMissingAttrErr(ctxt,
6414 XML_SCHEMAP_S4S_ATTR_MISSING,
6415 NULL, NULL, node,
6416 "name", NULL);
6417 return (NULL);
6418 } else if (xmlSchemaPValAttrNode(ctxt,
6419 NULL, NULL, attr,
6420 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
6421 return (NULL);
6422 }
6423 /*
6424 * Create the component.
6425 */
6426 if (schema->idcDef == NULL)
6427 schema->idcDef = xmlHashCreateDict(10, ctxt->dict);
6428 if (schema->idcDef == NULL)
6429 return (NULL);
6430
6431 item = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
6432 if (item == NULL) {
6433 xmlSchemaPErrMemory(ctxt,
6434 "allocating an identity-constraint definition", NULL);
6435 return (NULL);
6436 }
6437 /*
6438 * Add the IDC to the list of IDCs on the schema component.
6439 */
6440 resAdd = xmlHashAddEntry2(schema->idcDef, name, targetNamespace, item);
6441 if (resAdd != 0) {
6442 xmlSchemaPCustomErrExt(ctxt,
6443 XML_SCHEMAP_REDEFINED_TYPE,
6444 NULL, NULL, node,
6445 "An identity-constraint definition with the name '%s' "
6446 "and targetNamespace '%s' does already exist",
6447 name, targetNamespace, NULL);
6448 xmlFree(item);
6449 return (NULL);
6450 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006451 memset(item, 0, sizeof(xmlSchemaIDC));
6452 item->name = name;
6453 item->type = idcCategory;
6454 item->node = node;
6455 /*
6456 * The target namespace of the parent element declaration.
6457 */
6458 item->targetNamespace = targetNamespace;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00006459 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) item,
6460 node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006461 if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
6462 /*
6463 * Attribute "refer" (mandatory).
6464 */
6465 attr = xmlSchemaGetPropNode(node, "refer");
6466 if (attr == NULL) {
6467 xmlSchemaPMissingAttrErr(ctxt,
6468 XML_SCHEMAP_S4S_ATTR_MISSING,
6469 NULL, NULL, node,
6470 "refer", NULL);
6471 } else {
6472 /*
6473 * Create a reference item.
6474 */
6475 item->ref = (xmlSchemaItemQNRefPtr) xmlMalloc(
6476 sizeof(xmlSchemaItemQNRef));
6477 if (item->ref == NULL) {
6478 xmlSchemaPErrMemory(ctxt,
6479 "allocating a QName reference item", NULL);
6480 return (NULL);
6481 }
6482 memset(item->ref, 0, sizeof(xmlSchemaItemQNRef));
6483 xmlSchemaPValAttrNodeQName(ctxt, schema,
6484 NULL, NULL, attr,
6485 &(item->ref->targetNamespace), 0,
6486 &(item->ref->name));
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006487 xmlSchemaCheckReference(ctxt, schema, node, (xmlSchemaTypePtr) item,
6488 item->ref->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006489 }
6490 }
6491 /*
6492 * And now for the children...
6493 */
6494 child = node->children;
6495 if (IS_SCHEMA(child, "annotation")) {
6496 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6497 child = child->next;
6498 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00006499 if (child == NULL) {
6500 xmlSchemaPContentErr(ctxt,
6501 XML_SCHEMAP_S4S_ELEM_MISSING,
6502 NULL, NULL, node, child,
6503 "A child element is missing",
6504 "(annotation?, (selector, field+))");
6505 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006506 /*
6507 * Child element <selector>.
6508 */
6509 if (IS_SCHEMA(child, "selector")) {
6510 item->selector = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
6511 item, child, 0);
6512 child = child->next;
6513 /*
6514 * Child elements <field>.
6515 */
6516 if (IS_SCHEMA(child, "field")) {
6517 do {
6518 field = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
6519 item, child, 1);
6520 if (field != NULL) {
6521 field->index = item->nbFields;
6522 item->nbFields++;
6523 if (lastField != NULL)
6524 lastField->next = field;
6525 else
6526 item->fields = field;
6527 lastField = field;
6528 }
6529 child = child->next;
6530 } while (IS_SCHEMA(child, "field"));
6531 } else {
6532 xmlSchemaPContentErr(ctxt,
6533 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6534 NULL, NULL, node, child,
6535 NULL, "(annotation?, (selector, field+))");
6536 }
6537 }
6538 if (child != NULL) {
6539 xmlSchemaPContentErr(ctxt,
6540 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6541 NULL, NULL, node, child,
6542 NULL, "(annotation?, (selector, field+))");
6543 }
6544
6545 return (item);
6546}
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006547#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006548
Daniel Veillardc0826a72004-08-10 14:17:33 +00006549/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006550 * xmlSchemaParseElement:
6551 * @ctxt: a schema validation context
6552 * @schema: the schema being built
6553 * @node: a subtree containing XML Schema informations
6554 *
6555 * parse a XML schema Element declaration
6556 * *WARNING* this interface is highly subject to change
6557 *
William M. Bracke7091952004-05-11 15:09:58 +00006558 * Returns the parsed element declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00006559 */
6560static xmlSchemaElementPtr
6561xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00006562 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006563{
Daniel Veillardc0826a72004-08-10 14:17:33 +00006564 const xmlChar *name = NULL;
6565 const xmlChar *attrValue;
6566 xmlChar *repName = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00006567 xmlSchemaElementPtr ret;
6568 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006569 const xmlChar *oldcontainer;
6570 xmlAttrPtr attr, nameAttr;
6571 int minOccurs, maxOccurs;
6572 int isRef = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006573#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006574 xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006575#endif
William M. Bracke7091952004-05-11 15:09:58 +00006576
6577 /* 3.3.3 Constraints on XML Representations of Element Declarations */
6578 /* TODO: Complete implementation of 3.3.6 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006579
Daniel Veillard4255d502002-04-16 15:50:10 +00006580 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6581 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006582
Daniel Veillardc0826a72004-08-10 14:17:33 +00006583 oldcontainer = ctxt->container;
6584
6585 nameAttr = xmlSchemaGetPropNode(node, "name");
6586 attr = xmlSchemaGetPropNode(node, "ref");
6587 if ((topLevel) || (attr == NULL)) {
6588 if (nameAttr == NULL) {
6589 xmlSchemaPMissingAttrErr(ctxt,
6590 XML_SCHEMAP_S4S_ATTR_MISSING,
6591 (xmlChar **) &xmlSchemaElemDesElemDecl, NULL, node,
6592 "name", NULL);
6593 return (NULL);
6594 }
6595 name = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) nameAttr);
6596 } else {
6597 isRef = 1;
6598
6599 }
6600 /*
6601 * ... unless minOccurs=maxOccurs=0, in which case the item corresponds
6602 * to no component at all
6603 * TODO: It might be better to validate the element, even if it won't be
6604 * used.
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006605 */
6606 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
6607 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(nonNegativeInteger | unbounded)");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006608 if ((minOccurs == 0) && (maxOccurs == 0))
6609 return (NULL);
6610 /*
6611 * If we get a "ref" attribute on a local <element> we will assume it's
6612 * a reference - even if there's a "name" attribute; this seems to be more
6613 * robust.
6614 */
6615 if (isRef) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006616 char buf[50];
Daniel Veillardc0826a72004-08-10 14:17:33 +00006617 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix;
6618
6619 /*
6620 * Parse as a particle.
6621 */
6622 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006623 (xmlChar **) &xmlSchemaElemDesElemRef,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006624 NULL, attr, &refNs, &refPrefix, &ref);
6625
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006626 snprintf(buf, 49, "#eRef%d", ctxt->counter++ + 1);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006627 ret = xmlSchemaAddElement(ctxt, schema, (const xmlChar *) buf, NULL, node, 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006628 if (ret == NULL) {
6629 if (repName != NULL)
6630 xmlFree(repName);
6631 return (NULL);
6632 }
6633 ret->type = XML_SCHEMA_TYPE_ELEMENT;
6634 ret->node = node;
6635 ret->ref = ref;
6636 ret->refNs = refNs;
6637 ret->refPrefix = refPrefix;
6638 ret->flags |= XML_SCHEMAS_ELEM_REF;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006639 xmlSchemaCheckReference(ctxt, schema, node, (xmlSchemaTypePtr) ret, refNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006640 /*
6641 * Check for illegal attributes.
6642 */
6643 /*
6644 * 3.3.3 : 2.1
6645 * One of ref or name must be present, but not both
6646 */
6647 if (nameAttr != NULL) {
6648 xmlSchemaPMutualExclAttrErr(ctxt,
6649 XML_SCHEMAP_SRC_ELEMENT_2_1,
6650 &repName, (xmlSchemaTypePtr) ret, nameAttr,
6651 "ref", "name");
6652 }
6653 /* 3.3.3 : 2.2 */
6654 attr = node->properties;
6655 while (attr != NULL) {
6656 if (attr->ns == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006657 if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
6658 xmlStrEqual(attr->name, BAD_CAST "name") ||
6659 xmlStrEqual(attr->name, BAD_CAST "id") ||
6660 xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
6661 xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
6662 {
6663 attr = attr->next;
6664 continue;
6665 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006666 xmlSchemaPCustomAttrErr(ctxt,
6667 XML_SCHEMAP_SRC_ELEMENT_2_2,
6668 &repName, (xmlSchemaTypePtr) ret, attr,
6669 "Only the attributes 'minOccurs', 'maxOccurs' and "
6670 "'id' are allowed in addition to 'ref'");
6671 break;
6672 }
6673 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6674 xmlSchemaPIllegalAttrErr(ctxt,
6675 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6676 &repName, (xmlSchemaTypePtr) ret, attr);
6677 }
6678 attr = attr->next;
6679 }
6680 } else {
6681 const xmlChar *ns = NULL, *fixed;
6682
6683 /*
6684 * Parse as an element declaration.
6685 */
6686 if (xmlSchemaPValAttrNode(ctxt,
6687 (xmlChar **) &xmlSchemaElemDesElemDecl, NULL, nameAttr,
6688 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
6689 return (NULL);
6690 /*
6691 * Evaluate the target namespace.
6692 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006693 if (topLevel) {
6694 ns = schema->targetNamespace;
6695 } else {
6696 attr = xmlSchemaGetPropNode(node, "form");
6697 if (attr != NULL) {
6698 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6699 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
William M. Bracke7091952004-05-11 15:09:58 +00006700 ns = schema->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006701 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
6702 xmlSchemaPSimpleTypeErr(ctxt,
6703 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6704 &repName, NULL, (xmlNodePtr) attr,
6705 NULL, "(qualified | unqualified)",
6706 attrValue, NULL, NULL, NULL);
6707 }
6708 } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
6709 ns = schema->targetNamespace;
William M. Brack2f2a6632004-08-20 23:09:47 +00006710 }
6711 ret = xmlSchemaAddElement(ctxt, schema, name, ns, node, topLevel);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006712 if (ret == NULL) {
6713 if (repName != NULL)
6714 xmlFree(repName);
6715 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006716 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006717 ret->type = XML_SCHEMA_TYPE_ELEMENT;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006718 ret->node = node;
6719 ret->targetNamespace = ns;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006720 /*
6721 * Check for illegal attributes.
6722 */
William M. Bracke7091952004-05-11 15:09:58 +00006723 attr = node->properties;
6724 while (attr != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006725 if (attr->ns == NULL) {
6726 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
6727 (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
6728 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6729 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
6730 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
6731 (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006732 (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
6733 {
6734 if (topLevel == 0) {
6735 if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006736 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006737 (!xmlStrEqual(attr->name, BAD_CAST "form")))
6738 {
6739 if (xmlStrEqual(attr->name, BAD_CAST "substitutionGroup")) {
6740 /*
6741 * 3.3.6 : 3 If there is a non-·absent· {substitution
6742 * group affiliation}, then {scope} must be global.
6743 * TODO: This one is redundant, since the S4S does
6744 * prohibit this attribute on local declarations already;
6745 * so why an explicit error code? Weird spec.
6746 * TODO: Move this to the proper constraint layer.
6747 * TODO: Or better wait for spec 1.1 to come.
6748 */
6749 xmlSchemaPIllegalAttrErr(ctxt,
6750 XML_SCHEMAP_E_PROPS_CORRECT_3,
6751 &repName, (xmlSchemaTypePtr) ret, attr);
6752 } else {
6753 xmlSchemaPIllegalAttrErr(ctxt,
6754 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6755 &repName, (xmlSchemaTypePtr) ret, attr);
6756 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006757 }
6758 } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
6759 (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
6760 (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
6761
6762 xmlSchemaPIllegalAttrErr(ctxt,
6763 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6764 &repName, (xmlSchemaTypePtr) ret, attr);
6765 }
6766 }
6767 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6768
6769 xmlSchemaPIllegalAttrErr(ctxt,
6770 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6771 &repName, (xmlSchemaTypePtr) ret, attr);
William M. Bracke7091952004-05-11 15:09:58 +00006772 }
6773 attr = attr->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006774 }
William M. Bracke7091952004-05-11 15:09:58 +00006775 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006776 * Extract/validate attributes.
6777 */
6778 if (topLevel) {
6779 /*
6780 * Process top attributes of global element declarations here.
6781 */
6782 ret->flags |= XML_SCHEMAS_ELEM_GLOBAL;
6783 ret->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
6784 xmlSchemaPValAttrQName(ctxt, schema, &repName,
6785 (xmlSchemaTypePtr) ret, node, "substitutionGroup",
6786 &(ret->substGroupNs), NULL, &(ret->substGroup));
6787 if (xmlGetBooleanProp(ctxt, &repName, (xmlSchemaTypePtr) ret,
6788 node, "abstract", 0))
6789 ret->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
6790 /*
6791 * Attribute "final".
6792 */
6793 attr = xmlSchemaGetPropNode(node, "final");
6794 if (attr == NULL) {
6795 ret->flags |= XML_SCHEMAS_ELEM_FINAL_ABSENT;
6796 } else {
6797 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6798 if (xmlSchemaPValAttrBlockFinal(attrValue, &(ret->flags),
6799 -1,
6800 XML_SCHEMAS_ELEM_FINAL_EXTENSION,
6801 XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
6802 xmlSchemaPSimpleTypeErr(ctxt,
6803 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6804 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00006805 NULL, "(#all | List of (extension | restriction))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00006806 attrValue, NULL, NULL, NULL);
6807 }
6808 }
6809 }
6810 /*
6811 * Attribute "block".
6812 */
6813 attr = xmlSchemaGetPropNode(node, "block");
6814 if (attr == NULL) {
6815 ret->flags |= XML_SCHEMAS_ELEM_BLOCK_ABSENT;
6816 } else {
6817 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6818 if (xmlSchemaPValAttrBlockFinal(attrValue, &(ret->flags),
6819 -1,
6820 XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
6821 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
6822 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
6823 xmlSchemaPSimpleTypeErr(ctxt,
6824 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6825 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00006826 NULL, "(#all | List of (extension | "
Daniel Veillardc0826a72004-08-10 14:17:33 +00006827 "restriction | substitution))", attrValue,
6828 NULL, NULL, NULL);
6829 }
6830 }
6831 if (xmlGetBooleanProp(ctxt, &repName, (xmlSchemaTypePtr) ret,
6832 node, "nillable", 0))
6833 ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006834
Daniel Veillardc0826a72004-08-10 14:17:33 +00006835 xmlSchemaPValAttrQName(ctxt, schema,
6836 &repName, (xmlSchemaTypePtr) ret, node,
6837 "type", &(ret->namedTypeNs), NULL, &(ret->namedType));
Daniel Veillard4255d502002-04-16 15:50:10 +00006838
Daniel Veillardc0826a72004-08-10 14:17:33 +00006839 ret->value = xmlSchemaGetProp(ctxt, node, "default");
6840 attr = xmlSchemaGetPropNode(node, "fixed");
6841 if (attr != NULL) {
6842 fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6843 if (ret->value != NULL) {
6844 /*
6845 * 3.3.3 : 1
6846 * default and fixed must not both be present.
6847 */
6848 xmlSchemaPMutualExclAttrErr(ctxt,
6849 XML_SCHEMAP_SRC_ELEMENT_1,
6850 &repName, (xmlSchemaTypePtr) ret, attr,
6851 "default", "fixed");
6852 } else {
6853 ret->flags |= XML_SCHEMAS_ELEM_FIXED;
6854 ret->value = fixed;
6855 }
6856 }
6857 }
6858 /*
6859 * Extract/validate common attributes.
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006860 */
6861 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6862 node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006863 ret->minOccurs = minOccurs;
6864 ret->maxOccurs = maxOccurs;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006865 if (topLevel != 1)
6866 xmlSchemaPCheckParticleCorrect_2(ctxt, (xmlSchemaTypePtr) ret,
6867 node, minOccurs, maxOccurs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006868 /*
6869 * And now for the children...
6870 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006871 ctxt->container = ret->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006872 child = node->children;
6873 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006874 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6875 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006876 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006877 if (isRef) {
6878 if (child != NULL) {
6879 xmlSchemaPContentErr(ctxt,
6880 XML_SCHEMAP_SRC_ELEMENT_2_2,
6881 &repName, (xmlSchemaTypePtr) ret, node, child,
6882 NULL, "(annotation?)");
William M. Bracke7091952004-05-11 15:09:58 +00006883 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006884 } else {
William M. Bracke7091952004-05-11 15:09:58 +00006885 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006886 /*
6887 * 3.3.3 : 3
6888 * "type" and either <simpleType> or <complexType> are mutually
6889 * exclusive
6890 */
William M. Bracke7091952004-05-11 15:09:58 +00006891 if (ret->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006892 xmlSchemaPContentErr(ctxt,
6893 XML_SCHEMAP_SRC_ELEMENT_3,
6894 &repName, (xmlSchemaTypePtr) ret, node, child,
6895 "The attribute 'type' and the <complexType> child are "
6896 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006897 } else
Daniel Veillard3646d642004-06-02 19:19:14 +00006898 ret->subtypes = xmlSchemaParseComplexType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00006899 child = child->next;
6900 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006901 /*
6902 * 3.3.3 : 3
6903 * "type" and either <simpleType> or <complexType> are
6904 * mutually exclusive
6905 */
William M. Bracke7091952004-05-11 15:09:58 +00006906 if (ret->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006907 xmlSchemaPContentErr(ctxt,
6908 XML_SCHEMAP_SRC_ELEMENT_3,
6909 &repName, (xmlSchemaTypePtr) ret, node, child,
6910 "The attribute 'type' and the <simpleType> child are "
6911 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006912 } else
Daniel Veillard3646d642004-06-02 19:19:14 +00006913 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00006914 child = child->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006915 }
William M. Bracke7091952004-05-11 15:09:58 +00006916 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00006917 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006918#ifdef IDC_ENABLED
6919 if (IS_SCHEMA(child, "unique")) {
6920 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
6921 XML_SCHEMA_TYPE_IDC_UNIQUE, ret->targetNamespace);
6922 } else if (IS_SCHEMA(child, "key")) {
6923 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
6924 XML_SCHEMA_TYPE_IDC_KEY, ret->targetNamespace);
6925 } else if (IS_SCHEMA(child, "keyref")) {
6926 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
6927 XML_SCHEMA_TYPE_IDC_KEYREF, ret->targetNamespace);
6928 }
6929 if (lastIDC != NULL)
6930 lastIDC->next = curIDC;
6931 else
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006932 ret->idcs = (void *) curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006933 lastIDC = curIDC;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006934#else
6935 TODO
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006936#endif
6937 child = child->next;
William M. Bracke7091952004-05-11 15:09:58 +00006938 }
6939 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006940 xmlSchemaPContentErr(ctxt,
6941 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6942 &repName, (xmlSchemaTypePtr) ret, node, child,
6943 NULL, "(annotation?, ((simpleType | complexType)?, "
6944 "(unique | key | keyref)*))");
6945 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006946
Daniel Veillardc0826a72004-08-10 14:17:33 +00006947 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006948 ctxt->container = oldcontainer;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006949 /*
6950 * Cleanup.
6951 */
6952 if (repName != NULL)
6953 xmlFree(repName);
6954 /*
6955 * NOTE: Element Declaration Representation OK 4. will be checked at a
6956 * different layer.
6957 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006958 return (ret);
6959}
6960
6961/**
6962 * xmlSchemaParseUnion:
6963 * @ctxt: a schema validation context
6964 * @schema: the schema being built
6965 * @node: a subtree containing XML Schema informations
6966 *
6967 * parse a XML schema Union definition
6968 * *WARNING* this interface is highly subject to change
6969 *
William M. Bracke7091952004-05-11 15:09:58 +00006970 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00006971 * 1 in case of success.
6972 */
6973static xmlSchemaTypePtr
6974xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006975 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006976{
6977 xmlSchemaTypePtr type, subtype, last = NULL;
6978 xmlNodePtr child = NULL;
6979 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00006980 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006981
6982 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6983 return (NULL);
6984
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006985 snprintf((char *) name, 30, "#union%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00006986 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006987 if (type == NULL)
6988 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00006989 type->type = XML_SCHEMA_TYPE_UNION;
Daniel Veillard4255d502002-04-16 15:50:10 +00006990 type->node = node;
William M. Brack2f2a6632004-08-20 23:09:47 +00006991 /*
6992 * Check for illegal attributes.
6993 */
6994 attr = node->properties;
6995 while (attr != NULL) {
6996 if (attr->ns == NULL) {
6997 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6998 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
6999 xmlSchemaPIllegalAttrErr(ctxt,
7000 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7001 NULL, type, attr);
7002 }
7003 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7004 xmlSchemaPIllegalAttrErr(ctxt,
7005 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7006 NULL, type, attr);
7007 }
7008 attr = attr->next;
7009 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00007010 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00007011 /*
7012 * Attribute "memberTypes". This is a list of QNames.
7013 * TODO: Validate the QNames.
7014 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00007015 type->base = xmlSchemaGetProp(ctxt, node, "memberTypes");
William M. Brack2f2a6632004-08-20 23:09:47 +00007016 /*
7017 * And now for the children...
7018 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007019 child = node->children;
7020 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007021 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7022 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007023 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007024 while (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007025 subtype = (xmlSchemaTypePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00007026 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007027 if (subtype != NULL) {
7028 if (last == NULL) {
7029 type->subtypes = subtype;
7030 last = subtype;
7031 } else {
7032 last->next = subtype;
7033 last = subtype;
7034 }
7035 last->next = NULL;
7036 }
7037 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007038 }
7039 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007040 /* TODO: Think about the error code. */
7041 xmlSchemaPContentErr(ctxt,
7042 XML_SCHEMAP_UNKNOWN_UNION_CHILD,
7043 NULL, type, node, child, NULL, "(annotation?, simpleType*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00007044 }
7045 return (type);
7046}
7047
7048/**
7049 * xmlSchemaParseList:
7050 * @ctxt: a schema validation context
7051 * @schema: the schema being built
7052 * @node: a subtree containing XML Schema informations
7053 *
7054 * parse a XML schema List definition
7055 * *WARNING* this interface is highly subject to change
7056 *
William M. Bracke7091952004-05-11 15:09:58 +00007057 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00007058 * 1 in case of success.
7059 */
7060static xmlSchemaTypePtr
7061xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007062 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007063{
7064 xmlSchemaTypePtr type, subtype;
7065 xmlNodePtr child = NULL;
7066 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00007067 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00007068
7069 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7070 return (NULL);
7071
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00007072 snprintf((char *) name, 30, "#list%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007073 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007074 if (type == NULL)
7075 return (NULL);
7076 type->node = node;
7077 type->type = XML_SCHEMA_TYPE_LIST;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00007078 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00007079 /*
7080 * Check for illegal attributes.
7081 */
7082 attr = node->properties;
7083 while (attr != NULL) {
7084 if (attr->ns == NULL) {
7085 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7086 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
7087 xmlSchemaPIllegalAttrErr(ctxt,
7088 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7089 NULL, type, attr);
7090 }
7091 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7092 xmlSchemaPIllegalAttrErr(ctxt,
7093 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7094 NULL, type, attr);
7095 }
7096 attr = attr->next;
7097 }
7098 /*
7099 * Attribute "itemType".
7100 */
7101 xmlSchemaPValAttrQName(ctxt, schema, NULL, NULL,
7102 node, "itemType", &(type->baseNs), NULL, &(type->base));
7103 /*
7104 * And now for the children...
7105 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007106 child = node->children;
7107 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007108 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7109 child = child->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00007110 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007111 subtype = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00007112 if (IS_SCHEMA(child, "simpleType")) {
7113 if (type->base != NULL) {
7114 xmlSchemaPCustomErr(ctxt,
7115 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
7116 NULL, type, node,
7117 "The attribute 'itemType' and the <simpleType> child "
7118 "are mutually exclusive", NULL);
7119 } else {
7120 subtype = (xmlSchemaTypePtr)
7121 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
7122 type->subtypes = subtype;
7123 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00007124 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007125 }
7126 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007127 /* TODO: Think about the error code. */
7128 xmlSchemaPContentErr(ctxt,
7129 XML_SCHEMAP_UNKNOWN_LIST_CHILD,
7130 NULL, type, node, child, NULL, "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00007131 }
7132 return (type);
7133}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007134
Daniel Veillard4255d502002-04-16 15:50:10 +00007135/**
7136 * xmlSchemaParseSimpleType:
7137 * @ctxt: a schema validation context
7138 * @schema: the schema being built
7139 * @node: a subtree containing XML Schema informations
7140 *
7141 * parse a XML schema Simple Type definition
7142 * *WARNING* this interface is highly subject to change
7143 *
William M. Bracke7091952004-05-11 15:09:58 +00007144 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardc0826a72004-08-10 14:17:33 +00007145 * 1 in case of success.
Daniel Veillard4255d502002-04-16 15:50:10 +00007146 */
7147static xmlSchemaTypePtr
7148xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00007149 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00007150{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007151 xmlSchemaTypePtr type, subtype, oldCtxtType, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00007152 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007153 const xmlChar *attrValue = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007154 xmlChar *des = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007155 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00007156
7157 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7158 return (NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007159
Daniel Veillardc0826a72004-08-10 14:17:33 +00007160 if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007161 attr = xmlSchemaGetPropNode(node, "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007162 if (attr == NULL) {
7163 xmlSchemaPMissingAttrErr(ctxt,
7164 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007165 (xmlChar **) &xmlSchemaElemDesST, NULL, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007166 "name", NULL);
7167 return (NULL);
7168 } else if (xmlSchemaPValAttrNode(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007169 (xmlChar **) &xmlSchemaElemDesST, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007170 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00007171 return (NULL);
7172 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007173 }
7174
7175 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007176 char buf[40];
Daniel Veillardc0826a72004-08-10 14:17:33 +00007177
Daniel Veillard01fa6152004-06-29 17:04:39 +00007178 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007179 * Parse as local simple type definition.
Daniel Veillard01fa6152004-06-29 17:04:39 +00007180 */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00007181 snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007182 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007183 if (type == NULL)
7184 return (NULL);
7185 type->node = node;
7186 type->type = XML_SCHEMA_TYPE_SIMPLE;
7187 /*
7188 * Check for illegal attributes.
7189 */
7190 attr = node->properties;
7191 while (attr != NULL) {
7192 if (attr->ns == NULL) {
7193 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
7194 xmlSchemaPIllegalAttrErr(ctxt,
7195 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007196 &des, type, attr);
Daniel Veillard01fa6152004-06-29 17:04:39 +00007197 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007198 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7199 xmlSchemaPIllegalAttrErr(ctxt,
7200 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007201 &des, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007202 }
7203 attr = attr->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +00007204 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007205 } else {
7206 /*
7207 * Parse as global simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007208 *
7209 * Note that attrValue is the value of the attribute "name" here.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007210 */
William M. Brack2f2a6632004-08-20 23:09:47 +00007211 type = xmlSchemaAddType(ctxt, schema, attrValue, schema->targetNamespace, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007212 if (type == NULL)
7213 return (NULL);
7214 type->node = node;
7215 type->type = XML_SCHEMA_TYPE_SIMPLE;
7216 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
7217 /*
7218 * Check for illegal attributes.
7219 */
7220 attr = node->properties;
7221 while (attr != NULL) {
7222 if (attr->ns == NULL) {
7223 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7224 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007225 (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007226 xmlSchemaPIllegalAttrErr(ctxt,
7227 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007228 &des, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007229 }
7230 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7231 xmlSchemaPIllegalAttrErr(ctxt,
7232 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007233 &des, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007234 }
7235 attr = attr->next;
7236 }
7237 /*
7238 * Attribute "final".
7239 */
7240 attr = xmlSchemaGetPropNode(node, "final");
7241 if (attr == NULL) {
7242 type->flags |= XML_SCHEMAS_TYPE_FINAL_DEFAULT;
7243 } else {
7244 attrValue = xmlSchemaGetProp(ctxt, node, "final");
7245 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
7246 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
7247 XML_SCHEMAS_TYPE_FINAL_LIST,
7248 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
7249
7250 xmlSchemaPSimpleTypeErr(ctxt,
7251 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007252 &des, type, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00007253 NULL, "(#all | List of (list | union | restriction)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00007254 attrValue, NULL, NULL, NULL);
7255 }
7256 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00007257 }
7258 type->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00007259 xmlSchemaPValAttrID(ctxt, NULL, type, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007260 /*
7261 * And now for the children...
7262 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007263 oldCtxtType = ctxt->ctxtType;
7264 oldParentItem = ctxt->parentItem;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007265 ctxt->ctxtType = type;
7266 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00007267 child = node->children;
7268 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007269 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7270 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007271 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007272 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00007273 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007274 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00007275 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007276 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007277 } else if (IS_SCHEMA(child, "list")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007278 subtype = (xmlSchemaTypePtr)
7279 xmlSchemaParseList(ctxt, schema, child);
7280 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007281 } else if (IS_SCHEMA(child, "union")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007282 subtype = (xmlSchemaTypePtr)
7283 xmlSchemaParseUnion(ctxt, schema, child);
7284 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007285 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007286 type->subtypes = subtype;
7287 if ((child != NULL) || (subtype == NULL)) {
7288 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007289 &des, type, node, child, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007290 "(annotation?, (restriction | list | union))");
Daniel Veillard4255d502002-04-16 15:50:10 +00007291 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007292 ctxt->parentItem = oldParentItem;
7293 ctxt->ctxtType = oldCtxtType;
7294 FREE_AND_NULL(des)
Daniel Veillard01fa6152004-06-29 17:04:39 +00007295
Daniel Veillard4255d502002-04-16 15:50:10 +00007296 return (type);
7297}
7298
7299
7300/**
7301 * xmlSchemaParseGroup:
7302 * @ctxt: a schema validation context
7303 * @schema: the schema being built
7304 * @node: a subtree containing XML Schema informations
7305 *
7306 * parse a XML schema Group definition
7307 * *WARNING* this interface is highly subject to change
7308 *
William M. Bracke7091952004-05-11 15:09:58 +00007309 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00007310 * 1 in case of success.
7311 */
7312static xmlSchemaTypePtr
7313xmlSchemaParseGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00007314 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00007315{
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00007316 xmlSchemaTypePtr item;
7317 xmlNodePtr child = NULL;
7318 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00007319
7320 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00007321 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007322
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00007323 if (topLevel) {
7324 const xmlChar *name;
7325 /*
7326 * Parse as model group definition.
7327 */
7328 attr = xmlSchemaGetPropNode(node, "name");
7329 if (attr == NULL) {
7330 xmlSchemaPMissingAttrErr(ctxt,
7331 XML_SCHEMAP_S4S_ATTR_MISSING,
7332 NULL, NULL, node,
7333 "name", NULL);
7334 return (NULL);
7335 } else if (xmlSchemaPValAttrNode(ctxt,
7336 NULL, NULL, attr,
7337 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7338 return (NULL);
7339 }
7340 item = xmlSchemaAddGroup(ctxt, schema, name,
7341 schema->targetNamespace, node);
7342 if (item == NULL)
7343 return (NULL);
7344 item->node = node;
7345 item->type = XML_SCHEMA_TYPE_GROUP;
7346 item->flags |= XML_SCHEMAS_TYPE_GLOBAL;
7347 /*
7348 * Check for illegal attributes.
7349 */
7350 attr = node->properties;
7351 while (attr != NULL) {
7352 if (attr->ns == NULL) {
7353 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7354 (!xmlStrEqual(attr->name, BAD_CAST "id"))) {
7355 xmlSchemaPIllegalAttrErr(ctxt,
7356 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7357 NULL, item, attr);
7358 }
7359 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7360 xmlSchemaPIllegalAttrErr(ctxt,
7361 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7362 NULL, item, attr);
7363 }
7364 attr = attr->next;
7365 }
7366 xmlSchemaPValAttrID(ctxt, NULL, item, node, BAD_CAST "id");
7367 /*
7368 * And now for the children...
7369 */
7370 child = node->children;
7371 if (IS_SCHEMA(child, "annotation")) {
7372 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7373 child = child->next;
7374 }
7375 if (IS_SCHEMA(child, "all")) {
7376 item->subtypes = (xmlSchemaTypePtr)
7377 xmlSchemaParseAll(ctxt, schema, child);
7378 child = child->next;
7379 } else if (IS_SCHEMA(child, "choice")) {
7380 item->subtypes = xmlSchemaParseChoice(ctxt, schema, child);
7381 child = child->next;
7382 } else if (IS_SCHEMA(child, "sequence")) {
7383 item->subtypes = xmlSchemaParseSequence(ctxt, schema, child);
7384 child = child->next;
7385 }
7386 if (child != NULL) {
7387 xmlSchemaPContentErr(ctxt,
7388 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7389 NULL, item, node, child, NULL,
7390 "(annotation?, (all | choice | sequence)?)");
7391 }
7392 } else {
7393 const xmlChar *ref = NULL, *refNs = NULL, *refPrefix = NULL;
7394 int minOccurs, maxOccurs;
7395 char buf[40];
Daniel Veillard4255d502002-04-16 15:50:10 +00007396
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00007397 /*
7398 * Parse as particle.
7399 */
7400 attr = xmlSchemaGetPropNode(node, "ref");
7401 if (attr == NULL) {
7402 xmlSchemaPMissingAttrErr(ctxt,
7403 XML_SCHEMAP_S4S_ATTR_MISSING,
7404 NULL, NULL, node,
7405 "ref", NULL);
7406 return (NULL);
7407 } else if (xmlSchemaPValAttrNodeQName(ctxt, schema, NULL, NULL,
7408 attr, &refNs, &refPrefix, &ref) != 0) {
7409 return (NULL);
7410 }
7411
7412 /*
7413 * TODO: Validate the element even if no item is created
7414 * (i.e. min/maxOccurs == 0).
7415 */
7416 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
7417 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
7418 "(nonNegativeInteger | unbounded)");
7419 if ((minOccurs == 0) && (maxOccurs == 0)) {
7420 return (NULL);
7421 }
7422
7423 snprintf(buf, 39, "#grRef%d", ctxt->counter++ + 1);
7424 item = xmlSchemaAddGroup(ctxt, schema, (const xmlChar *)buf, NULL, node);
7425 if (item == NULL)
7426 return (NULL);
7427 item->node = node;
7428 item->type = XML_SCHEMA_TYPE_GROUP;
7429 item->ref = ref;
7430 item->refNs = refNs;
7431 xmlSchemaCheckReference(ctxt, schema, node, item, refNs);
7432 item->minOccurs = minOccurs;
7433 item->maxOccurs = maxOccurs;
7434 xmlSchemaPCheckParticleCorrect_2(ctxt, item,
7435 node, item->minOccurs, item->maxOccurs);
7436 /*
7437 * Check for illegal attributes.
7438 */
7439 attr = node->properties;
7440 while (attr != NULL) {
7441 if (attr->ns == NULL) {
7442 if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
7443 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7444 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
7445 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs"))) {
7446 xmlSchemaPIllegalAttrErr(ctxt,
7447 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7448 NULL, item, attr);
7449 }
7450 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7451 xmlSchemaPIllegalAttrErr(ctxt,
7452 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7453 NULL, item, attr);
7454 }
7455 attr = attr->next;
7456 }
7457 xmlSchemaPValAttrID(ctxt, NULL, item, node, BAD_CAST "id");
7458 /*
7459 * And now for the children...
7460 */
7461 child = node->children;
7462 if (IS_SCHEMA(child, "annotation")) {
7463 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7464 child = child->next;
7465 }
7466 if (child != NULL) {
7467 xmlSchemaPContentErr(ctxt,
7468 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7469 NULL, item, node, child, NULL,
7470 "(annotation?, (all | choice | sequence)?)");
7471 }
7472 }
7473
7474 return (item);
Daniel Veillard4255d502002-04-16 15:50:10 +00007475}
7476
7477/**
7478 * xmlSchemaParseAll:
7479 * @ctxt: a schema validation context
7480 * @schema: the schema being built
7481 * @node: a subtree containing XML Schema informations
7482 *
7483 * parse a XML schema All definition
7484 * *WARNING* this interface is highly subject to change
7485 *
William M. Bracke7091952004-05-11 15:09:58 +00007486 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00007487 * 1 in case of success.
7488 */
7489static xmlSchemaTypePtr
7490xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007491 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007492{
7493 xmlSchemaTypePtr type, subtype, last = NULL;
7494 xmlNodePtr child = NULL;
7495 xmlChar name[30];
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00007496 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007497
7498 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7499 return (NULL);
7500
7501
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00007502 snprintf((char *) name, 30, "#all%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007503 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007504 if (type == NULL)
7505 return (NULL);
7506 type->node = node;
Daniel Veillard7646b182002-04-20 06:41:40 +00007507 type->type = XML_SCHEMA_TYPE_ALL;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00007508
7509 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007510
7511 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
7512 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00007513
7514 oldcontainer = ctxt->container;
7515 ctxt->container = (const xmlChar *) name;
Daniel Veillard4255d502002-04-16 15:50:10 +00007516 child = node->children;
7517 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007518 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7519 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007520 }
7521 while (IS_SCHEMA(child, "element")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007522 subtype = (xmlSchemaTypePtr)
7523 xmlSchemaParseElement(ctxt, schema, child, 0);
7524 if (subtype != NULL) {
William M. Brackb15351e2003-12-27 04:34:42 +00007525 if (subtype->minOccurs > 1)
7526 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MINOCCURS,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007527 "invalid value for minOccurs (must be 0 or 1).\n",
William M. Brackb15351e2003-12-27 04:34:42 +00007528 NULL, NULL);
7529 if (subtype->maxOccurs > 1)
7530 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MAXOCCURS,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007531 "invalid value for maxOccurs (must be 0 or 1).\n",
William M. Brackb15351e2003-12-27 04:34:42 +00007532 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007533 if (last == NULL) {
7534 type->subtypes = subtype;
7535 last = subtype;
7536 } else {
7537 last->next = subtype;
7538 last = subtype;
7539 }
7540 last->next = NULL;
7541 }
7542 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007543 }
7544 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007545 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ALL_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007546 "<all> has unexpected content.\n", type->name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007547 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007548 }
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00007549 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007550 return (type);
7551}
7552
7553/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007554 * xmlSchemaCleanupDoc:
7555 * @ctxt: a schema validation context
7556 * @node: the root of the document.
7557 *
7558 * removes unwanted nodes in a schemas document tree
7559 */
7560static void
7561xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
7562{
7563 xmlNodePtr delete, cur;
7564
7565 if ((ctxt == NULL) || (root == NULL)) return;
7566
7567 /*
7568 * Remove all the blank text nodes
7569 */
7570 delete = NULL;
7571 cur = root;
7572 while (cur != NULL) {
7573 if (delete != NULL) {
7574 xmlUnlinkNode(delete);
7575 xmlFreeNode(delete);
7576 delete = NULL;
7577 }
7578 if (cur->type == XML_TEXT_NODE) {
7579 if (IS_BLANK_NODE(cur)) {
7580 if (xmlNodeGetSpacePreserve(cur) != 1) {
7581 delete = cur;
7582 }
7583 }
7584 } else if ((cur->type != XML_ELEMENT_NODE) &&
7585 (cur->type != XML_CDATA_SECTION_NODE)) {
7586 delete = cur;
7587 goto skip_children;
7588 }
7589
7590 /*
7591 * Skip to next node
7592 */
7593 if (cur->children != NULL) {
7594 if ((cur->children->type != XML_ENTITY_DECL) &&
7595 (cur->children->type != XML_ENTITY_REF_NODE) &&
7596 (cur->children->type != XML_ENTITY_NODE)) {
7597 cur = cur->children;
7598 continue;
7599 }
7600 }
7601 skip_children:
7602 if (cur->next != NULL) {
7603 cur = cur->next;
7604 continue;
7605 }
7606
7607 do {
7608 cur = cur->parent;
7609 if (cur == NULL)
7610 break;
7611 if (cur == root) {
7612 cur = NULL;
7613 break;
7614 }
7615 if (cur->next != NULL) {
7616 cur = cur->next;
7617 break;
7618 }
7619 } while (cur != NULL);
7620 }
7621 if (delete != NULL) {
7622 xmlUnlinkNode(delete);
7623 xmlFreeNode(delete);
7624 delete = NULL;
7625 }
7626}
7627
William M. Brack2f2a6632004-08-20 23:09:47 +00007628
7629/**
7630 * xmlSchemaImportSchema
7631 *
7632 * @ctxt: a schema validation context
7633 * @schemaLocation: an URI defining where to find the imported schema
7634 *
7635 * import a XML schema
7636 * *WARNING* this interface is highly subject to change
7637 *
7638 * Returns -1 in case of error and 1 in case of success.
7639 */
7640#if 0
7641static xmlSchemaImportPtr
7642xmlSchemaImportSchema(xmlSchemaParserCtxtPtr ctxt,
7643 const xmlChar *schemaLocation)
7644{
7645 xmlSchemaImportPtr import;
7646 xmlSchemaParserCtxtPtr newctxt;
7647
7648 newctxt = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
7649 if (newctxt == NULL) {
7650 xmlSchemaPErrMemory(ctxt, "allocating schema parser context",
7651 NULL);
7652 return (NULL);
7653 }
7654 memset(newctxt, 0, sizeof(xmlSchemaParserCtxt));
7655 /* Keep the same dictionnary for parsing, really */
7656 xmlDictReference(ctxt->dict);
7657 newctxt->dict = ctxt->dict;
7658 newctxt->includes = 0;
7659 newctxt->URL = xmlDictLookup(newctxt->dict, schemaLocation, -1);
7660
7661 xmlSchemaSetParserErrors(newctxt, ctxt->error, ctxt->warning,
7662 ctxt->userData);
7663
7664 import = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
7665 if (import == NULL) {
7666 xmlSchemaPErrMemory(NULL, "allocating imported schema",
7667 NULL);
7668 xmlSchemaFreeParserCtxt(newctxt);
7669 return (NULL);
7670 }
7671
7672 memset(import, 0, sizeof(xmlSchemaImport));
7673 import->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
7674 import->schema = xmlSchemaParse(newctxt);
7675
7676 if (import->schema == NULL) {
7677 /* FIXME use another error enum here ? */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00007678 xmlSchemaPErr(ctxt, NULL, XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00007679 "Failed to import schema from location \"%s\".\n",
7680 schemaLocation, NULL);
7681
7682 xmlSchemaFreeParserCtxt(newctxt);
7683 /* The schemaLocation is held by the dictionary.
7684 if (import->schemaLocation != NULL)
7685 xmlFree((xmlChar *)import->schemaLocation);
7686 */
7687 xmlFree(import);
7688 return NULL;
7689 }
7690
7691 xmlSchemaFreeParserCtxt(newctxt);
7692 return import;
7693}
7694#endif
7695
7696static void
7697xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
7698{
7699 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
7700 schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
7701
7702 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
7703 schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
7704
7705 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
7706 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
7707 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
7708 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
7709 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
7710 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
7711 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
7712 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
7713
7714 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
7715 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
7716 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
7717 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
7718 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
7719 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
7720}
7721
7722static void
7723xmlSchemaParseSchemaDefaults(xmlSchemaParserCtxtPtr ctxt,
7724 xmlSchemaPtr schema,
7725 xmlNodePtr node)
7726{
7727 xmlAttrPtr attr;
7728 const xmlChar *val;
7729
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00007730 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
7731 if (schema->version == NULL)
7732 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
7733 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &(schema->version));
7734 else
7735 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
7736 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), NULL);
7737
William M. Brack2f2a6632004-08-20 23:09:47 +00007738 attr = xmlSchemaGetPropNode(node, "elementFormDefault");
7739 if (attr != NULL) {
7740 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7741 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
7742 XML_SCHEMAS_QUALIF_ELEM) != 0) {
7743 xmlSchemaPSimpleTypeErr(ctxt,
7744 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
7745 NULL, NULL, (xmlNodePtr) attr, NULL,
7746 "(qualified | unqualified)", val, NULL, NULL, NULL);
7747 }
7748 }
7749
7750 attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
7751 if (attr != NULL) {
7752 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7753 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
7754 XML_SCHEMAS_QUALIF_ATTR) != 0) {
7755 xmlSchemaPSimpleTypeErr(ctxt,
7756 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
7757 NULL, NULL, (xmlNodePtr) attr, NULL,
7758 "(qualified | unqualified)", val, NULL, NULL, NULL);
7759 }
7760 }
7761
7762 attr = xmlSchemaGetPropNode(node, "finalDefault");
7763 if (attr != NULL) {
7764 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7765 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
7766 XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
7767 XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
7768 -1,
7769 XML_SCHEMAS_FINAL_DEFAULT_LIST,
7770 XML_SCHEMAS_FINAL_DEFAULT_UNION) != 0) {
7771 xmlSchemaPSimpleTypeErr(ctxt,
7772 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7773 NULL, NULL, (xmlNodePtr) attr, NULL,
7774 "(#all | List of (extension | restriction | list | union))",
7775 val, NULL, NULL, NULL);
7776 }
7777 }
7778
7779 attr = xmlSchemaGetPropNode(node, "blockDefault");
7780 if (attr != NULL) {
7781 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7782 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
7783 XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
7784 XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
7785 XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1) != 0) {
7786 xmlSchemaPSimpleTypeErr(ctxt,
7787 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7788 NULL, NULL, (xmlNodePtr) attr, NULL,
7789 "(#all | List of (extension | restriction | substitution))",
7790 val, NULL, NULL, NULL);
7791 }
7792 }
7793}
7794
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007795/**
7796 * xmlSchemaParseSchemaTopLevel:
7797 * @ctxt: a schema validation context
7798 * @schema: the schemas
7799 * @nodes: the list of top level nodes
7800 *
7801 * Returns the internal XML Schema structure built from the resource or
7802 * NULL in case of error
7803 */
7804static void
7805xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
7806 xmlSchemaPtr schema, xmlNodePtr nodes)
7807{
7808 xmlNodePtr child;
7809 xmlSchemaAnnotPtr annot;
7810
7811 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
7812 return;
7813
7814 child = nodes;
7815 while ((IS_SCHEMA(child, "include")) ||
7816 (IS_SCHEMA(child, "import")) ||
7817 (IS_SCHEMA(child, "redefine")) ||
7818 (IS_SCHEMA(child, "annotation"))) {
7819 if (IS_SCHEMA(child, "annotation")) {
7820 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7821 if (schema->annot == NULL)
7822 schema->annot = annot;
7823 else
7824 xmlSchemaFreeAnnot(annot);
7825 } else if (IS_SCHEMA(child, "import")) {
7826 xmlSchemaParseImport(ctxt, schema, child);
7827 } else if (IS_SCHEMA(child, "include")) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00007828 ctxt->includes++;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007829 xmlSchemaParseInclude(ctxt, schema, child);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00007830 ctxt->includes--;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007831 } else if (IS_SCHEMA(child, "redefine")) {
7832 TODO
7833 }
7834 child = child->next;
7835 }
7836 while (child != NULL) {
7837 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007838 xmlSchemaParseComplexType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007839 child = child->next;
7840 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007841 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007842 child = child->next;
7843 } else if (IS_SCHEMA(child, "element")) {
7844 xmlSchemaParseElement(ctxt, schema, child, 1);
7845 child = child->next;
7846 } else if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00007847 xmlSchemaParseAttribute(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007848 child = child->next;
7849 } else if (IS_SCHEMA(child, "attributeGroup")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007850 xmlSchemaParseAttributeGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007851 child = child->next;
7852 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007853 xmlSchemaParseGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007854 child = child->next;
7855 } else if (IS_SCHEMA(child, "notation")) {
7856 xmlSchemaParseNotation(ctxt, schema, child);
7857 child = child->next;
7858 } else {
7859 xmlSchemaPErr2(ctxt, NULL, child,
7860 XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007861 "Unexpected element \"%s\" as child of <schema>.\n",
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007862 child->name, NULL);
7863 child = child->next;
7864 }
7865 while (IS_SCHEMA(child, "annotation")) {
7866 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7867 if (schema->annot == NULL)
7868 schema->annot = annot;
7869 else
7870 xmlSchemaFreeAnnot(annot);
7871 child = child->next;
7872 }
7873 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00007874 ctxt->parentItem = NULL;
7875 ctxt->ctxtType = NULL;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007876}
7877
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007878static xmlSchemaImportPtr
7879xmlSchemaAddImport(xmlSchemaParserCtxtPtr ctxt,
7880 xmlHashTablePtr *imports,
7881 const xmlChar *nsName)
7882{
7883 xmlSchemaImportPtr ret;
7884
7885 if (*imports == NULL) {
Daniel Veillardb9e2f262005-01-23 23:48:34 +00007886 *imports = xmlHashCreateDict(10, ctxt->dict);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007887 if (*imports == NULL) {
7888 xmlSchemaPCustomErr(ctxt,
7889 XML_SCHEMAP_FAILED_BUILD_IMPORT,
7890 NULL, NULL, (xmlNodePtr) ctxt->doc,
7891 "Internal error: failed to build the import table",
7892 NULL);
7893 return (NULL);
7894 }
7895 }
7896 ret = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
7897 if (ret == NULL) {
7898 xmlSchemaPErrMemory(NULL, "allocating import struct", NULL);
7899 return (NULL);
7900 }
7901 memset(ret, 0, sizeof(xmlSchemaImport));
7902 if (nsName == NULL)
7903 nsName = XML_SCHEMAS_NO_NAMESPACE;
7904 xmlHashAddEntry(*imports, nsName, ret);
7905
7906 return (ret);
7907}
7908
7909static int
7910xmlSchemaAcquireSchemaDoc(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007911 xmlSchemaPtr schema,
7912 xmlNodePtr node,
7913 const xmlChar *nsName,
7914 const xmlChar *location,
7915 xmlDocPtr *doc,
7916 const xmlChar **targetNamespace,
7917 int absolute)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007918{
7919 xmlParserCtxtPtr parserCtxt;
7920 xmlSchemaImportPtr import;
7921 const xmlChar *ns;
7922 xmlNodePtr root;
7923
7924 /*
7925 * NOTE: This will be used for <import>, <xsi:schemaLocation> and
7926 * <xsi:noNamespaceSchemaLocation>.
7927 */
7928 *doc = NULL;
7929 /*
7930 * Given that the schemaLocation [attribute] is only a hint, it is open
7931 * to applications to ignore all but the first <import> for a given
7932 * namespace, regardless of the ·actual value· of schemaLocation, but
7933 * such a strategy risks missing useful information when new
7934 * schemaLocations are offered.
7935 *
7936 * XSV (ver 2.5-2) does use the first <import> which resolves to a valid schema.
7937 * Xerces-J (ver 2.5.1) ignores all but the first given <import> - regardless if
7938 * valid or not.
7939 * We will follow XSV here.
7940 */
7941 if (location == NULL) {
7942 /*
7943 * Schema Document Location Strategy:
7944 *
7945 * 3 Based on the namespace name, identify an existing schema document,
7946 * either as a resource which is an XML document or a <schema> element
7947 * information item, in some local schema repository;
7948 *
7949 * 5 Attempt to resolve the namespace name to locate such a resource.
7950 *
7951 * NOTE: Those stategies are not supported, so we will skip.
7952 */
7953 return (0);
7954 }
7955 if (nsName == NULL)
7956 ns = XML_SCHEMAS_NO_NAMESPACE;
7957 else
7958 ns = nsName;
7959
7960 import = xmlHashLookup(schema->schemasImports, ns);
7961 if (import != NULL) {
7962 /*
7963 * There was a valid resource for the specified namespace already
7964 * defined, so skip.
7965 * TODO: This might be changed someday to allow import of
7966 * components from multiple documents for a single target namespace.
7967 */
7968 return (0);
7969 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007970
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007971 /*
7972 * Schema Document Location Strategy:
7973 *
7974 * 2 Based on the location URI, identify an existing schema document,
7975 * either as a resource which is an XML document or a <schema> element
7976 * information item, in some local schema repository;
7977 *
7978 * 4 Attempt to resolve the location URI, to locate a resource on the
7979 * web which is or contains or references a <schema> element;
7980 * TODO: Hmm, I don't know if the reference stuff in 4. will work.
7981 *
7982 */
7983 if ((absolute == 0) && (node != NULL)) {
7984 xmlChar *base, *URI;
7985
7986 base = xmlNodeGetBase(node->doc, node);
7987 if (base == NULL) {
7988 URI = xmlBuildURI(location, node->doc->URL);
7989 } else {
7990 URI = xmlBuildURI(location, base);
7991 xmlFree(base);
7992 }
7993 if (URI != NULL) {
7994 location = xmlDictLookup(ctxt->dict, URI, -1);
7995 xmlFree(URI);
7996 }
7997 }
7998 parserCtxt = xmlNewParserCtxt();
7999 if (parserCtxt == NULL) {
8000 xmlSchemaPErrMemory(NULL, "xmlSchemaParseImport: "
8001 "allocating a parser context", NULL);
8002 return(-1);
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00008003 }
8004
8005 if ((ctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
8006 xmlDictFree(parserCtxt->dict);
8007 parserCtxt->dict = ctxt->dict;
8008 xmlDictReference(parserCtxt->dict);
8009 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008010
8011 *doc = xmlCtxtReadFile(parserCtxt, (const char *) location,
8012 NULL, SCHEMAS_PARSE_OPTIONS);
8013
8014 /*
8015 * 2.1 The referent is (a fragment of) a resource which is an
8016 * XML document (see clause 1.1), which in turn corresponds to
8017 * a <schema> element information item in a well-formed information
8018 * set, which in turn corresponds to a valid schema.
8019 * TODO: What to do with the "fragment" stuff?
8020 *
8021 * 2.2 The referent is a <schema> element information item in
8022 * a well-formed information set, which in turn corresponds
8023 * to a valid schema.
8024 * NOTE: 2.2 won't apply, since only XML documents will be processed
8025 * here.
8026 */
8027 if (*doc == NULL) {
8028 xmlErrorPtr lerr;
8029 /*
8030 * It is *not* an error for the application schema reference
8031 * strategy to fail.
8032 *
8033 * If the doc is NULL and the parser error is an IO error we
8034 * will assume that the resource could not be located or accessed.
8035 *
8036 * TODO: Try to find specific error codes to react only on
8037 * localisation failures.
8038 *
8039 * TODO, FIXME: Check the spec: is a namespace added to the imported
8040 * namespaces, even if the schemaLocation did not provide
8041 * a resource? I guess so, since omitting the "schemaLocation"
8042 * attribute, imports a namespace as well.
8043 */
8044 lerr = xmlGetLastError();
8045 if ((lerr != NULL) && (lerr->domain == XML_FROM_IO)) {
8046 xmlFreeParserCtxt(parserCtxt);
8047 return(0);
8048 }
8049
8050 xmlSchemaPCustomErr(ctxt,
8051 XML_SCHEMAP_SRC_IMPORT_2_1,
8052 NULL, NULL, node,
8053 "Failed to parse the resource '%s' for import",
8054 location);
8055 xmlFreeParserCtxt(parserCtxt);
8056 return(XML_SCHEMAP_SRC_IMPORT_2_1);
8057 }
8058 xmlFreeParserCtxt(parserCtxt);
8059
8060 root = xmlDocGetRootElement(*doc);
8061 if (root == NULL) {
8062 xmlSchemaPCustomErr(ctxt,
8063 XML_SCHEMAP_SRC_IMPORT_2_1,
8064 NULL, NULL, node,
8065 "The XML document '%s' to be imported has no document "
8066 "element", location);
8067 xmlFreeDoc(*doc);
8068 *doc = NULL;
8069 return (XML_SCHEMAP_SRC_IMPORT_2_1);
8070 }
8071
8072 xmlSchemaCleanupDoc(ctxt, root);
8073
8074 if (!IS_SCHEMA(root, "schema")) {
8075 xmlSchemaPCustomErr(ctxt,
8076 XML_SCHEMAP_SRC_IMPORT_2_1,
8077 NULL, NULL, node,
8078 "The XML document '%s' to be imported is not a XML schema document",
8079 location);
8080 xmlFreeDoc(*doc);
8081 *doc = NULL;
8082 return (XML_SCHEMAP_SRC_IMPORT_2_1);
8083 }
8084 *targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
8085 /*
8086 * Schema Representation Constraint: Import Constraints and Semantics
8087 */
8088 if (nsName == NULL) {
8089 if (*targetNamespace != NULL) {
8090 xmlSchemaPCustomErr(ctxt,
8091 XML_SCHEMAP_SRC_IMPORT_3_2,
8092 NULL, NULL, node,
8093 "The XML schema to be imported is not expected "
8094 "to have a target namespace; this differs from "
8095 "its target namespace of '%s'", *targetNamespace);
8096 xmlFreeDoc(*doc);
8097 *doc = NULL;
8098 return (XML_SCHEMAP_SRC_IMPORT_3_2);
8099 }
8100 } else {
8101 if (*targetNamespace == NULL) {
8102 xmlSchemaPCustomErr(ctxt,
8103 XML_SCHEMAP_SRC_IMPORT_3_1,
8104 NULL, NULL, node,
8105 "The XML schema to be imported is expected to have a target "
8106 "namespace of '%s'", nsName);
8107 xmlFreeDoc(*doc);
8108 *doc = NULL;
8109 return (XML_SCHEMAP_SRC_IMPORT_3_1);
8110 } else if (!xmlStrEqual(*targetNamespace, nsName)) {
8111 xmlSchemaPCustomErrExt(ctxt,
8112 XML_SCHEMAP_SRC_IMPORT_3_1,
8113 NULL, NULL, node,
8114 "The XML schema to be imported is expected to have a "
8115 "target namespace of '%s'; this differs from "
8116 "its target namespace of '%s'",
8117 nsName, *targetNamespace, NULL);
8118 xmlFreeDoc(*doc);
8119 *doc = NULL;
8120 return (XML_SCHEMAP_SRC_IMPORT_3_1);
8121 }
8122 }
8123
8124 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports), nsName);
8125 if (import == NULL) {
8126 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT,
8127 NULL, NULL, NULL,
8128 "Internal error: xmlSchemaAcquireSchemaDoc, "
8129 "failed to build import table", NULL);
8130 xmlFreeDoc(*doc);
8131 *doc = NULL;
8132 return (-1);
8133 }
8134 import->schemaLocation = location;
8135 import->doc = *doc;
8136 return (0);
8137}
William M. Brack2f2a6632004-08-20 23:09:47 +00008138
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008139static void
8140xmlSchemaParseForImpInc(xmlSchemaParserCtxtPtr pctxt,
8141 xmlSchemaPtr schema,
8142 const xmlChar *targetNamespace,
8143 xmlNodePtr node)
8144{
8145 const xmlChar *oldURL, **oldLocImps, *oldTNS;
8146 int oldFlags, oldNumLocImps, oldSizeLocImps;
8147
8148 /*
8149 * Save and reset the context & schema.
8150 */
8151 oldURL = pctxt->URL;
8152 /* TODO: Is using the doc->URL here correct? */
8153 pctxt->URL = node->doc->URL;
8154 oldLocImps = pctxt->localImports;
8155 pctxt->localImports = NULL;
8156 oldNumLocImps = pctxt->nbLocalImports;
8157 pctxt->nbLocalImports = 0;
8158 oldSizeLocImps = pctxt->sizeLocalImports;
8159 pctxt->sizeLocalImports = 0;
8160 oldFlags = schema->flags;
8161 xmlSchemaClearSchemaDefaults(schema);
8162 oldTNS = schema->targetNamespace;
8163 schema->targetNamespace = targetNamespace;
8164 /*
8165 * Parse the schema.
8166 */
8167 xmlSchemaParseSchemaDefaults(pctxt, schema, node);
8168 xmlSchemaParseSchemaTopLevel(pctxt, schema, node->children);
8169 /*
8170 * Restore the context & schema.
8171 */
8172 schema->flags = oldFlags;
8173 schema->targetNamespace = oldTNS;
8174 if (pctxt->localImports != NULL)
8175 xmlFree((xmlChar *) pctxt->localImports);
8176 pctxt->localImports = oldLocImps;
8177 pctxt->nbLocalImports = oldNumLocImps;
8178 pctxt->sizeLocalImports = oldSizeLocImps;
8179 pctxt->URL = oldURL;
8180}
8181
William M. Brack2f2a6632004-08-20 23:09:47 +00008182/**
8183 * xmlSchemaParseImport:
8184 * @ctxt: a schema validation context
8185 * @schema: the schema being built
8186 * @node: a subtree containing XML Schema informations
8187 *
8188 * parse a XML schema Import definition
8189 * *WARNING* this interface is highly subject to change
8190 *
8191 * Returns 0 in case of success, a positive error code if
8192 * not valid and -1 in case of an internal error.
8193 */
8194static int
8195xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
8196 xmlNodePtr node)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008197{
8198 xmlNodePtr child;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008199 const xmlChar *namespaceName = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00008200 const xmlChar *schemaLocation = NULL;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008201 const xmlChar *targetNamespace;
William M. Brack2f2a6632004-08-20 23:09:47 +00008202 xmlAttrPtr attr;
8203 xmlDocPtr doc;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008204 int ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00008205
8206 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8207 return (-1);
8208
8209 /*
8210 * Check for illegal attributes.
8211 */
8212 attr = node->properties;
8213 while (attr != NULL) {
8214 if (attr->ns == NULL) {
8215 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8216 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
8217 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
8218 xmlSchemaPIllegalAttrErr(ctxt,
8219 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8220 NULL, NULL, attr);
8221 }
8222 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8223 xmlSchemaPIllegalAttrErr(ctxt,
8224 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8225 NULL, NULL, attr);
8226 }
8227 attr = attr->next;
8228 }
8229 /*
8230 * Extract and validate attributes.
8231 */
8232 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
8233 "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008234 &namespaceName) != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008235 xmlSchemaPSimpleTypeErr(ctxt,
8236 XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI,
8237 NULL, NULL, node,
8238 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008239 NULL, namespaceName, NULL, NULL, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00008240 return (XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI);
8241 }
8242
8243 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
8244 "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
8245 &schemaLocation) != 0) {
8246 xmlSchemaPSimpleTypeErr(ctxt,
8247 XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI,
8248 NULL, NULL, node,
8249 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008250 NULL, namespaceName, NULL, NULL, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00008251 return (XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI);
8252 }
8253 /*
8254 * And now for the children...
8255 */
8256 child = node->children;
8257 if (IS_SCHEMA(child, "annotation")) {
8258 /*
8259 * the annotation here is simply discarded ...
8260 */
8261 child = child->next;
8262 }
8263 if (child != NULL) {
8264 xmlSchemaPContentErr(ctxt,
8265 XML_SCHEMAP_UNKNOWN_IMPORT_CHILD,
8266 NULL, NULL, node, child, NULL,
8267 "(annotation?)");
8268 }
8269 /*
8270 * Apply additional constraints.
8271 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008272 if (namespaceName != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008273 /*
8274 * 1.1 If the namespace [attribute] is present, then its ·actual value·
8275 * must not match the ·actual value· of the enclosing <schema>'s
8276 * targetNamespace [attribute].
8277 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008278 if (xmlStrEqual(schema->targetNamespace, namespaceName)) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008279 xmlSchemaPCustomErr(ctxt,
8280 XML_SCHEMAP_SRC_IMPORT_1_1,
8281 NULL, NULL, node,
8282 "The value of the attribute 'namespace' must not match "
8283 "the target namespace '%s' of the importing schema",
8284 schema->targetNamespace);
8285 return (XML_SCHEMAP_SRC_IMPORT_1_1);
8286 }
8287 } else {
8288 /*
8289 * 1.2 If the namespace [attribute] is not present, then the enclosing
8290 * <schema> must have a targetNamespace [attribute].
8291 */
8292 if (schema->targetNamespace == NULL) {
8293 xmlSchemaPCustomErr(ctxt,
8294 XML_SCHEMAP_SRC_IMPORT_1_2,
8295 NULL, NULL, node,
8296 "The attribute 'namespace' must be existent if "
8297 "the importing schema has no target namespace",
8298 NULL);
8299 return (XML_SCHEMAP_SRC_IMPORT_1_2);
8300 }
8301 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008302 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008303 * Add the namespace to the list of locally imported namespace.
8304 */
8305 if (ctxt->localImports == NULL) {
8306 ctxt->localImports = (const xmlChar **) xmlMalloc(10 *
8307 sizeof(const xmlChar*));
8308 ctxt->sizeLocalImports = 10;
8309 ctxt->nbLocalImports = 0;
8310 } else if (ctxt->sizeLocalImports <= ctxt->nbLocalImports) {
8311 ctxt->sizeLocalImports *= 2;
8312 ctxt->localImports = (const xmlChar **) xmlRealloc(
8313 (xmlChar **) ctxt->localImports,
8314 ctxt->sizeLocalImports * sizeof(const xmlChar*));
8315 }
8316 ctxt->localImports[ctxt->nbLocalImports++] = namespaceName;
8317 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008318 * Locate and aquire the schema document.
William M. Brack2f2a6632004-08-20 23:09:47 +00008319 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008320 ret = xmlSchemaAcquireSchemaDoc(ctxt, schema, node, namespaceName,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008321 schemaLocation, &doc, &targetNamespace, 0);
8322 if (ret != 0) {
8323 if (doc != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00008324 xmlFreeDoc(doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008325 return (ret);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008326 } else if (doc != NULL) {
8327 xmlSchemaParseForImpInc(ctxt, schema, targetNamespace,
8328 xmlDocGetRootElement(doc));
William M. Brack2f2a6632004-08-20 23:09:47 +00008329 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008330
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008331 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +00008332}
8333
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008334/**
8335 * xmlSchemaParseInclude:
8336 * @ctxt: a schema validation context
8337 * @schema: the schema being built
8338 * @node: a subtree containing XML Schema informations
8339 *
8340 * parse a XML schema Include definition
8341 *
William M. Bracke7091952004-05-11 15:09:58 +00008342 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008343 * 1 in case of success.
8344 */
8345static int
8346xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
8347 xmlNodePtr node)
8348{
8349 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008350 const xmlChar *schemaLocation, *targetNamespace;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008351 xmlDocPtr doc = NULL;
8352 xmlNodePtr root = NULL;
Daniel Veillardcffc1c72005-03-12 18:54:55 +00008353 xmlSchemaIncludePtr include = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008354 int wasConvertingNs = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00008355 xmlAttrPtr attr;
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00008356 xmlParserCtxtPtr parserCtxt;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008357
8358
8359 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8360 return (-1);
8361
8362 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00008363 * Check for illegal attributes.
8364 */
8365 attr = node->properties;
8366 while (attr != NULL) {
8367 if (attr->ns == NULL) {
8368 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8369 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
8370 xmlSchemaPIllegalAttrErr(ctxt,
8371 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8372 NULL, NULL, attr);
8373 }
8374 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8375 xmlSchemaPIllegalAttrErr(ctxt,
8376 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8377 NULL, NULL, attr);
8378 }
8379 attr = attr->next;
8380 }
8381 /*
8382 * Extract and validate attributes.
8383 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008384 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00008385 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008386 * Preliminary step, extract the URI-Reference for the include and
8387 * make an URI from the base.
8388 */
William M. Brack2f2a6632004-08-20 23:09:47 +00008389 attr = xmlSchemaGetPropNode(node, "schemaLocation");
8390 if (attr != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008391 xmlChar *base = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00008392 xmlChar *uri = NULL;
8393
8394 if (xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
8395 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &schemaLocation) != 0)
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008396 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008397 base = xmlNodeGetBase(node->doc, node);
8398 if (base == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008399 uri = xmlBuildURI(schemaLocation, node->doc->URL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008400 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00008401 uri = xmlBuildURI(schemaLocation, base);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008402 xmlFree(base);
8403 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008404 if (uri == NULL) {
8405 xmlSchemaPErr(ctxt,
8406 node,
8407 XML_SCHEMAP_INTERNAL,
8408 "Internal error: xmlSchemaParseInclude, "
8409 "could not build an URI from the schemaLocation.\n",
8410 NULL, NULL);
8411 goto exit_failure;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008412 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008413 schemaLocation = xmlDictLookup(ctxt->dict, uri, -1);
8414 xmlFree(uri);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008415 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00008416 xmlSchemaPMissingAttrErr(ctxt,
8417 XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI,
8418 NULL, NULL, node, "schemaLocation", NULL);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008419 goto exit_invalid;
8420 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008421 /*
8422 * And now for the children...
8423 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008424 child = node->children;
8425 while (IS_SCHEMA(child, "annotation")) {
8426 /*
8427 * the annotations here are simply discarded ...
8428 */
8429 child = child->next;
8430 }
8431 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008432 xmlSchemaPContentErr(ctxt,
8433 XML_SCHEMAP_UNKNOWN_INCLUDE_CHILD,
8434 NULL, NULL, node, child, NULL,
8435 "(annotation?)");
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008436 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008437 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008438 * Report self-inclusion.
8439 */
8440 if (xmlStrEqual(schemaLocation, ctxt->URL)) {
8441 xmlSchemaPCustomErr(ctxt,
8442 XML_SCHEMAP_SRC_INCLUDE,
8443 NULL, NULL, node,
8444 "The schema document '%s' cannot include itself.",
8445 schemaLocation);
8446 return (XML_SCHEMAP_SRC_INCLUDE);
8447 }
8448 /*
8449 * Check if this one was already processed to avoid incorrect
8450 * duplicate component errors and infinite circular inclusion.
8451 */
8452 include = schema->includes;
8453 while (include != NULL) {
8454 if (xmlStrEqual(include->schemaLocation, schemaLocation)) {
8455 targetNamespace = include->origTargetNamespace;
8456 if (targetNamespace == NULL) {
8457 /*
8458 * Chameleon include: skip only if it was build for
8459 * the targetNamespace of the including schema.
8460 */
8461 if (xmlStrEqual(schema->targetNamespace,
8462 include->targetNamespace)) {
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008463 goto check_targetNamespace;
8464 }
8465 } else {
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008466 goto check_targetNamespace;
8467 }
8468 }
8469 include = include->next;
8470 }
8471 /*
8472 * First step is to parse the input document into an DOM/Infoset
8473 * TODO: Use xmlCtxtReadFile to share the dictionary?
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00008474 */
8475 parserCtxt = xmlNewParserCtxt();
8476 if (parserCtxt == NULL) {
8477 xmlSchemaPErrMemory(NULL, "xmlSchemaParseInclude: "
8478 "allocating a parser context", NULL);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008479 goto exit_failure;
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00008480 }
8481
8482 if ((ctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
8483 xmlDictFree(parserCtxt->dict);
8484 parserCtxt->dict = ctxt->dict;
8485 xmlDictReference(parserCtxt->dict);
8486 }
8487
8488 doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
8489 NULL, SCHEMAS_PARSE_OPTIONS);
8490 xmlFreeParserCtxt(parserCtxt);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008491 if (doc == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008492 /*
8493 * TODO: It is not an error for the ·actual value· of the
8494 * schemaLocation [attribute] to fail to resolve it all, in which
8495 * case no corresponding inclusion is performed.
8496 * So do we need a warning report here?
8497 */
8498 xmlSchemaPCustomErr(ctxt,
8499 XML_SCHEMAP_FAILED_LOAD,
8500 NULL, NULL, node,
8501 "Failed to load the document '%s' for inclusion", schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008502 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008503 }
8504
8505 /*
8506 * Then extract the root of the schema
8507 */
8508 root = xmlDocGetRootElement(doc);
8509 if (root == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008510 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008511 XML_SCHEMAP_NOROOT,
William M. Brack2f2a6632004-08-20 23:09:47 +00008512 NULL, NULL, node,
8513 "The included document '%s' has no document "
8514 "element", schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008515 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008516 }
8517
8518 /*
8519 * Remove all the blank text nodes
8520 */
8521 xmlSchemaCleanupDoc(ctxt, root);
8522
8523 /*
8524 * Check the schemas top level element
8525 */
8526 if (!IS_SCHEMA(root, "schema")) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008527 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008528 XML_SCHEMAP_NOT_SCHEMA,
William M. Brack2f2a6632004-08-20 23:09:47 +00008529 NULL, NULL, node,
8530 "The document '%s' to be included is not a schema document",
8531 schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008532 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008533 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008534
William M. Brack2f2a6632004-08-20 23:09:47 +00008535 targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008536 /*
8537 * 2.1 SII has a targetNamespace [attribute], and its ·actual
8538 * value· is identical to the ·actual value· of the targetNamespace
8539 * [attribute] of SIIÂ’ (which must have such an [attribute]).
8540 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008541check_targetNamespace:
Daniel Veillardc0826a72004-08-10 14:17:33 +00008542 if (targetNamespace != NULL) {
8543 if (schema->targetNamespace == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008544 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008545 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00008546 NULL, NULL, node,
8547 "The target namespace of the included schema "
8548 "'%s' has to be absent, since the including schema "
8549 "has no target namespace",
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008550 schemaLocation);
8551 goto exit_invalid;
William M. Brack2f2a6632004-08-20 23:09:47 +00008552 } else if (!xmlStrEqual(targetNamespace, schema->targetNamespace)) {
8553 xmlSchemaPCustomErrExt(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008554 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00008555 NULL, NULL, node,
8556 "The target namespace '%s' of the included schema '%s' "
8557 "differs from '%s' of the including schema",
8558 targetNamespace, schemaLocation, schema->targetNamespace);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008559 goto exit_invalid;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008560 }
8561 } else if (schema->targetNamespace != NULL) {
8562 if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
8563 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
8564 } else
8565 wasConvertingNs = 1;
8566 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008567
8568 if (include != NULL)
8569 goto exit;
8570
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008571 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008572 * URGENT TODO: If the schema is a chameleon-include then copy the
8573 * components into the including schema and modify the targetNamespace
8574 * of those components, do nothing otherwise.
8575 * NOTE: This is currently worked-around by compiling the chameleon
8576 * for every destinct including targetNamespace; thus not performant at
8577 * the moment.
8578 * TODO: Check when the namespace in wildcards for chameleons needs
8579 * to be converted: before we built wildcard intersections or after.
8580 */
8581 /*
8582 * Register the include.
8583 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008584 include = (xmlSchemaIncludePtr) xmlMalloc(sizeof(xmlSchemaInclude));
8585 if (include == NULL) {
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008586 xmlSchemaPErrMemory(ctxt, "allocating include entry", NULL);
8587 goto exit_failure;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008588 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008589 memset(include, 0, sizeof(xmlSchemaInclude));
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008590 include->next = schema->includes;
8591 schema->includes = include;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008592 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008593 * TODO: Use the resolved URI for the this location, since it might
8594 * differ if using filenames/URIs simultaneosly.
Daniel Veillardc0826a72004-08-10 14:17:33 +00008595 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008596 include->schemaLocation = schemaLocation;
8597 include->doc = doc;
8598 /*
8599 * In case of chameleons, the original target namespace will differ
8600 * from the resulting namespace.
8601 */
8602 include->origTargetNamespace = targetNamespace;
8603 include->targetNamespace = schema->targetNamespace;
8604 /*
8605 * Compile the included schema.
8606 */
8607 xmlSchemaParseForImpInc(ctxt, schema, schema->targetNamespace, root);
8608
8609exit:
Daniel Veillardc0826a72004-08-10 14:17:33 +00008610 /*
8611 * Remove the converting flag.
8612 */
William M. Brack2f2a6632004-08-20 23:09:47 +00008613 if ((wasConvertingNs == 0) &&
8614 (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS))
Daniel Veillardc0826a72004-08-10 14:17:33 +00008615 schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008616 return (1);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008617
8618exit_invalid:
8619 if (doc != NULL) {
8620 if (include != NULL)
8621 include->doc = NULL;
8622 xmlFreeDoc(doc);
8623 }
8624 return (ctxt->err);
8625
8626exit_failure:
8627 if (doc != NULL) {
8628 if (include != NULL)
8629 include->doc = NULL;
8630 xmlFreeDoc(doc);
8631 }
8632 return (-1);
8633
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008634}
8635
8636/**
Daniel Veillard4255d502002-04-16 15:50:10 +00008637 * xmlSchemaParseChoice:
8638 * @ctxt: a schema validation context
8639 * @schema: the schema being built
8640 * @node: a subtree containing XML Schema informations
8641 *
8642 * parse a XML schema Choice definition
8643 * *WARNING* this interface is highly subject to change
8644 *
William M. Bracke7091952004-05-11 15:09:58 +00008645 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00008646 * 1 in case of success.
8647 */
8648static xmlSchemaTypePtr
8649xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008650 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008651{
8652 xmlSchemaTypePtr type, subtype, last = NULL;
8653 xmlNodePtr child = NULL;
8654 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00008655 xmlAttrPtr attr;
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00008656 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00008657
8658 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8659 return (NULL);
8660
8661
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008662 snprintf((char *) name, 30, "#ch%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008663 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00008664 if (type == NULL)
8665 return (NULL);
8666 type->node = node;
8667 type->type = XML_SCHEMA_TYPE_CHOICE;
William M. Brack2f2a6632004-08-20 23:09:47 +00008668 /*
8669 * Check for illegal attributes.
8670 */
8671 attr = node->properties;
8672 while (attr != NULL) {
8673 if (attr->ns == NULL) {
8674 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8675 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
8676 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
8677 xmlSchemaPIllegalAttrErr(ctxt,
8678 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8679 NULL, type, attr);
8680 }
8681 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8682 xmlSchemaPIllegalAttrErr(ctxt,
8683 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8684 NULL, type, attr);
8685 }
8686 attr = attr->next;
8687 }
8688 /*
8689 * Extract and validate attributes.
8690 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00008691 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008692 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
8693 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
8694 "(nonNegativeInteger | unbounded)");
William M. Brack2f2a6632004-08-20 23:09:47 +00008695 /*
8696 * And now for the children...
8697 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00008698 oldcontainer = ctxt->container;
8699 ctxt->container = (const xmlChar *) name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008700 child = node->children;
8701 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008702 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8703 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008704 }
8705 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008706 (IS_SCHEMA(child, "group")) ||
8707 (IS_SCHEMA(child, "any")) ||
8708 (IS_SCHEMA(child, "choice")) ||
8709 (IS_SCHEMA(child, "sequence"))) {
8710 subtype = NULL;
8711 if (IS_SCHEMA(child, "element")) {
8712 subtype = (xmlSchemaTypePtr)
8713 xmlSchemaParseElement(ctxt, schema, child, 0);
8714 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008715 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008716 } else if (IS_SCHEMA(child, "any")) {
8717 subtype = xmlSchemaParseAny(ctxt, schema, child);
8718 } else if (IS_SCHEMA(child, "sequence")) {
8719 subtype = xmlSchemaParseSequence(ctxt, schema, child);
8720 } else if (IS_SCHEMA(child, "choice")) {
8721 subtype = xmlSchemaParseChoice(ctxt, schema, child);
8722 }
8723 if (subtype != NULL) {
8724 if (last == NULL) {
8725 type->subtypes = subtype;
8726 last = subtype;
8727 } else {
8728 last->next = subtype;
8729 last = subtype;
8730 }
8731 last->next = NULL;
8732 }
8733 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008734 }
8735 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008736 /* TODO: error code. */
8737 xmlSchemaPContentErr(ctxt,
8738 XML_SCHEMAP_UNKNOWN_CHOICE_CHILD,
8739 NULL, type, node, child, NULL,
8740 "(annotation?, (element | group | choice | sequence | any)*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00008741 }
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00008742 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00008743 return (type);
8744}
8745
8746/**
8747 * xmlSchemaParseSequence:
8748 * @ctxt: a schema validation context
8749 * @schema: the schema being built
8750 * @node: a subtree containing XML Schema informations
8751 *
8752 * parse a XML schema Sequence definition
8753 * *WARNING* this interface is highly subject to change
8754 *
William M. Bracke7091952004-05-11 15:09:58 +00008755 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00008756 * 1 in case of success.
8757 */
8758static xmlSchemaTypePtr
8759xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008760 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008761{
8762 xmlSchemaTypePtr type, subtype, last = NULL;
8763 xmlNodePtr child = NULL;
8764 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00008765 xmlAttrPtr attr;
8766 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00008767
8768 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8769 return (NULL);
8770
William M. Brack2f2a6632004-08-20 23:09:47 +00008771 oldcontainer = ctxt->container;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008772 snprintf((char *) name, 30, "#seq%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008773 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00008774 if (type == NULL)
8775 return (NULL);
8776 type->node = node;
8777 type->type = XML_SCHEMA_TYPE_SEQUENCE;
William M. Brack2f2a6632004-08-20 23:09:47 +00008778 /*
8779 * Check for illegal attributes.
8780 */
8781 attr = node->properties;
8782 while (attr != NULL) {
8783 if (attr->ns == NULL) {
8784 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8785 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
8786 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
8787 xmlSchemaPIllegalAttrErr(ctxt,
8788 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8789 NULL, type, attr);
8790 }
8791 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8792 xmlSchemaPIllegalAttrErr(ctxt,
8793 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8794 NULL, type, attr);
8795 }
8796 attr = attr->next;
8797 }
8798 /*
8799 * Extract and validate attributes.
8800 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00008801 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008802 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
8803 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
8804 "(nonNegativeInteger | unbounded)");
William M. Brack2f2a6632004-08-20 23:09:47 +00008805 /*
8806 * And now for the children...
8807 */
8808 ctxt->container = (const xmlChar *) name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008809 child = node->children;
8810 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008811 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8812 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008813 }
8814 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008815 (IS_SCHEMA(child, "group")) ||
8816 (IS_SCHEMA(child, "any")) ||
8817 (IS_SCHEMA(child, "choice")) ||
8818 (IS_SCHEMA(child, "sequence"))) {
8819 subtype = NULL;
8820 if (IS_SCHEMA(child, "element")) {
8821 subtype = (xmlSchemaTypePtr)
8822 xmlSchemaParseElement(ctxt, schema, child, 0);
8823 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008824 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008825 } else if (IS_SCHEMA(child, "any")) {
8826 subtype = xmlSchemaParseAny(ctxt, schema, child);
8827 } else if (IS_SCHEMA(child, "choice")) {
8828 subtype = xmlSchemaParseChoice(ctxt, schema, child);
8829 } else if (IS_SCHEMA(child, "sequence")) {
8830 subtype = xmlSchemaParseSequence(ctxt, schema, child);
8831 }
8832 if (subtype != NULL) {
8833 if (last == NULL) {
8834 type->subtypes = subtype;
8835 last = subtype;
8836 } else {
8837 last->next = subtype;
8838 last = subtype;
8839 }
8840 last->next = NULL;
8841 }
8842 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008843 }
8844 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008845 xmlSchemaPContentErr(ctxt,
8846 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
8847 NULL, type, node, child, NULL,
8848 "(annotation?, (element | group | choice | sequence | any)*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00008849 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008850 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00008851
8852 return (type);
8853}
8854
8855/**
8856 * xmlSchemaParseRestriction:
8857 * @ctxt: a schema validation context
8858 * @schema: the schema being built
8859 * @node: a subtree containing XML Schema informations
Daniel Veillard4255d502002-04-16 15:50:10 +00008860 *
8861 * parse a XML schema Restriction definition
8862 * *WARNING* this interface is highly subject to change
8863 *
8864 * Returns the type definition or NULL in case of error
8865 */
8866static xmlSchemaTypePtr
8867xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00008868 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008869{
Daniel Veillard01fa6152004-06-29 17:04:39 +00008870 xmlSchemaTypePtr type, subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00008871 xmlNodePtr child = NULL;
8872 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008873 const xmlChar *oldcontainer;
William M. Brack2f2a6632004-08-20 23:09:47 +00008874 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00008875
8876 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8877 return (NULL);
8878
8879 oldcontainer = ctxt->container;
8880
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008881 snprintf((char *) name, 30, "#restr%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008882 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00008883 if (type == NULL)
8884 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00008885 type->type = XML_SCHEMA_TYPE_RESTRICTION;
Daniel Veillard4255d502002-04-16 15:50:10 +00008886 type->node = node;
William M. Brack2f2a6632004-08-20 23:09:47 +00008887 /*
8888 * Check for illegal attributes.
8889 */
8890 attr = node->properties;
8891 while (attr != NULL) {
8892 if (attr->ns == NULL) {
8893 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8894 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
8895 xmlSchemaPIllegalAttrErr(ctxt,
8896 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8897 NULL, type, attr);
8898 }
8899 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8900 xmlSchemaPIllegalAttrErr(ctxt,
8901 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8902 NULL, type, attr);
8903 }
8904 attr = attr->next;
8905 }
8906 /*
8907 * Extract and validate attributes.
8908 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00008909 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00008910 /*
8911 * Attribute "base".
8912 */
Daniel Veillard4255d502002-04-16 15:50:10 +00008913 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
Daniel Veillard01fa6152004-06-29 17:04:39 +00008914 if ((type->base == NULL) &&
William M. Brack2f2a6632004-08-20 23:09:47 +00008915 (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX)) {
8916 /* TODO: Think about the error code. */
8917 xmlSchemaPMissingAttrErr(ctxt,
8918 XML_SCHEMAP_RESTRICTION_NONAME_NOREF,
8919 NULL, type, node, "base", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008920 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008921 /*
8922 * And now for the children...
8923 */
Daniel Veillard4255d502002-04-16 15:50:10 +00008924 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008925 child = node->children;
8926 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008927 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8928 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008929 }
8930 subtype = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008931 if (ctxt->parentItem->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
8932 if (IS_SCHEMA(child, "all")) {
8933 subtype = (xmlSchemaTypePtr)
8934 xmlSchemaParseAll(ctxt, schema, child);
8935 child = child->next;
8936 type->subtypes = subtype;
8937 } else if (IS_SCHEMA(child, "choice")) {
8938 subtype = xmlSchemaParseChoice(ctxt, schema, child);
8939 child = child->next;
8940 type->subtypes = subtype;
8941 } else if (IS_SCHEMA(child, "sequence")) {
8942 subtype = (xmlSchemaTypePtr)
8943 xmlSchemaParseSequence(ctxt, schema, child);
8944 child = child->next;
8945 type->subtypes = subtype;
8946 } else if (IS_SCHEMA(child, "group")) {
8947 subtype = (xmlSchemaTypePtr)
8948 xmlSchemaParseGroup(ctxt, schema, child, 0);
8949 child = child->next;
8950 type->subtypes = subtype;
8951 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008952 } else if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_SIMPLE) {
8953 if (IS_SCHEMA(child, "simpleType")) {
8954 if (type->base != NULL) {
8955 /*
8956 * src-restriction-base-or-simpleType
8957 * Either the base [attribute] or the simpleType [child] of the
8958 * <restriction> element must be present, but not both.
8959 */
8960 xmlSchemaPContentErr(ctxt,
8961 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
8962 NULL, NULL, type->node, child,
8963 "The attribute 'base' and the <simpleType> child are "
8964 "mutually exclusive", NULL);
8965 } else {
8966 subtype = (xmlSchemaTypePtr)
8967 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
8968 type->baseType = subtype;
8969 }
8970 child = child->next;
8971 }
8972 } else if (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00008973 if (IS_SCHEMA(child, "simpleType")) {
8974 subtype = (xmlSchemaTypePtr)
8975 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008976 type->subtypes = subtype;
8977 child = child->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00008978 }
8979 }
8980 if ((ctxt->ctxtType->type == XML_SCHEMA_TYPE_SIMPLE) ||
8981 (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
8982 xmlSchemaFacetPtr facet, lastfacet = NULL;
8983
Daniel Veillard01fa6152004-06-29 17:04:39 +00008984 /*
8985 * Add the facets to the parent simpleType/complexType.
8986 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00008987 /*
8988 * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
8989 * Simple Type Definition Schema Representation Constraint:
8990 * *Single Facet Value*
8991 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00008992 while ((IS_SCHEMA(child, "minInclusive")) ||
8993 (IS_SCHEMA(child, "minExclusive")) ||
8994 (IS_SCHEMA(child, "maxInclusive")) ||
8995 (IS_SCHEMA(child, "maxExclusive")) ||
8996 (IS_SCHEMA(child, "totalDigits")) ||
8997 (IS_SCHEMA(child, "fractionDigits")) ||
8998 (IS_SCHEMA(child, "pattern")) ||
8999 (IS_SCHEMA(child, "enumeration")) ||
9000 (IS_SCHEMA(child, "whiteSpace")) ||
9001 (IS_SCHEMA(child, "length")) ||
9002 (IS_SCHEMA(child, "maxLength")) ||
9003 (IS_SCHEMA(child, "minLength"))) {
9004 facet = xmlSchemaParseFacet(ctxt, schema, child);
9005 if (facet != NULL) {
9006 if (lastfacet == NULL)
9007 ctxt->ctxtType->facets = facet;
9008 else
9009 lastfacet->next = facet;
9010 lastfacet = facet;
9011 lastfacet->next = NULL;
9012 }
9013 child = child->next;
9014 }
9015 /*
9016 * Create links for derivation and validation.
9017 */
9018 if (lastfacet != NULL) {
9019 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
9020
9021 facet = ctxt->ctxtType->facets;
9022 do {
9023 facetLink = (xmlSchemaFacetLinkPtr) xmlMalloc(sizeof(xmlSchemaFacetLink));
9024 if (facetLink == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009025 xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009026 xmlFree(facetLink);
9027 return (NULL);
9028 }
9029 facetLink->facet = facet;
9030 facetLink->next = NULL;
9031 if (lastFacetLink == NULL)
9032 ctxt->ctxtType->facetSet = facetLink;
9033 else
9034 lastFacetLink->next = facetLink;
9035 lastFacetLink = facetLink;
9036 facet = facet->next;
9037 } while (facet != NULL);
9038 }
9039 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009040 if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX) {
9041 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
9042 if (IS_SCHEMA(child, "anyAttribute")) {
9043 ctxt->ctxtType->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
9044 child = child->next;
9045 }
9046 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009047 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009048 /* TODO: Think about the error code. */
9049 if (ctxt->parentItem->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
9050 xmlSchemaPContentErr(ctxt,
9051 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
9052 NULL, type, node, child, NULL,
9053 "annotation?, (group | all | choice | sequence)?, "
9054 "((attribute | attributeGroup)*, anyAttribute?))");
9055 } else if (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
9056 xmlSchemaPContentErr(ctxt,
9057 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
9058 NULL, type, node, child, NULL,
9059 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
9060 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
9061 "length | minLength | maxLength | enumeration | whiteSpace | "
9062 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
9063 } else {
9064 /* Simple type */
9065 xmlSchemaPContentErr(ctxt,
9066 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
9067 NULL, type, node, child, NULL,
9068 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
9069 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
9070 "length | minLength | maxLength | enumeration | whiteSpace | "
9071 "pattern)*))");
9072 }
9073 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009074 ctxt->container = oldcontainer;
9075 return (type);
9076}
9077
9078/**
9079 * xmlSchemaParseExtension:
9080 * @ctxt: a schema validation context
9081 * @schema: the schema being built
9082 * @node: a subtree containing XML Schema informations
9083 *
9084 * parse a XML schema Extension definition
9085 * *WARNING* this interface is highly subject to change
9086 *
9087 * Returns the type definition or NULL in case of error
9088 */
9089static xmlSchemaTypePtr
9090xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009091 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00009092{
9093 xmlSchemaTypePtr type, subtype;
9094 xmlNodePtr child = NULL;
9095 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009096 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00009097
9098 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9099 return (NULL);
9100
9101 oldcontainer = ctxt->container;
9102
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00009103 snprintf((char *) name, 30, "#ext%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00009104 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00009105 if (type == NULL)
9106 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00009107 type->type = XML_SCHEMA_TYPE_EXTENSION;
Daniel Veillard4255d502002-04-16 15:50:10 +00009108 type->node = node;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00009109
9110 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
9111
Daniel Veillard4255d502002-04-16 15:50:10 +00009112 ctxt->container = name;
9113
9114 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
9115 if (type->base == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009116 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_EXTENSION_NO_BASE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009117 "<extension>: The attribute \"base\" is missing.\n",
9118 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009119 }
9120 child = node->children;
9121 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009122 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
9123 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009124 }
9125 subtype = NULL;
9126
9127 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009128 subtype = xmlSchemaParseAll(ctxt, schema, child);
9129 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009130 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009131 subtype = xmlSchemaParseChoice(ctxt, schema, child);
9132 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009133 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009134 subtype = xmlSchemaParseSequence(ctxt, schema, child);
9135 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009136 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009137 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009138 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009139 }
9140 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009141 type->subtypes = subtype;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009142 if ((ctxt->ctxtType != NULL) &&
9143 (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX)) {
9144 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
9145 if (IS_SCHEMA(child, "anyAttribute")) {
9146 ctxt->ctxtType->attributeWildcard =
9147 xmlSchemaParseAnyAttribute(ctxt, schema, child);
9148 child = child->next;
9149 }
9150 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009151 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009152 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009153 XML_SCHEMAP_UNKNOWN_EXTENSION_CHILD,
9154 "<extension> has unexpected content.\n", type->name,
9155 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009156 }
9157 ctxt->container = oldcontainer;
9158 return (type);
9159}
9160
9161/**
9162 * xmlSchemaParseSimpleContent:
9163 * @ctxt: a schema validation context
9164 * @schema: the schema being built
9165 * @node: a subtree containing XML Schema informations
9166 *
9167 * parse a XML schema SimpleContent definition
9168 * *WARNING* this interface is highly subject to change
9169 *
9170 * Returns the type definition or NULL in case of error
9171 */
9172static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009173xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
9174 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00009175{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009176 xmlSchemaTypePtr type, subtype, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00009177 xmlNodePtr child = NULL;
9178 xmlChar name[30];
9179
9180 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9181 return (NULL);
9182
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00009183 snprintf((char *) name, 30, "#SC%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00009184 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00009185 if (type == NULL)
9186 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00009187 type->type = XML_SCHEMA_TYPE_SIMPLE_CONTENT;
Daniel Veillard4255d502002-04-16 15:50:10 +00009188 type->node = node;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00009189
9190 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00009191
9192 child = node->children;
9193 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009194 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
9195 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009196 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009197 oldParentItem = ctxt->parentItem;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009198 ctxt->parentItem = type;
9199 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00009200 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009201 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009202 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009203 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009204 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009205 subtype = (xmlSchemaTypePtr)
9206 xmlSchemaParseExtension(ctxt, schema, child);
9207 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009208 }
9209 type->subtypes = subtype;
9210 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009211 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009212 XML_SCHEMAP_UNKNOWN_SIMPLECONTENT_CHILD,
9213 "<simpleContent> has unexpected content.\n",
9214 NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009215 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009216 ctxt->parentItem = oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00009217 return (type);
9218}
9219
9220/**
9221 * xmlSchemaParseComplexContent:
9222 * @ctxt: a schema validation context
9223 * @schema: the schema being built
9224 * @node: a subtree containing XML Schema informations
9225 *
9226 * parse a XML schema ComplexContent definition
9227 * *WARNING* this interface is highly subject to change
9228 *
9229 * Returns the type definition or NULL in case of error
9230 */
9231static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009232xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
9233 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00009234{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009235 xmlSchemaTypePtr type, subtype, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00009236 xmlNodePtr child = NULL;
9237 xmlChar name[30];
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009238 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00009239
9240 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9241 return (NULL);
9242
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00009243 snprintf((char *) name, 30, "#CC%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00009244 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00009245 if (type == NULL)
9246 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00009247 type->type = XML_SCHEMA_TYPE_COMPLEX_CONTENT;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009248 type->node = node;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009249 /*
9250 * Check for illegal attributes.
9251 */
9252 attr = node->properties;
9253 while (attr != NULL) {
9254 if (attr->ns == NULL) {
9255 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9256 (!xmlStrEqual(attr->name, BAD_CAST "mixed")))
9257 {
9258 xmlSchemaPIllegalAttrErr(ctxt,
9259 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9260 NULL, NULL, attr);
9261 }
9262 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9263 xmlSchemaPIllegalAttrErr(ctxt,
9264 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9265 NULL, NULL, attr);
9266 }
9267 attr = attr->next;
9268 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00009269
9270 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
9271
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009272 /*
9273 * Handle attribute 'mixed'.
9274 */
9275 if (xmlGetBooleanProp(ctxt, NULL, type, node, "mixed", 0)) {
9276 if ((ctxt->ctxtType->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
9277 ctxt->ctxtType->flags |= XML_SCHEMAS_TYPE_MIXED;
9278 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009279 child = node->children;
9280 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009281 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
9282 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009283 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009284 oldParentItem = ctxt->parentItem;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009285 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00009286 subtype = NULL;
9287 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009288 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00009289 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009290 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009291 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009292 subtype = (xmlSchemaTypePtr)
9293 xmlSchemaParseExtension(ctxt, schema, child);
9294 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009295 }
9296 type->subtypes = subtype;
9297 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009298 xmlSchemaPContentErr(ctxt,
9299 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9300 NULL, NULL, node, child,
9301 NULL, "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +00009302 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009303 ctxt->parentItem = oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00009304 return (type);
9305}
9306
9307/**
9308 * xmlSchemaParseComplexType:
9309 * @ctxt: a schema validation context
9310 * @schema: the schema being built
9311 * @node: a subtree containing XML Schema informations
9312 *
9313 * parse a XML schema Complex Type definition
9314 * *WARNING* this interface is highly subject to change
9315 *
9316 * Returns the type definition or NULL in case of error
9317 */
9318static xmlSchemaTypePtr
9319xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00009320 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00009321{
Daniel Veillard01fa6152004-06-29 17:04:39 +00009322 xmlSchemaTypePtr type, subtype, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00009323 xmlNodePtr child = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009324 const xmlChar *name = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00009325 const xmlChar *oldcontainer;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009326 xmlAttrPtr attr;
9327 const xmlChar *attrValue;
9328 xmlChar *des = NULL; /* The reported designation. */
Daniel Veillard1a380b82004-10-21 16:00:06 +00009329 char buf[40];
9330
Daniel Veillard4255d502002-04-16 15:50:10 +00009331
9332 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9333 return (NULL);
9334
Daniel Veillard01fa6152004-06-29 17:04:39 +00009335 ctxtType = ctxt->ctxtType;
9336
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009337 if (topLevel) {
9338 attr = xmlSchemaGetPropNode(node, "name");
9339 if (attr == NULL) {
9340 xmlSchemaPMissingAttrErr(ctxt,
9341 XML_SCHEMAP_S4S_ATTR_MISSING,
9342 (xmlChar **) &xmlSchemaElemDesCT, NULL, node,
9343 "name", NULL);
9344 return (NULL);
9345 } else if (xmlSchemaPValAttrNode(ctxt,
9346 (xmlChar **) &xmlSchemaElemDesCT, NULL, attr,
9347 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
9348 return (NULL);
9349 }
9350 }
9351
9352 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009353 /*
9354 * Parse as local complex type definition.
9355 */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00009356 snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009357 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
9358 if (type == NULL)
9359 return (NULL);
9360 name = (const xmlChar *) buf;
9361 type->node = node;
9362 type->type = XML_SCHEMA_TYPE_COMPLEX;
9363 /*
9364 * TODO: We need the target namespace.
9365 */
9366 } else {
9367 /*
9368 * Parse as global complex type definition.
9369 */
William M. Brack2f2a6632004-08-20 23:09:47 +00009370 type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace, node);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009371 if (type == NULL)
9372 return (NULL);
9373 type->node = node;
9374 type->type = XML_SCHEMA_TYPE_COMPLEX;
9375 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
9376 /*
9377 * Set defaults.
9378 */
9379 type->flags |= XML_SCHEMAS_TYPE_FINAL_DEFAULT;
9380 type->flags |= XML_SCHEMAS_TYPE_BLOCK_DEFAULT;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00009381 }
9382 type->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009383 /*
9384 * Handle attributes.
9385 */
9386 attr = node->properties;
9387 while (attr != NULL) {
9388 if (attr->ns == NULL) {
9389 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
9390 /*
9391 * Attribute "id".
9392 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00009393 xmlSchemaPValAttrID(ctxt, NULL, type, node,
9394 BAD_CAST "id");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009395 } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
9396 /*
9397 * Attribute "mixed".
9398 */
9399 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
9400 (xmlNodePtr) attr))
9401 type->flags |= XML_SCHEMAS_TYPE_MIXED;
9402 } else if (topLevel) {
9403 /*
9404 * Attributes of global complex type definitions.
9405 */
9406 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
9407 /* Pass. */
9408 } else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
9409 /*
9410 * Attribute "abstract".
9411 */
9412 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
9413 (xmlNodePtr) attr))
9414 type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
9415 } else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
9416 /*
9417 * Attribute "final".
9418 */
9419 attrValue = xmlSchemaGetNodeContent(ctxt,
9420 (xmlNodePtr) attr);
9421 if (xmlSchemaPValAttrBlockFinal(attrValue,
9422 &(type->flags),
9423 -1,
9424 XML_SCHEMAS_TYPE_FINAL_EXTENSION,
9425 XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
9426 -1, -1, -1) != 0)
9427 {
9428 xmlSchemaPSimpleTypeErr(ctxt,
9429 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9430 &des, type, (xmlNodePtr) attr,
9431 NULL,
9432 "(#all | List of (extension | restriction))",
9433 attrValue, NULL, NULL, NULL);
9434 }
9435 } else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
9436 /*
9437 * Attribute "block".
9438 */
9439 attrValue = xmlSchemaGetNodeContent(ctxt,
9440 (xmlNodePtr) attr);
9441 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
9442 -1,
9443 XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
9444 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
9445 -1, -1, -1) != 0) {
9446 xmlSchemaPSimpleTypeErr(ctxt,
9447 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9448 &des, type, (xmlNodePtr) attr,
9449 NULL,
9450 "(#all | List of (extension | restriction)) ",
9451 attrValue, NULL, NULL, NULL);
9452 }
9453 } else {
9454 xmlSchemaPIllegalAttrErr(ctxt,
9455 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9456 &des, type, attr);
9457 }
9458 } else {
9459 xmlSchemaPIllegalAttrErr(ctxt,
9460 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9461 &des, type, attr);
9462 }
9463 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9464 xmlSchemaPIllegalAttrErr(ctxt,
9465 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9466 &des, type, attr);
9467 }
9468 attr = attr->next;
9469 }
9470 /*
9471 * Set as default for attribute wildcards.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009472 * This will be only changed if a complex type
9473 * inherits an attribute wildcard from a base type.
9474 */
9475 type->flags |= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009476 /*
9477 * And now for the children...
9478 */
9479 oldcontainer = ctxt->container;
9480 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +00009481 child = node->children;
9482 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009483 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
9484 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009485 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00009486 ctxt->ctxtType = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00009487 if (IS_SCHEMA(child, "simpleContent")) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009488 /*
9489 * 3.4.3 : 2.2
9490 * Specifying mixed='true' when the <simpleContent>
9491 * alternative is chosen has no effect
9492 */
William M. Bracke7091952004-05-11 15:09:58 +00009493 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
9494 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009495 type->subtypes = xmlSchemaParseSimpleContent(ctxt, schema, child);
9496 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009497 } else if (IS_SCHEMA(child, "complexContent")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009498 type->subtypes = xmlSchemaParseComplexContent(ctxt, schema, child);
9499 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009500 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009501 subtype = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009502 /*
9503 * Parse model groups.
9504 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009505 if (IS_SCHEMA(child, "all")) {
9506 subtype = xmlSchemaParseAll(ctxt, schema, child);
9507 child = child->next;
9508 } else if (IS_SCHEMA(child, "choice")) {
9509 subtype = xmlSchemaParseChoice(ctxt, schema, child);
9510 child = child->next;
9511 } else if (IS_SCHEMA(child, "sequence")) {
9512 subtype = xmlSchemaParseSequence(ctxt, schema, child);
9513 child = child->next;
9514 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00009515 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009516 child = child->next;
9517 }
9518 if (subtype != NULL)
9519 type->subtypes = subtype;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009520 /*
9521 * Parse attribute decls/refs.
9522 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009523 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009524 /*
9525 * Parse attribute wildcard.
9526 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009527 if (IS_SCHEMA(child, "anyAttribute")) {
9528 type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
9529 child = child->next;
9530 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009531 }
9532 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009533 xmlSchemaPContentErr(ctxt,
9534 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9535 &des, type, node, child,
9536 NULL, "(annotation?, (simpleContent | complexContent | "
9537 "((group | all | choice | sequence)?, ((attribute | "
9538 "attributeGroup)*, anyAttribute?))))");
Daniel Veillard4255d502002-04-16 15:50:10 +00009539 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009540 FREE_AND_NULL(des);
Daniel Veillard4255d502002-04-16 15:50:10 +00009541 ctxt->container = oldcontainer;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009542 ctxt->ctxtType = ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00009543 return (type);
9544}
9545
Daniel Veillard4255d502002-04-16 15:50:10 +00009546/**
9547 * xmlSchemaParseSchema:
9548 * @ctxt: a schema validation context
9549 * @node: a subtree containing XML Schema informations
9550 *
9551 * parse a XML schema definition from a node set
9552 * *WARNING* this interface is highly subject to change
9553 *
9554 * Returns the internal XML Schema structure built from the resource or
9555 * NULL in case of error
9556 */
9557static xmlSchemaPtr
9558xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
9559{
9560 xmlSchemaPtr schema = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009561 const xmlChar *val;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00009562 int nberrors;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009563 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00009564
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009565 /*
9566 * This one is called by xmlSchemaParse only and is used if
9567 * the schema to be parsed was specified via the API; i.e. not
9568 * automatically by the validated instance document.
9569 */
Daniel Veillard4255d502002-04-16 15:50:10 +00009570 if ((ctxt == NULL) || (node == NULL))
9571 return (NULL);
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00009572 nberrors = ctxt->nberrors;
9573 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00009574 if (IS_SCHEMA(node, "schema")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009575 xmlSchemaImportPtr import;
9576
Daniel Veillard4255d502002-04-16 15:50:10 +00009577 schema = xmlSchemaNewSchema(ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009578 if (schema == NULL)
9579 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009580 /*
9581 * Disable build of list of items.
9582 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00009583 attr = xmlSchemaGetPropNode(node, "targetNamespace");
9584 if (attr != NULL) {
9585 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
9586 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &val);
9587 /*
9588 * TODO: Should we proceed with an invalid target namespace?
9589 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009590 schema->targetNamespace = xmlDictLookup(ctxt->dict, val, -1);
9591 } else {
9592 schema->targetNamespace = NULL;
9593 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009594 /*
9595 * Add the current ns name and location to the import table;
9596 * this is needed to have a consistent mechanism, regardless
9597 * if all schemata are constructed dynamically fired by the
9598 * instance or if the schema to be used was specified via
9599 * the API.
9600 */
9601 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports),
9602 schema->targetNamespace);
9603 if (import == NULL) {
9604 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT,
9605 NULL, NULL, (xmlNodePtr) ctxt->doc,
9606 "Internal error: xmlSchemaParseSchema, "
9607 "failed to add an import entry", NULL);
9608 xmlSchemaFree(schema);
9609 schema = NULL;
9610 return (NULL);
9611 }
9612 import->schemaLocation = ctxt->URL;
9613 /*
9614 * NOTE: We won't set the doc here, otherwise it will be freed
9615 * if the import struct is freed.
9616 * import->doc = ctxt->doc;
9617 */
William M. Brack2f2a6632004-08-20 23:09:47 +00009618 xmlSchemaParseSchemaDefaults(ctxt, schema, node);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009619 xmlSchemaParseSchemaTopLevel(ctxt, schema, node->children);
9620 } else {
9621 xmlDocPtr doc;
9622
9623 doc = node->doc;
9624
9625 if ((doc != NULL) && (doc->URL != NULL)) {
9626 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
9627 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009628 "The file \"%s\" is not a XML schema.\n", doc->URL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009629 } else {
9630 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
9631 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009632 "The file is not a XML schema.\n", NULL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009633 }
9634 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009635 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00009636 if (ctxt->nberrors != 0) {
9637 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009638 xmlSchemaFree(schema);
9639 schema = NULL;
9640 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00009641 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009642 if (schema != NULL)
9643 schema->counter = ctxt->counter;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00009644 ctxt->nberrors = nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00009645#ifdef DEBUG
9646 if (schema == NULL)
9647 xmlGenericError(xmlGenericErrorContext,
9648 "xmlSchemaParse() failed\n");
9649#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00009650 return (schema);
9651}
9652
9653/************************************************************************
9654 * *
9655 * Validating using Schemas *
9656 * *
9657 ************************************************************************/
9658
9659/************************************************************************
9660 * *
9661 * Reading/Writing Schemas *
9662 * *
9663 ************************************************************************/
9664
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009665#if 0 /* Will be enabled if it is clear what options are needed. */
9666/**
9667 * xmlSchemaParserCtxtSetOptions:
9668 * @ctxt: a schema parser context
9669 * @options: a combination of xmlSchemaParserOption
9670 *
9671 * Sets the options to be used during the parse.
9672 *
9673 * Returns 0 in case of success, -1 in case of an
9674 * API error.
9675 */
9676static int
9677xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
9678 int options)
9679
9680{
9681 int i;
9682
9683 if (ctxt == NULL)
9684 return (-1);
9685 /*
9686 * WARNING: Change the start value if adding to the
9687 * xmlSchemaParseOption.
9688 */
9689 for (i = 1; i < (int) sizeof(int) * 8; i++) {
9690 if (options & 1<<i) {
9691 return (-1);
9692 }
9693 }
9694 ctxt->options = options;
9695 return (0);
9696}
9697
9698/**
9699 * xmlSchemaValidCtxtGetOptions:
9700 * @ctxt: a schema parser context
9701 *
9702 * Returns the option combination of the parser context.
9703 */
9704static int
9705xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
9706
9707{
9708 if (ctxt == NULL)
9709 return (-1);
9710 else
9711 return (ctxt->options);
9712}
9713
9714 void *curItems; /* used for dynamic addition of schemata */
9715 int nbCurItems; /* used for dynamic addition of schemata */
9716 int sizeCurItems; /* used for dynamic addition of schemata */
9717
9718#endif
9719
Daniel Veillard4255d502002-04-16 15:50:10 +00009720/**
9721 * xmlSchemaNewParserCtxt:
9722 * @URL: the location of the schema
9723 *
9724 * Create an XML Schemas parse context for that file/resource expected
9725 * to contain an XML Schemas file.
9726 *
9727 * Returns the parser context or NULL in case of error
9728 */
9729xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009730xmlSchemaNewParserCtxt(const char *URL)
9731{
Daniel Veillard4255d502002-04-16 15:50:10 +00009732 xmlSchemaParserCtxtPtr ret;
9733
9734 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009735 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009736
9737 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9738 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009739 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009740 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009741 return (NULL);
9742 }
9743 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009744 ret->dict = xmlDictCreate();
9745 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00009746 ret->includes = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00009747 return (ret);
9748}
9749
9750/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009751 * xmlSchemaNewParserCtxtUseDict:
9752 * @URL: the location of the schema
9753 * @dict: the dictionary to be used
9754 *
9755 * Create an XML Schemas parse context for that file/resource expected
9756 * to contain an XML Schemas file.
9757 *
9758 * Returns the parser context or NULL in case of error
9759 */
9760static xmlSchemaParserCtxtPtr
9761xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
9762{
9763 xmlSchemaParserCtxtPtr ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009764 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009765 if (URL == NULL)
9766 return (NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009767 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009768
9769 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9770 if (ret == NULL) {
9771 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
9772 NULL);
9773 return (NULL);
9774 }
9775 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
9776 ret->dict = dict;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009777 xmlDictReference(dict);
9778 if (URL != NULL)
9779 ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009780 ret->includes = 0;
9781 return (ret);
9782}
9783
9784
9785/**
Daniel Veillard6045c902002-10-09 21:13:59 +00009786 * xmlSchemaNewMemParserCtxt:
9787 * @buffer: a pointer to a char array containing the schemas
9788 * @size: the size of the array
9789 *
9790 * Create an XML Schemas parse context for that memory buffer expected
9791 * to contain an XML Schemas file.
9792 *
9793 * Returns the parser context or NULL in case of error
9794 */
9795xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009796xmlSchemaNewMemParserCtxt(const char *buffer, int size)
9797{
Daniel Veillard6045c902002-10-09 21:13:59 +00009798 xmlSchemaParserCtxtPtr ret;
9799
9800 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009801 return (NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00009802
9803 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9804 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009805 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009806 NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00009807 return (NULL);
9808 }
9809 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
9810 ret->buffer = buffer;
9811 ret->size = size;
William M. Brackcf9eadf2003-12-25 13:24:05 +00009812 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +00009813 return (ret);
9814}
9815
9816/**
Daniel Veillard9d751502003-10-29 13:21:47 +00009817 * xmlSchemaNewDocParserCtxt:
9818 * @doc: a preparsed document tree
9819 *
9820 * Create an XML Schemas parse context for that document.
9821 * NB. The document may be modified during the parsing process.
9822 *
9823 * Returns the parser context or NULL in case of error
9824 */
9825xmlSchemaParserCtxtPtr
9826xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
9827{
9828 xmlSchemaParserCtxtPtr ret;
9829
9830 if (doc == NULL)
9831 return (NULL);
9832
9833 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9834 if (ret == NULL) {
9835 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
9836 NULL);
9837 return (NULL);
9838 }
9839 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
9840 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +00009841 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +00009842 /* The application has responsibility for the document */
9843 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +00009844
9845 return (ret);
9846}
9847
9848/**
Daniel Veillard4255d502002-04-16 15:50:10 +00009849 * xmlSchemaFreeParserCtxt:
9850 * @ctxt: the schema parser context
9851 *
9852 * Free the resources associated to the schema parser context
9853 */
9854void
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009855xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
9856{
Daniel Veillard4255d502002-04-16 15:50:10 +00009857 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009858 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +00009859 if (ctxt->doc != NULL && !ctxt->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009860 xmlFreeDoc(ctxt->doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009861 if (ctxt->assemble != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009862 xmlFree((xmlSchemaTypePtr *) ctxt->assemble->items);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009863 xmlFree(ctxt->assemble);
9864 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009865 if (ctxt->vctxt != NULL) {
9866 xmlSchemaFreeValidCtxt(ctxt->vctxt);
9867 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009868 if (ctxt->localImports != NULL)
9869 xmlFree((xmlChar *) ctxt->localImports);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009870 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00009871 xmlFree(ctxt);
9872}
9873
9874/************************************************************************
9875 * *
9876 * Building the content models *
9877 * *
9878 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009879
Daniel Veillard4255d502002-04-16 15:50:10 +00009880/**
9881 * xmlSchemaBuildAContentModel:
9882 * @type: the schema type definition
9883 * @ctxt: the schema parser context
9884 * @name: the element name whose content is being built
9885 *
9886 * Generate the automata sequence needed for that type
9887 */
9888static void
9889xmlSchemaBuildAContentModel(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009890 xmlSchemaParserCtxtPtr ctxt,
9891 const xmlChar * name)
9892{
Daniel Veillard4255d502002-04-16 15:50:10 +00009893 if (type == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009894 xmlGenericError(xmlGenericErrorContext,
9895 "Found unexpected type = NULL in %s content model\n",
9896 name);
9897 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00009898 }
9899 switch (type->type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009900 case XML_SCHEMA_TYPE_ANY: {
9901 xmlAutomataStatePtr start, end;
9902 xmlSchemaWildcardPtr wild;
9903 xmlSchemaWildcardNsPtr ns;
Daniel Veillard32370232002-10-16 14:08:14 +00009904
Daniel Veillardc0826a72004-08-10 14:17:33 +00009905 wild = type->attributeWildcard;
9906
9907 if (wild == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00009908 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009909 "Internal error: xmlSchemaBuildAContentModel, "
9910 "no wildcard on xsd:any.\n", NULL, NULL);
9911 return;
9912 }
9913
9914 start = ctxt->state;
9915 end = xmlAutomataNewState(ctxt->am);
9916
9917 if (type->maxOccurs == 1) {
9918 if (wild->any == 1) {
9919 /*
9920 * We need to add both transitions:
9921 *
9922 * 1. the {"*", "*"} for elements in a namespace.
9923 */
9924 ctxt->state =
9925 xmlAutomataNewTransition2(ctxt->am,
9926 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
9927 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9928 /*
9929 * 2. the {"*"} for elements in no namespace.
9930 */
9931 ctxt->state =
9932 xmlAutomataNewTransition2(ctxt->am,
9933 start, NULL, BAD_CAST "*", NULL, type);
9934 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9935
9936 } else if (wild->nsSet != NULL) {
9937 ns = wild->nsSet;
9938 do {
9939 ctxt->state = start;
9940 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9941 ctxt->state, NULL, BAD_CAST "*", ns->value, type);
9942 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9943 ns = ns->next;
9944 } while (ns != NULL);
9945
9946 } else if (wild->negNsSet != NULL) {
9947 xmlAutomataStatePtr deadEnd;
9948
9949 deadEnd = xmlAutomataNewState(ctxt->am);
9950 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9951 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, type);
9952 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9953 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
9954 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9955 }
9956 } else {
9957 int counter;
9958 xmlAutomataStatePtr hop;
9959 int maxOccurs =
9960 type->maxOccurs == UNBOUNDED ? UNBOUNDED : type->maxOccurs - 1;
9961 int minOccurs =
9962 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
9963
9964 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
9965 hop = xmlAutomataNewState(ctxt->am);
9966 if (wild->any == 1) {
9967 ctxt->state =
9968 xmlAutomataNewTransition2(ctxt->am,
9969 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
9970 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
9971 ctxt->state =
9972 xmlAutomataNewTransition2(ctxt->am,
9973 start, NULL, BAD_CAST "*", NULL, type);
9974 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
9975 } else if (wild->nsSet != NULL) {
9976 ns = wild->nsSet;
9977 do {
9978 ctxt->state =
9979 xmlAutomataNewTransition2(ctxt->am,
9980 start, NULL, BAD_CAST "*", ns->value, type);
9981 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
9982 ns = ns->next;
9983 } while (ns != NULL);
9984
9985 } else if (wild->negNsSet != NULL) {
9986 xmlAutomataStatePtr deadEnd;
9987
9988 deadEnd = xmlAutomataNewState(ctxt->am);
9989 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9990 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, type);
9991 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9992 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
9993 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
9994 }
9995 xmlAutomataNewCountedTrans(ctxt->am, hop, start, counter);
9996 xmlAutomataNewCounterTrans(ctxt->am, hop, end, counter);
9997 }
9998 if (type->minOccurs == 0) {
9999 xmlAutomataNewEpsilon(ctxt->am, start, end);
10000 }
10001 ctxt->state = end;
10002 break;
10003 }
10004 case XML_SCHEMA_TYPE_ELEMENT:{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010005 xmlAutomataStatePtr oldstate;
10006 xmlSchemaElementPtr particle, elemDecl;
Daniel Veillard32370232002-10-16 14:08:14 +000010007
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010008 /*
10009 * IMPORTANT: This puts element declarations
10010 * (and never element decl. references) into the
10011 * automaton. This is crucial and should not be changed,
10012 * since validating functions rely now on it.
10013 */
10014 particle = (xmlSchemaElementPtr) type;
10015 if (particle->ref != NULL) {
10016 if (particle->refDecl == NULL) {
10017 /*
10018 * Skip content model creation if the reference
10019 * did not resolve to a declaration.
10020 */
10021 break;
10022 } else {
10023 /*
10024 * Referenced global element declaration.
10025 */
10026 elemDecl = particle->refDecl;
10027 }
10028 } else {
10029 /*
10030 * Anonymous element declaration.
10031 */
10032 elemDecl = particle;
10033 }
10034
10035 oldstate = ctxt->state;
10036
10037 if (particle->maxOccurs >= UNBOUNDED) {
10038 if (particle->minOccurs > 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010039 xmlAutomataStatePtr tmp;
10040 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +000010041
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010042 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010043 oldstate, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010044 oldstate = ctxt->state;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010045 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010046 particle->minOccurs - 1, UNBOUNDED);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000010047 ctxt->state =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010048 xmlAutomataNewTransition2(ctxt->am,
10049 ctxt->state, NULL,
10050 elemDecl->name,
10051 elemDecl->targetNamespace,
10052 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010053 tmp = ctxt->state;
10054 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010055 counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010056 ctxt->state =
10057 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010058 counter);
Daniel Veillard32370232002-10-16 14:08:14 +000010059
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010060 } else {
10061 ctxt->state =
10062 xmlAutomataNewTransition2(ctxt->am,
10063 ctxt->state, NULL,
10064 elemDecl->name,
10065 elemDecl->targetNamespace,
10066 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010067 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
10068 oldstate);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010069 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010070 /* basically an elem* */
10071 xmlAutomataNewEpsilon(ctxt->am, oldstate,
10072 ctxt->state);
10073 }
10074 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010075 } else if ((particle->maxOccurs > 1) || (particle->minOccurs > 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010076 xmlAutomataStatePtr tmp;
10077 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +000010078
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010079 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
10080 oldstate, NULL);
10081 oldstate = ctxt->state;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010082 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010083 particle->minOccurs - 1,
10084 particle->maxOccurs - 1);
10085 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
10086 ctxt->state,
10087 NULL,
10088 elemDecl->name,
10089 elemDecl->targetNamespace,
10090 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010091 tmp = ctxt->state;
10092 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010093 counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010094 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, tmp,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010095 NULL, counter);
10096 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010097 /* basically an elem? */
10098 xmlAutomataNewEpsilon(ctxt->am, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010099 ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010100 }
Daniel Veillardb39bc392002-10-26 19:29:51 +000010101
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010102 } else {
10103 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
10104 ctxt->state,
10105 NULL,
10106 elemDecl->name,
10107 elemDecl->targetNamespace,
10108 (xmlSchemaTypePtr) elemDecl);
10109 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010110 /* basically an elem? */
10111 xmlAutomataNewEpsilon(ctxt->am, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010112 ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010113 }
10114 }
10115 break;
10116 }
10117 case XML_SCHEMA_TYPE_SEQUENCE:{
10118 xmlSchemaTypePtr subtypes;
Daniel Veillardb39bc392002-10-26 19:29:51 +000010119
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010120 /*
10121 * If max and min occurances are default (1) then
10122 * simply iterate over the subtypes
10123 */
10124 if ((type->minOccurs == 1) && (type->maxOccurs == 1)) {
10125 subtypes = type->subtypes;
10126 while (subtypes != NULL) {
10127 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
10128 subtypes = subtypes->next;
10129 }
10130 } else {
10131 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000010132
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010133 if (type->maxOccurs >= UNBOUNDED) {
10134 if (type->minOccurs > 1) {
10135 xmlAutomataStatePtr tmp;
10136 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000010137
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010138 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
10139 oldstate,
10140 NULL);
10141 oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000010142
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010143 counter = xmlAutomataNewCounter(ctxt->am,
10144 type->
10145 minOccurs - 1,
10146 UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +000010147
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010148 subtypes = type->subtypes;
10149 while (subtypes != NULL) {
10150 xmlSchemaBuildAContentModel(subtypes, ctxt,
10151 name);
10152 subtypes = subtypes->next;
10153 }
10154 tmp = ctxt->state;
10155 xmlAutomataNewCountedTrans(ctxt->am, tmp,
10156 oldstate, counter);
10157 ctxt->state =
10158 xmlAutomataNewCounterTrans(ctxt->am, tmp,
10159 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +000010160
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010161 } else {
10162 subtypes = type->subtypes;
10163 while (subtypes != NULL) {
10164 xmlSchemaBuildAContentModel(subtypes, ctxt,
10165 name);
10166 subtypes = subtypes->next;
10167 }
10168 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
10169 oldstate);
10170 if (type->minOccurs == 0) {
10171 xmlAutomataNewEpsilon(ctxt->am, oldstate,
10172 ctxt->state);
10173 }
10174 }
10175 } else if ((type->maxOccurs > 1)
10176 || (type->minOccurs > 1)) {
10177 xmlAutomataStatePtr tmp;
10178 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000010179
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010180 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
10181 oldstate,
10182 NULL);
10183 oldstate = ctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +000010184
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010185 counter = xmlAutomataNewCounter(ctxt->am,
10186 type->minOccurs -
10187 1,
10188 type->maxOccurs -
10189 1);
Daniel Veillard4255d502002-04-16 15:50:10 +000010190
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010191 subtypes = type->subtypes;
10192 while (subtypes != NULL) {
10193 xmlSchemaBuildAContentModel(subtypes, ctxt,
10194 name);
10195 subtypes = subtypes->next;
10196 }
10197 tmp = ctxt->state;
10198 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
10199 counter);
10200 ctxt->state =
10201 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
10202 counter);
10203 if (type->minOccurs == 0) {
10204 xmlAutomataNewEpsilon(ctxt->am, oldstate,
10205 ctxt->state);
10206 }
Daniel Veillardb509f152002-04-17 16:28:10 +000010207
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010208 } else {
10209 subtypes = type->subtypes;
10210 while (subtypes != NULL) {
10211 xmlSchemaBuildAContentModel(subtypes, ctxt,
10212 name);
10213 subtypes = subtypes->next;
10214 }
10215 if (type->minOccurs == 0) {
10216 xmlAutomataNewEpsilon(ctxt->am, oldstate,
10217 ctxt->state);
10218 }
10219 }
10220 }
10221 break;
10222 }
10223 case XML_SCHEMA_TYPE_CHOICE:{
10224 xmlSchemaTypePtr subtypes;
10225 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +000010226
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010227 start = ctxt->state;
10228 end = xmlAutomataNewState(ctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +000010229
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010230 /*
10231 * iterate over the subtypes and remerge the end with an
10232 * epsilon transition
10233 */
10234 if (type->maxOccurs == 1) {
10235 subtypes = type->subtypes;
10236 while (subtypes != NULL) {
10237 ctxt->state = start;
10238 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
10239 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
10240 subtypes = subtypes->next;
10241 }
10242 } else {
10243 int counter;
10244 xmlAutomataStatePtr hop;
10245 int maxOccurs = type->maxOccurs == UNBOUNDED ?
10246 UNBOUNDED : type->maxOccurs - 1;
10247 int minOccurs =
10248 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +000010249
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010250 /*
10251 * use a counter to keep track of the number of transtions
10252 * which went through the choice.
10253 */
10254 counter =
10255 xmlAutomataNewCounter(ctxt->am, minOccurs,
10256 maxOccurs);
10257 hop = xmlAutomataNewState(ctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +000010258
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010259 subtypes = type->subtypes;
10260 while (subtypes != NULL) {
10261 ctxt->state = start;
10262 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
10263 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
10264 subtypes = subtypes->next;
10265 }
10266 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
10267 counter);
10268 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
10269 counter);
10270 }
10271 if (type->minOccurs == 0) {
10272 xmlAutomataNewEpsilon(ctxt->am, start, end);
10273 }
10274 ctxt->state = end;
10275 break;
10276 }
10277 case XML_SCHEMA_TYPE_ALL:{
10278 xmlAutomataStatePtr start;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000010279 xmlSchemaElementPtr elemDecl, particle;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010280 int lax;
10281
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000010282 particle = (xmlSchemaElementPtr) type->subtypes;
10283 if (particle == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010284 break;
10285 start = ctxt->state;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000010286 while (particle != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010287 ctxt->state = start;
William M. Brack9989c7d2004-05-12 14:39:38 +000010288 /*
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000010289 * Changed to put the element declaration and
10290 * never the element decl. reference into the
10291 * automaton. This fixes bug 139897 and bug 167754.
William M. Brack9989c7d2004-05-12 14:39:38 +000010292 */
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000010293 if (particle->ref != NULL) {
10294 if (particle->refDecl == NULL) {
10295 /*
10296 * TODO: Note that we break on missing
10297 * sub-components.
10298 */
10299 break;
10300 } else
10301 elemDecl = particle->refDecl;
10302 } else
10303 elemDecl = particle;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010304 /*
10305 * NOTE: The {max occurs} of all the particles in the
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000010306 * {particles} of the group must be 0 or 1; this is
10307 * already ensured during the parse of the content of
10308 * <all>.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010309 */
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000010310 if ((particle->minOccurs == 1) &&
10311 (particle->maxOccurs == 1)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010312 xmlAutomataNewOnceTrans2(ctxt->am, ctxt->state,
10313 ctxt->state,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000010314 elemDecl->name,
10315 elemDecl->targetNamespace,
10316 1, 1, elemDecl);
10317 } else if ((particle->minOccurs == 0) &&
10318 (particle->maxOccurs == 1)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010319
10320 xmlAutomataNewCountTrans2(ctxt->am, ctxt->state,
10321 ctxt->state,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000010322 elemDecl->name,
10323 elemDecl->targetNamespace,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010324 0,
10325 1,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000010326 elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010327 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000010328 particle = (xmlSchemaElementPtr) particle->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010329 }
10330 lax = type->minOccurs == 0;
10331 ctxt->state =
10332 xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL,
10333 lax);
10334 break;
10335 }
10336 case XML_SCHEMA_TYPE_RESTRICTION:
10337 if (type->subtypes != NULL)
10338 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
10339 break;
10340 case XML_SCHEMA_TYPE_EXTENSION:
10341 if (type->baseType != NULL) {
10342 xmlSchemaTypePtr subtypes;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010343
10344 /*
10345 * TODO: Circular definitions will be checked at the
10346 * constraint level. So remove this when the complex type
10347 * constraints are implemented.
10348 */
Daniel Veillardf7627552004-04-22 07:15:40 +000010349 if (type->recurse) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010350 /* TODO: Change the error code. */
10351 xmlSchemaPCustomErr(ctxt,
10352 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
10353 NULL, type, type->node,
10354 "This item is circular", NULL);
Daniel Veillardf7627552004-04-22 07:15:40 +000010355 return;
10356 }
10357 type->recurse = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010358 xmlSchemaBuildAContentModel(type->baseType, ctxt, name);
Daniel Veillardf7627552004-04-22 07:15:40 +000010359 type->recurse = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010360 subtypes = type->subtypes;
10361 while (subtypes != NULL) {
10362 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
10363 subtypes = subtypes->next;
10364 }
10365 } else if (type->subtypes != NULL)
10366 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
10367 break;
10368 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000010369 /*
10370 * Handle model group definition references.
10371 * NOTE: type->subtypes is the referenced model grop definition;
10372 * and type->subtypes->subtypes is the model group (i.e. <all> or
10373 * <choice> or <sequence>).
10374 */
10375 if ((type->ref != NULL) && (type->subtypes != NULL) &&
10376 (type->subtypes->subtypes != NULL)) {
10377 xmlSchemaTypePtr modelGr;
10378 xmlAutomataStatePtr start, end;
10379
10380 modelGr = type->subtypes->subtypes;
10381 start = ctxt->state;
10382 end = xmlAutomataNewState(ctxt->am);
10383 if (type->maxOccurs == 1) {
10384 ctxt->state = start;
10385 xmlSchemaBuildAContentModel(modelGr, ctxt, name);
10386 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
10387 } else {
10388 int counter;
10389 xmlAutomataStatePtr hop;
10390 int maxOccurs = type->maxOccurs == UNBOUNDED ?
10391 UNBOUNDED : type->maxOccurs - 1;
10392 int minOccurs =
10393 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
10394
10395 counter =
10396 xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
10397 hop = xmlAutomataNewState(ctxt->am);
10398 ctxt->state = start;
10399 xmlSchemaBuildAContentModel(modelGr, ctxt, name);
10400 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
10401 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
10402 counter);
10403 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
10404 counter);
10405 }
10406 if (type->minOccurs == 0) {
10407 xmlAutomataNewEpsilon(ctxt->am, start, end);
10408 }
10409 ctxt->state = end;
10410 break;
10411 }
10412 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010413 case XML_SCHEMA_TYPE_COMPLEX:
10414 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
10415 if (type->subtypes != NULL)
10416 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
10417 break;
William M. Brack2f2a6632004-08-20 23:09:47 +000010418 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
10419 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010420 default:
10421 xmlGenericError(xmlGenericErrorContext,
10422 "Found unexpected type %d in %s content model\n",
10423 type->type, name);
10424 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000010425 }
10426}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010427
Daniel Veillard4255d502002-04-16 15:50:10 +000010428/**
10429 * xmlSchemaBuildContentModel:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010430 * @type: the type definition (or reference)
Daniel Veillard4255d502002-04-16 15:50:10 +000010431 * @ctxt: the schema parser context
Daniel Veillarda84c0b32003-06-02 16:58:46 +000010432 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +000010433 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010434 * Builds the content model of the complex type.
Daniel Veillard4255d502002-04-16 15:50:10 +000010435 */
10436static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010437xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010438 xmlSchemaParserCtxtPtr ctxt,
10439 const xmlChar * name)
10440{
Daniel Veillard4255d502002-04-16 15:50:10 +000010441 xmlAutomataStatePtr start;
10442
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010443 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) || (type->ref != NULL) ||
10444 (type->contentType == XML_SCHEMA_CONTENT_BASIC) ||
10445 (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
10446 (type->contModel != NULL))
10447 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +000010448
10449#ifdef DEBUG_CONTENT
10450 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010451 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000010452#endif
10453
Daniel Veillard4255d502002-04-16 15:50:10 +000010454 ctxt->am = xmlNewAutomata();
10455 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010456 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010457 "Cannot create automata for complex tpye %s\n", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010458 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000010459 }
10460 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010461 xmlSchemaBuildAContentModel(type, ctxt, name);
Daniel Veillard4255d502002-04-16 15:50:10 +000010462 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010463 type->contModel = xmlAutomataCompile(ctxt->am);
10464 if (type->contModel == NULL) {
10465 xmlSchemaPCustomErr(ctxt,
10466 XML_SCHEMAP_INTERNAL,
10467 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010468 "Failed to compile the content model", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010469 } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010470 xmlSchemaPCustomErr(ctxt,
10471 XML_SCHEMAP_NOT_DETERMINISTIC,
10472 /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010473 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010474 "The content model is not determinist", NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +000010475 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +000010476#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010477 xmlGenericError(xmlGenericErrorContext,
10478 "Content model of %s:\n", name);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010479 xmlRegexpPrint(stderr, type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +000010480#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +000010481 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +000010482 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000010483 xmlFreeAutomata(ctxt->am);
10484 ctxt->am = NULL;
10485}
10486
10487/**
10488 * xmlSchemaRefFixupCallback:
10489 * @elem: the schema element context
10490 * @ctxt: the schema parser context
10491 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000010492 * Resolves the references of an element declaration
10493 * or particle, which has an element declaration as it's
10494 * term.
Daniel Veillard4255d502002-04-16 15:50:10 +000010495 */
10496static void
10497xmlSchemaRefFixupCallback(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010498 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010499 const xmlChar * name ATTRIBUTE_UNUSED,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010500 const xmlChar * context ATTRIBUTE_UNUSED,
10501 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000010502{
Daniel Veillardc0826a72004-08-10 14:17:33 +000010503 if ((ctxt == NULL) || (elem == NULL) ||
10504 ((elem != NULL) && (elem->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010505 return;
Daniel Veillardc0826a72004-08-10 14:17:33 +000010506 elem->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
Daniel Veillard4255d502002-04-16 15:50:10 +000010507 if (elem->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010508 xmlSchemaElementPtr elemDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +000010509
Daniel Veillardc0826a72004-08-10 14:17:33 +000010510 /*
10511 * TODO: Evaluate, what errors could occur if the declaration is not
10512 * found. It might be possible that the "typefixup" might crash if
10513 * no ref declaration was found.
10514 */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010515 elemDecl = xmlSchemaGetElem(ctxt->schema, elem->ref, elem->refNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +000010516 if (elemDecl == NULL) {
10517 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010518 XML_SCHEMAP_SRC_RESOLVE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010519 NULL, (xmlSchemaTypePtr) elem, elem->node,
10520 "ref", elem->ref, elem->refNs,
10521 XML_SCHEMA_TYPE_ELEMENT, NULL);
10522 } else
10523 elem->refDecl = elemDecl;
10524 } else {
10525 if ((elem->subtypes == NULL) && (elem->namedType != NULL)) {
10526 xmlSchemaTypePtr type;
10527
10528 /* (type definition) ... otherwise the type definition ·resolved·
10529 * to by the ·actual value· of the type [attribute] ...
10530 */
10531 type = xmlSchemaGetType(ctxt->schema, elem->namedType,
10532 elem->namedTypeNs);
10533 if (type == NULL) {
10534 xmlSchemaPResCompAttrErr(ctxt,
10535 XML_SCHEMAP_SRC_RESOLVE,
10536 NULL, (xmlSchemaTypePtr) elem, elem->node,
10537 "type", elem->namedType, elem->namedTypeNs,
10538 XML_SCHEMA_TYPE_BASIC, "type definition");
10539 } else
10540 elem->subtypes = type;
10541 }
10542 if (elem->substGroup != NULL) {
10543 xmlSchemaElementPtr substHead;
10544
10545 /*
10546 * FIXME TODO: Do we need a new field in _xmlSchemaElement for
10547 * substitutionGroup?
10548 */
10549 substHead = xmlSchemaGetElem(ctxt->schema, elem->substGroup,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010550 elem->substGroupNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +000010551 if (substHead == NULL) {
10552 xmlSchemaPResCompAttrErr(ctxt,
10553 XML_SCHEMAP_SRC_RESOLVE,
10554 NULL, (xmlSchemaTypePtr) elem, NULL,
10555 "substitutionGroup", elem->substGroup, elem->substGroupNs,
10556 XML_SCHEMA_TYPE_ELEMENT, NULL);
10557 } else {
10558 xmlSchemaRefFixupCallback(substHead, ctxt, NULL, NULL, NULL);
10559 /*
10560 * (type definition)...otherwise the {type definition} of the
10561 * element declaration ·resolved· to by the ·actual value· of
10562 * the substitutionGroup [attribute], if present
10563 */
10564 if (elem->subtypes == NULL)
10565 elem->subtypes = substHead->subtypes;
10566 }
10567 }
10568 if ((elem->subtypes == NULL) && (elem->namedType == NULL) &&
10569 (elem->substGroup == NULL))
10570 elem->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
10571 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010572}
10573
William M. Bracke7091952004-05-11 15:09:58 +000010574/**
10575 * xmlSchemaParseListRefFixup:
10576 * @type: the schema type definition
10577 * @ctxt: the schema parser context
10578 *
10579 * Fixup of the itemType reference of the list type.
10580 */
Daniel Veillard377e1a92004-04-16 16:30:05 +000010581static void
William M. Bracke7091952004-05-11 15:09:58 +000010582xmlSchemaParseListRefFixup(xmlSchemaTypePtr type, xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010583{
Daniel Veillardc0826a72004-08-10 14:17:33 +000010584
Daniel Veillard01fa6152004-06-29 17:04:39 +000010585 if (((type->base == NULL) &&
10586 (type->subtypes == NULL)) ||
10587 ((type->base != NULL) &&
10588 (type->subtypes != NULL))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010589 /*
10590 * src-list-itemType-or-simpleType
10591 * Either the itemType [attribute] or the <simpleType> [child] of
10592 * the <list> element must be present, but not both.
Daniel Veillard01fa6152004-06-29 17:04:39 +000010593 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000010594 /*
10595 * TODO: Move this to the parse function.
10596 */
10597 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010598 XML_SCHEMAP_SRC_LIST_ITEMTYPE_OR_SIMPLETYPE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010599 NULL, type, type->node,
10600 "The attribute 'itemType' and the <simpleType> child "
10601 "are mutually exclusive", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010602 } else if (type->base!= NULL) {
10603 type->subtypes = xmlSchemaGetType(ctxt->schema, type->base, type->baseNs);
10604 if (type->subtypes == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010605 xmlSchemaPResCompAttrErr(ctxt,
10606 XML_SCHEMAP_SRC_RESOLVE,
10607 NULL, type, type->node,
10608 "itemType", type->base, type->baseNs,
10609 XML_SCHEMA_TYPE_SIMPLE, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010610 }
10611 }
10612 if ((type->subtypes != NULL) &&
10613 (type->subtypes->contentType == XML_SCHEMA_CONTENT_UNKNOWN))
10614 xmlSchemaTypeFixup(type->subtypes, ctxt, NULL);
William M. Bracke7091952004-05-11 15:09:58 +000010615}
10616
10617/**
10618 * xmlSchemaParseUnionRefCheck:
10619 * @typeDecl: the schema type definition
10620 * @ctxt: the schema parser context
10621 *
Daniel Veillard01fa6152004-06-29 17:04:39 +000010622 * Checks and builds the memberTypes of the union type.
10623 * Returns -1 in case of an internal error, 0 otherwise.
William M. Bracke7091952004-05-11 15:09:58 +000010624 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010625static int
William M. Bracke7091952004-05-11 15:09:58 +000010626xmlSchemaParseUnionRefCheck(xmlSchemaTypePtr type,
Daniel Veillard377e1a92004-04-16 16:30:05 +000010627 xmlSchemaParserCtxtPtr ctxt)
10628{
Daniel Veillardc0826a72004-08-10 14:17:33 +000010629
Daniel Veillard01fa6152004-06-29 17:04:39 +000010630 xmlSchemaTypeLinkPtr link, lastLink = NULL, prevLink, subLink, newLink;
10631 xmlSchemaTypePtr memberType, ctxtType;
Daniel Veillard377e1a92004-04-16 16:30:05 +000010632
Daniel Veillard01fa6152004-06-29 17:04:39 +000010633 /* 1 If the <union> alternative is chosen, then [Definition:]
10634 * define the explicit members as the type definitions ·resolved·
10635 * to by the items in the ·actual value· of the memberTypes [attribute],
10636 * if any, followed by the type definitions corresponding to the
10637 * <simpleType>s among the [children] of <union>, if any.
10638 */
Daniel Veillard377e1a92004-04-16 16:30:05 +000010639
Daniel Veillard01fa6152004-06-29 17:04:39 +000010640 if (type->type != XML_SCHEMA_TYPE_UNION)
10641 return (-1);
10642 if (ctxt->ctxtType == NULL) {
10643 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010644 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010645 "Internal error: xmlSchemaParseUnionRefCheck, no parent type "
10646 "available", NULL, NULL);
10647 return (-1);
10648 }
10649 /*
10650 * src-union-memberTypes-or-simpleTypes
10651 * Either the memberTypes [attribute] of the <union> element must
10652 * be non-empty or there must be at least one simpleType [child].
10653 */
10654 if ((type->base == NULL) &&
10655 (type->subtypes == NULL)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010656 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010657 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010658 NULL, NULL, type->node,
10659 "Either the attribute 'memberTypes' must be non-empty "
10660 "or there must be at least one <simpleType> child", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010661 }
10662
10663 ctxtType = ctxt->ctxtType;
10664 if (type->base != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010665 xmlAttrPtr attr;
10666 const xmlChar *cur, *end;
10667 xmlChar *tmp;
10668 const xmlChar *localName, *uri;
10669
10670 attr = xmlSchemaGetPropNode(type->node, "memberTypes");
Daniel Veillard01fa6152004-06-29 17:04:39 +000010671 cur = type->base;
10672 do {
10673 while (IS_BLANK_CH(*cur))
10674 cur++;
10675 end = cur;
10676 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
10677 end++;
10678 if (end == cur)
10679 break;
10680 tmp = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +000010681 xmlSchemaPValAttrNodeQNameValue(ctxt, ctxt->schema, NULL,
10682 NULL, attr, BAD_CAST tmp, &uri, NULL, &localName);
10683 memberType = xmlSchemaGetType(ctxt->schema, localName, uri);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010684 if (memberType == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010685 xmlSchemaPResCompAttrErr(ctxt,
10686 XML_SCHEMAP_UNKNOWN_MEMBER_TYPE,
10687 NULL, NULL, type->node, "memberTypes", localName, uri,
10688 XML_SCHEMA_TYPE_SIMPLE, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010689 } else {
10690 if (memberType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
10691 xmlSchemaTypeFixup(memberType, ctxt, NULL);
10692 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
10693 if (link == NULL) {
10694 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
10695 return (-1);
10696 }
10697 link->type = memberType;
10698 link->next = NULL;
10699 if (lastLink == NULL)
10700 ctxtType->memberTypes = link;
10701 else
10702 lastLink->next = link;
10703 lastLink = link;
10704 }
10705 xmlFree(tmp);
10706 cur = end;
10707 } while (*cur != 0);
10708 }
10709 /*
10710 * Add local simple types,
10711 */
10712 memberType = type->subtypes;
10713 while (memberType != NULL) {
10714 if (memberType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
10715 xmlSchemaTypeFixup(memberType, ctxt, NULL);
10716 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
10717 if (link == NULL) {
10718 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
10719 return (-1);
10720 }
10721 link->type = memberType;
10722 link->next = NULL;
10723 if (lastLink == NULL)
10724 ctxtType->memberTypes = link;
10725 else
10726 lastLink->next = link;
10727 lastLink = link;
10728 memberType = memberType->next;
10729 }
10730 /*
10731 * The actual value is then formed by replacing any union type
10732 * definition in the ·explicit members· with the members of their
10733 * {member type definitions}, in order.
10734 */
10735 link = ctxtType->memberTypes;
10736 while (link != NULL) {
10737 if (link->type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
10738 subLink = link->type->memberTypes;
10739 if (subLink != NULL) {
10740 link->type = subLink->type;
10741 if (subLink->next != NULL) {
10742 lastLink = link->next;
10743 subLink = subLink->next;
10744 prevLink = link;
10745 while (subLink != NULL) {
10746 newLink = (xmlSchemaTypeLinkPtr)
10747 xmlMalloc(sizeof(xmlSchemaTypeLink));
10748 if (newLink == NULL) {
10749 xmlSchemaPErrMemory(ctxt, "allocating a type link",
10750 NULL);
10751 return (-1);
10752 }
10753 newLink->type = memberType;
10754 prevLink->next = newLink;
10755 prevLink = newLink;
10756 newLink->next = lastLink;
10757
10758 subLink = subLink->next;
10759 }
10760 }
10761 }
10762 }
10763 link = link->next;
10764 }
10765
10766 return (0);
Daniel Veillard377e1a92004-04-16 16:30:05 +000010767}
10768
Daniel Veillard4255d502002-04-16 15:50:10 +000010769/**
Daniel Veillard3646d642004-06-02 19:19:14 +000010770 * xmlSchemaIsDerivedFromBuiltInType:
10771 * @ctxt: the schema parser context
10772 * @type: the type definition
10773 * @valType: the value type
10774 *
10775 *
10776 * Returns 1 if the type has the given value type, or
10777 * is derived from such a type.
10778 */
William M. Brack803812b2004-06-03 02:11:24 +000010779static int
Daniel Veillard3646d642004-06-02 19:19:14 +000010780xmlSchemaIsDerivedFromBuiltInType(xmlSchemaParserCtxtPtr ctxt,
10781 xmlSchemaTypePtr type, int valType)
10782{
10783 /* TODO: Check if this works in every case. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010784 if ((type->type == XML_SCHEMA_TYPE_BASIC) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000010785 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000010786 if (type->builtInType == valType)
Daniel Veillard3646d642004-06-02 19:19:14 +000010787 return(1);
10788 } else if (type->type == XML_SCHEMA_TYPE_ATTRIBUTE) {
10789 if (((xmlSchemaAttributePtr) type)->subtypes != NULL)
10790 return(xmlSchemaIsDerivedFromBuiltInType(ctxt,
10791 ((xmlSchemaAttributePtr) type)->subtypes, valType));
10792 } else if ((type->type == XML_SCHEMA_TYPE_RESTRICTION) ||
10793 (type->type == XML_SCHEMA_TYPE_EXTENSION)) {
10794 if (type->baseType != NULL)
10795 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->baseType,
10796 valType));
10797 } else if ((type->subtypes != NULL) &&
10798 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX) ||
10799 (type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
10800 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE) ||
10801 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
10802 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->subtypes,
10803 valType));
10804 }
10805
10806 return (0);
10807}
10808
10809/**
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000010810 * xmlSchemaGetPrimitiveType:
Daniel Veillard01fa6152004-06-29 17:04:39 +000010811 * @type: the simpleType definition
10812 *
10813 * Returns the primitive type of the given type or
10814 * NULL in case of error.
10815 */
10816static xmlSchemaTypePtr
10817xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
10818{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000010819
Daniel Veillard01fa6152004-06-29 17:04:39 +000010820 while (type != NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000010821 /*
10822 * Note that anySimpleType is actually not a primitive type
10823 * but we need that here.
10824 */
10825 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
10826 (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
Daniel Veillard01fa6152004-06-29 17:04:39 +000010827 return (type);
10828 type = type->baseType;
10829 }
10830
10831 return (NULL);
10832}
10833
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000010834#if 0
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000010835/**
10836 * xmlSchemaGetBuiltInTypeAncestor:
10837 * @type: the simpleType definition
10838 *
10839 * Returns the primitive type of the given type or
10840 * NULL in case of error.
10841 */
10842static xmlSchemaTypePtr
10843xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
10844{
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000010845 if ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
10846 (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION))
10847 return (0);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000010848 while (type != NULL) {
10849 if (type->type == XML_SCHEMA_TYPE_BASIC)
10850 return (type);
10851 type = type->baseType;
10852 }
10853
10854 return (NULL);
10855}
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000010856#endif
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000010857
Daniel Veillard01fa6152004-06-29 17:04:39 +000010858/**
Daniel Veillard3646d642004-06-02 19:19:14 +000010859 * xmlSchemaBuildAttributeUsesOwned:
10860 * @ctxt: the schema parser context
10861 * @type: the complex type definition
10862 * @cur: the attribute declaration list
10863 * @lastUse: the top of the attribute use list
10864 *
10865 * Builds the attribute uses list on the given complex type.
10866 * This one is supposed to be called by
10867 * xmlSchemaBuildAttributeValidation only.
10868 */
10869static int
10870xmlSchemaBuildAttributeUsesOwned(xmlSchemaParserCtxtPtr ctxt,
10871 xmlSchemaAttributePtr cur,
10872 xmlSchemaAttributeLinkPtr *uses,
10873 xmlSchemaAttributeLinkPtr *lastUse)
10874{
10875 xmlSchemaAttributeLinkPtr tmp;
10876 while (cur != NULL) {
10877 if (cur->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
10878 /*
10879 * W3C: "2 The {attribute uses} of the attribute groups ·resolved·
10880 * to by the ·actual value·s of the ref [attribute] of the
10881 * <attributeGroup> [children], if any."
10882 */
10883 if (xmlSchemaBuildAttributeUsesOwned(ctxt,
10884 ((xmlSchemaAttributeGroupPtr) cur)->attributes, uses,
10885 lastUse) == -1) {
10886 return (-1);
10887 }
10888 } else {
10889 /* W3C: "1 The set of attribute uses corresponding to the
10890 * <attribute> [children], if any."
10891 */
10892 tmp = (xmlSchemaAttributeLinkPtr)
10893 xmlMalloc(sizeof(xmlSchemaAttributeLink));
10894 if (tmp == NULL) {
10895 xmlSchemaPErrMemory(ctxt, "building attribute uses", NULL);
10896 return (-1);
10897 }
10898 tmp->attr = cur;
10899 tmp->next = NULL;
10900 if (*uses == NULL)
10901 *uses = tmp;
10902 else
10903 (*lastUse)->next = tmp;
10904 *lastUse = tmp;
10905 }
10906 cur = cur->next;
10907 }
10908 return (0);
10909}
10910
Daniel Veillard50355f02004-06-08 17:52:16 +000010911/**
10912 * xmlSchemaCloneWildcardNsConstraints:
10913 * @ctxt: the schema parser context
10914 * @dest: the destination wildcard
10915 * @source: the source wildcard
10916 *
10917 * Clones the namespace constraints of source
10918 * and assignes them to dest.
10919 * Returns -1 on internal error, 0 otherwise.
10920 */
Daniel Veillard3646d642004-06-02 19:19:14 +000010921static int
10922xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
10923 xmlSchemaWildcardPtr *dest,
10924 xmlSchemaWildcardPtr source)
10925{
10926 xmlSchemaWildcardNsPtr cur, tmp, last;
10927
10928 if ((source == NULL) || (*dest == NULL))
10929 return(-1);
10930 (*dest)->any = source->any;
10931 cur = source->nsSet;
10932 last = NULL;
10933 while (cur != NULL) {
10934 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
10935 if (tmp == NULL)
10936 return(-1);
10937 tmp->value = cur->value;
10938 if (last == NULL)
10939 (*dest)->nsSet = tmp;
10940 else
10941 last->next = tmp;
10942 last = tmp;
10943 cur = cur->next;
10944 }
10945 if ((*dest)->negNsSet != NULL)
10946 xmlSchemaFreeWildcardNsSet((*dest)->negNsSet);
10947 if (source->negNsSet != NULL) {
10948 (*dest)->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
10949 if ((*dest)->negNsSet == NULL)
10950 return(-1);
10951 (*dest)->negNsSet->value = source->negNsSet->value;
10952 } else
10953 (*dest)->negNsSet = NULL;
10954 return(0);
10955}
10956
Daniel Veillard50355f02004-06-08 17:52:16 +000010957/**
10958 * xmlSchemaUnionWildcards:
10959 * @ctxt: the schema parser context
10960 * @completeWild: the first wildcard
10961 * @curWild: the second wildcard
10962 *
10963 * Unions the namespace constraints of the given wildcards.
10964 * @completeWild will hold the resulting union.
10965 * Returns a positive error code on failure, -1 in case of an
10966 * internal error, 0 otherwise.
10967 */
Daniel Veillard3646d642004-06-02 19:19:14 +000010968static int
10969xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
10970 xmlSchemaWildcardPtr completeWild,
10971 xmlSchemaWildcardPtr curWild)
10972{
10973 xmlSchemaWildcardNsPtr cur, curB, tmp;
10974
10975 /*
10976 * 1 If O1 and O2 are the same value, then that value must be the
10977 * value.
10978 */
10979 if ((completeWild->any == curWild->any) &&
10980 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
10981 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
10982
10983 if ((completeWild->negNsSet == NULL) ||
10984 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
10985
10986 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000010987 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000010988
10989 /*
10990 * Check equality of sets.
10991 */
10992 cur = completeWild->nsSet;
10993 while (cur != NULL) {
10994 found = 0;
10995 curB = curWild->nsSet;
10996 while (curB != NULL) {
10997 if (cur->value == curB->value) {
10998 found = 1;
10999 break;
11000 }
11001 curB = curB->next;
11002 }
11003 if (!found)
11004 break;
11005 cur = cur->next;
11006 }
11007 if (found)
11008 return(0);
11009 } else
11010 return(0);
11011 }
11012 }
11013 /*
11014 * 2 If either O1 or O2 is any, then any must be the value
11015 */
Daniel Veillard50355f02004-06-08 17:52:16 +000011016 if (completeWild->any != curWild->any) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011017 if (completeWild->any == 0) {
11018 completeWild->any = 1;
11019 if (completeWild->nsSet != NULL) {
11020 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11021 completeWild->nsSet = NULL;
11022 }
11023 if (completeWild->negNsSet != NULL) {
11024 xmlFree(completeWild->negNsSet);
11025 completeWild->negNsSet = NULL;
11026 }
11027 }
Daniel Veillard50355f02004-06-08 17:52:16 +000011028 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000011029 }
11030 /*
11031 * 3 If both O1 and O2 are sets of (namespace names or ·absent·),
11032 * then the union of those sets must be the value.
11033 */
11034 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
11035 int found;
11036 xmlSchemaWildcardNsPtr start;
11037
11038 cur = curWild->nsSet;
11039 start = completeWild->nsSet;
11040 while (cur != NULL) {
11041 found = 0;
11042 curB = start;
11043 while (curB != NULL) {
11044 if (cur->value == curB->value) {
11045 found = 1;
11046 break;
11047 }
11048 curB = curB->next;
11049 }
11050 if (!found) {
11051 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
11052 if (tmp == NULL)
11053 return (-1);
11054 tmp->value = cur->value;
11055 tmp->next = completeWild->nsSet;
11056 completeWild->nsSet = tmp;
11057 }
11058 cur = cur->next;
11059 }
11060
11061 return(0);
11062 }
11063 /*
11064 * 4 If the two are negations of different values (namespace names
11065 * or ·absent·), then a pair of not and ·absent· must be the value.
11066 */
11067 if ((completeWild->negNsSet != NULL) &&
11068 (curWild->negNsSet != NULL) &&
11069 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
11070 completeWild->negNsSet->value = NULL;
Daniel Veillard50355f02004-06-08 17:52:16 +000011071
11072 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +000011073 }
11074 /*
11075 * 5.
11076 */
11077 if (((completeWild->negNsSet != NULL) &&
11078 (completeWild->negNsSet->value != NULL) &&
11079 (curWild->nsSet != NULL)) ||
11080 ((curWild->negNsSet != NULL) &&
11081 (curWild->negNsSet->value != NULL) &&
11082 (completeWild->nsSet != NULL))) {
11083
11084 int nsFound, absentFound = 0;
11085
11086 if (completeWild->nsSet != NULL) {
11087 cur = completeWild->nsSet;
11088 curB = curWild->negNsSet;
11089 } else {
11090 cur = curWild->nsSet;
11091 curB = completeWild->negNsSet;
11092 }
11093 nsFound = 0;
11094 while (cur != NULL) {
11095 if (cur->value == NULL)
11096 absentFound = 1;
11097 else if (cur->value == curB->value)
11098 nsFound = 1;
11099 if (nsFound && absentFound)
11100 break;
11101 cur = cur->next;
11102 }
11103
11104 if (nsFound && absentFound) {
11105 /*
11106 * 5.1 If the set S includes both the negated namespace
11107 * name and ·absent·, then any must be the value.
11108 */
11109 completeWild->any = 1;
11110 if (completeWild->nsSet != NULL) {
11111 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11112 completeWild->nsSet = NULL;
11113 }
11114 if (completeWild->negNsSet != NULL) {
11115 xmlFree(completeWild->negNsSet);
11116 completeWild->negNsSet = NULL;
11117 }
11118 } else if (nsFound && (!absentFound)) {
11119 /*
11120 * 5.2 If the set S includes the negated namespace name
11121 * but not ·absent·, then a pair of not and ·absent· must
11122 * be the value.
11123 */
11124 if (completeWild->nsSet != NULL) {
11125 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11126 completeWild->nsSet = NULL;
11127 }
11128 if (completeWild->negNsSet == NULL) {
11129 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
11130 if (completeWild->negNsSet == NULL)
11131 return (-1);
11132 }
11133 completeWild->negNsSet->value = NULL;
11134 } else if ((!nsFound) && absentFound) {
11135 /*
11136 * 5.3 If the set S includes ·absent· but not the negated
11137 * namespace name, then the union is not expressible.
11138 */
11139 xmlSchemaPErr(ctxt, completeWild->node,
11140 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011141 "The union of the wilcard is not expressible.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +000011142 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000011143 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +000011144 } else if ((!nsFound) && (!absentFound)) {
11145 /*
11146 * 5.4 If the set S does not include either the negated namespace
11147 * name or ·absent·, then whichever of O1 or O2 is a pair of not
11148 * and a namespace name must be the value.
11149 */
11150 if (completeWild->negNsSet == NULL) {
11151 if (completeWild->nsSet != NULL) {
11152 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11153 completeWild->nsSet = NULL;
11154 }
11155 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
11156 if (completeWild->negNsSet == NULL)
11157 return (-1);
11158 completeWild->negNsSet->value = curWild->negNsSet->value;
11159 }
11160 }
11161 return (0);
11162 }
11163 /*
11164 * 6.
11165 */
11166 if (((completeWild->negNsSet != NULL) &&
11167 (completeWild->negNsSet->value == NULL) &&
11168 (curWild->nsSet != NULL)) ||
11169 ((curWild->negNsSet != NULL) &&
11170 (curWild->negNsSet->value == NULL) &&
11171 (completeWild->nsSet != NULL))) {
11172
11173 if (completeWild->nsSet != NULL) {
11174 cur = completeWild->nsSet;
11175 } else {
11176 cur = curWild->nsSet;
11177 }
11178 while (cur != NULL) {
11179 if (cur->value == NULL) {
11180 /*
11181 * 6.1 If the set S includes ·absent·, then any must be the
11182 * value.
11183 */
11184 completeWild->any = 1;
11185 if (completeWild->nsSet != NULL) {
11186 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11187 completeWild->nsSet = NULL;
11188 }
11189 if (completeWild->negNsSet != NULL) {
11190 xmlFree(completeWild->negNsSet);
11191 completeWild->negNsSet = NULL;
11192 }
11193 return (0);
11194 }
11195 cur = cur->next;
11196 }
11197 if (completeWild->negNsSet == NULL) {
11198 /*
11199 * 6.2 If the set S does not include ·absent·, then a pair of not
11200 * and ·absent· must be the value.
11201 */
11202 if (completeWild->nsSet != NULL) {
11203 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11204 completeWild->nsSet = NULL;
11205 }
11206 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
11207 if (completeWild->negNsSet == NULL)
11208 return (-1);
11209 completeWild->negNsSet->value = NULL;
11210 }
11211 return (0);
11212 }
11213 return (0);
11214
11215}
11216
Daniel Veillard50355f02004-06-08 17:52:16 +000011217/**
11218 * xmlSchemaIntersectWildcards:
11219 * @ctxt: the schema parser context
11220 * @completeWild: the first wildcard
11221 * @curWild: the second wildcard
11222 *
11223 * Intersects the namespace constraints of the given wildcards.
11224 * @completeWild will hold the resulting intersection.
11225 * Returns a positive error code on failure, -1 in case of an
11226 * internal error, 0 otherwise.
11227 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011228static int
11229xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
11230 xmlSchemaWildcardPtr completeWild,
11231 xmlSchemaWildcardPtr curWild)
11232{
William M. Brack803812b2004-06-03 02:11:24 +000011233 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000011234
11235 /*
11236 * 1 If O1 and O2 are the same value, then that value must be the
11237 * value.
11238 */
11239 if ((completeWild->any == curWild->any) &&
11240 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
11241 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
11242
11243 if ((completeWild->negNsSet == NULL) ||
11244 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
11245
11246 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000011247 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000011248
11249 /*
11250 * Check equality of sets.
11251 */
11252 cur = completeWild->nsSet;
11253 while (cur != NULL) {
11254 found = 0;
11255 curB = curWild->nsSet;
11256 while (curB != NULL) {
11257 if (cur->value == curB->value) {
11258 found = 1;
11259 break;
11260 }
11261 curB = curB->next;
11262 }
11263 if (!found)
11264 break;
11265 cur = cur->next;
11266 }
11267 if (found)
11268 return(0);
11269 } else
11270 return(0);
11271 }
11272 }
11273 /*
11274 * 2 If either O1 or O2 is any, then the other must be the value.
11275 */
11276 if ((completeWild->any != curWild->any) && (completeWild->any)) {
11277 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
11278 return(-1);
11279 return(0);
11280 }
11281 /*
11282 * 3 If either O1 or O2 is a pair of not and a value (a namespace
11283 * name or ·absent·) and the other is a set of (namespace names or
11284 * ·absent·), then that set, minus the negated value if it was in
11285 * the set, minus ·absent· if it was in the set, must be the value.
11286 */
11287 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
11288 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
11289 const xmlChar *neg;
11290
11291 if (completeWild->nsSet == NULL) {
11292 neg = completeWild->negNsSet->value;
11293 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
11294 return(-1);
11295 } else
11296 neg = curWild->negNsSet->value;
11297 /*
11298 * Remove absent and negated.
11299 */
11300 prev = NULL;
11301 cur = completeWild->nsSet;
11302 while (cur != NULL) {
11303 if (cur->value == NULL) {
11304 if (prev == NULL)
11305 completeWild->nsSet = cur->next;
11306 else
11307 prev->next = cur->next;
11308 xmlFree(cur);
11309 break;
11310 }
11311 prev = cur;
11312 cur = cur->next;
11313 }
11314 if (neg != NULL) {
11315 prev = NULL;
11316 cur = completeWild->nsSet;
11317 while (cur != NULL) {
11318 if (cur->value == neg) {
11319 if (prev == NULL)
11320 completeWild->nsSet = cur->next;
11321 else
11322 prev->next = cur->next;
11323 xmlFree(cur);
11324 break;
11325 }
11326 prev = cur;
11327 cur = cur->next;
11328 }
11329 }
11330
11331 return(0);
11332 }
11333 /*
11334 * 4 If both O1 and O2 are sets of (namespace names or ·absent·),
11335 * then the intersection of those sets must be the value.
11336 */
11337 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
11338 int found;
11339
11340 cur = completeWild->nsSet;
11341 prev = NULL;
11342 while (cur != NULL) {
11343 found = 0;
11344 curB = curWild->nsSet;
11345 while (curB != NULL) {
11346 if (cur->value == curB->value) {
11347 found = 1;
11348 break;
11349 }
11350 curB = curB->next;
11351 }
11352 if (!found) {
11353 if (prev == NULL)
11354 completeWild->nsSet = cur->next;
11355 else
11356 prev->next = cur->next;
11357 tmp = cur->next;
11358 xmlFree(cur);
11359 cur = tmp;
11360 continue;
11361 }
11362 prev = cur;
11363 cur = cur->next;
11364 }
11365
11366 return(0);
11367 }
11368 /* 5 If the two are negations of different namespace names,
11369 * then the intersection is not expressible
11370 */
11371 if ((completeWild->negNsSet != NULL) &&
11372 (curWild->negNsSet != NULL) &&
11373 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
11374 (completeWild->negNsSet->value != NULL) &&
11375 (curWild->negNsSet->value != NULL)) {
11376
11377 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011378 "The intersection of the wilcard is not expressible.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +000011379 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000011380 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +000011381 }
11382 /*
11383 * 6 If the one is a negation of a namespace name and the other
11384 * is a negation of ·absent·, then the one which is the negation
11385 * of a namespace name must be the value.
11386 */
11387 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
11388 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
11389 (completeWild->negNsSet->value == NULL)) {
11390 completeWild->negNsSet->value = curWild->negNsSet->value;
11391 }
11392 return(0);
11393}
11394
Daniel Veillard50355f02004-06-08 17:52:16 +000011395/**
11396 * xmlSchemaIsWildcardNsConstraintSubset:
11397 * @ctxt: the schema parser context
11398 * @wildA: the first wildcard
11399 * @wildB: the second wildcard
11400 *
11401 * Returns 1 if the namespace constraint of @wildA is an intensional
11402 * subset of @wildB, 0 otherwise.
11403 */
11404static int
Daniel Veillardc0826a72004-08-10 14:17:33 +000011405xmlSchemaIsWildcardNsConstraintSubset(xmlSchemaWildcardPtr wildA,
11406 xmlSchemaWildcardPtr wildB)
Daniel Veillard50355f02004-06-08 17:52:16 +000011407{
Daniel Veillard3646d642004-06-02 19:19:14 +000011408
Daniel Veillard50355f02004-06-08 17:52:16 +000011409 /*
11410 * Schema Component Constraint: Wildcard Subset
11411 */
11412 /*
11413 * 1 super must be any.
11414 */
11415 if (wildB->any)
11416 return (1);
11417 /*
11418 * 2.1 sub must be a pair of not and a namespace name or ·absent·.
11419 * 2.2 super must be a pair of not and the same value.
11420 */
11421 if ((wildA->negNsSet != NULL) &&
11422 (wildB->negNsSet != NULL) &&
11423 (wildA->negNsSet->value == wildA->negNsSet->value))
11424 return (1);
11425 /*
11426 * 3.1 sub must be a set whose members are either namespace names or ·absent·.
11427 */
11428 if (wildA->nsSet != NULL) {
11429 /*
11430 * 3.2.1 super must be the same set or a superset thereof.
11431 */
11432 if (wildB->nsSet != NULL) {
11433 xmlSchemaWildcardNsPtr cur, curB;
11434 int found = 0;
11435
11436 cur = wildA->nsSet;
11437 while (cur != NULL) {
11438 found = 0;
11439 curB = wildB->nsSet;
11440 while (curB != NULL) {
11441 if (cur->value == curB->value) {
11442 found = 1;
11443 break;
11444 }
11445 curB = curB->next;
11446 }
11447 if (!found)
11448 return (0);
11449 cur = cur->next;
11450 }
11451 if (found)
11452 return (1);
11453 } else if (wildB->negNsSet != NULL) {
11454 xmlSchemaWildcardNsPtr cur;
11455 /*
11456 * 3.2.2 super must be a pair of not and a namespace name or
11457 * ·absent· and that value must not be in sub's set.
11458 */
11459 cur = wildA->nsSet;
11460 while (cur != NULL) {
11461 if (cur->value == wildB->negNsSet->value)
11462 return (0);
11463 cur = cur->next;
11464 }
11465 return (1);
11466 }
11467 }
11468 return (0);
11469}
11470
11471/**
11472 * xmlSchemaBuildCompleteAttributeWildcard:
11473 * @ctxt: the schema parser context
11474 * @attrs: the attribute list
11475 * @completeWild: the resulting complete wildcard
11476 *
11477 * Returns -1 in case of an internal error, 0 otherwise.
11478 */
11479static int
11480xmlSchemaBuildCompleteAttributeWildcard(xmlSchemaParserCtxtPtr ctxt,
11481 xmlSchemaAttributePtr attrs,
11482 xmlSchemaWildcardPtr *completeWild)
Daniel Veillard3646d642004-06-02 19:19:14 +000011483{
11484 while (attrs != NULL) {
11485 if (attrs->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
11486 xmlSchemaAttributeGroupPtr group;
11487
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011488 group = (xmlSchemaAttributeGroupPtr) attrs;
11489 /*
11490 * Handle attribute group references.
11491 */
11492 if (group->ref != NULL) {
11493 if (group->refItem == NULL) {
11494 /*
11495 * TODO: Should we raise a warning here?
11496 */
11497 /*
11498 * The referenced attribute group definition could not
11499 * be resolved beforehand, so skip.
11500 */
11501 attrs = attrs->next;
11502 continue;
11503 } else
11504 group = group->refItem;
11505 }
11506 /*
11507 * For every attribute group definition, an intersected wildcard
11508 * will be created (assumed that a wildcard exists on the
11509 * particular attr. gr. def. or on any contained attr. gr. def
11510 * at all).
11511 * The flag XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED ensures
11512 * that the intersection will be performed only once.
11513 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011514 if ((group->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
11515 if (group->attributes != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000011516 if (xmlSchemaBuildCompleteAttributeWildcard(ctxt,
11517 group->attributes, &group->attributeWildcard) == -1)
11518 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000011519 }
11520 group->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
11521 }
11522 if (group->attributeWildcard != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000011523 if (*completeWild == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011524 /*
11525 * Copy the first encountered wildcard as context, except for the annotation.
11526 */
Daniel Veillard50355f02004-06-08 17:52:16 +000011527 *completeWild = xmlSchemaAddWildcard(ctxt);
11528 (*completeWild)->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
11529 if (xmlSchemaCloneWildcardNsConstraints(ctxt,
11530 completeWild, group->attributeWildcard) == -1)
11531 return (-1);
11532 (*completeWild)->processContents = group->attributeWildcard->processContents;
Daniel Veillard3646d642004-06-02 19:19:14 +000011533 /*
11534 * Although the complete wildcard might not correspond to any
11535 * node in the schema, we will save this context node.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011536 * TODO: Hmm, is this sane?
Daniel Veillard3646d642004-06-02 19:19:14 +000011537 */
Daniel Veillard50355f02004-06-08 17:52:16 +000011538 (*completeWild)->node = group->attributeWildcard->node;
11539
11540 } else if (xmlSchemaIntersectWildcards(ctxt, *completeWild, group->attributeWildcard) == -1) {
11541 xmlSchemaFreeWildcard(*completeWild);
11542 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000011543 }
11544 }
11545 }
11546 attrs = attrs->next;
11547 }
11548
Daniel Veillard50355f02004-06-08 17:52:16 +000011549 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000011550}
11551
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011552static int
11553xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributePtr item,
11554 int *fixed,
11555 const xmlChar **value,
11556 xmlSchemaValPtr *val)
11557{
11558 *fixed = 0;
11559 *value = NULL;
11560 if (val != 0)
11561 *val = NULL;
11562
11563 if (item->defValue == NULL)
11564 item = item->refDecl;
11565
11566 if (item == NULL)
11567 return (0);
11568
11569 if (item->defValue != NULL) {
11570 *value = item->defValue;
11571 if (val != 0)
11572 *val = item->defVal;
11573 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
11574 *fixed = 1;
11575 return (1);
11576 }
11577 return (0);
11578}
Daniel Veillard3646d642004-06-02 19:19:14 +000011579/**
11580 * xmlSchemaMatchesWildcardNs:
11581 * @wild: the wildcard
11582 * @ns: the namespace
11583 *
11584 *
11585 * Returns 1 if the given namespace matches the wildcard,
11586 * 0 otherwise.
11587 */
11588static int
11589xmlSchemaMatchesWildcardNs(xmlSchemaWildcardPtr wild, const xmlChar* ns)
11590{
11591 if (wild == NULL)
11592 return(0);
11593
11594 if (wild->any)
11595 return(1);
11596 else if (wild->nsSet != NULL) {
11597 xmlSchemaWildcardNsPtr cur;
11598
11599 cur = wild->nsSet;
11600 while (cur != NULL) {
11601 if (xmlStrEqual(cur->value, ns))
11602 return(1);
11603 cur = cur->next;
11604 }
11605 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
11606 (!xmlStrEqual(wild->negNsSet->value, ns)))
11607 return(1);
11608
11609 return(0);
11610}
11611
11612/**
11613 * xmlSchemaBuildAttributeValidation:
11614 * @ctxt: the schema parser context
11615 * @type: the complex type definition
11616 *
11617 *
11618 * Builds the wildcard and the attribute uses on the given complex type.
11619 * Returns -1 if an internal error occurs, 0 otherwise.
11620 */
11621static int
11622xmlSchemaBuildAttributeValidation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaTypePtr type)
11623{
11624 xmlSchemaTypePtr baseType = NULL;
11625 xmlSchemaAttributeLinkPtr cur, base, tmp, id = NULL, prev = NULL, uses = NULL,
William M. Brack803812b2004-06-03 02:11:24 +000011626 lastUse = NULL, lastBaseUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000011627 xmlSchemaAttributePtr attrs;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011628 xmlSchemaTypePtr anyType;
Daniel Veillard50355f02004-06-08 17:52:16 +000011629 int baseIsAnyType = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011630 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000011631 int err = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000011632
Daniel Veillard01fa6152004-06-29 17:04:39 +000011633 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Daniel Veillard3646d642004-06-02 19:19:14 +000011634 /*
11635 * Complex Type Definition with complex content Schema Component.
11636 *
11637 * Attribute uses.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011638 * TODO: Add checks for absent referenced attribute declarations and
11639 * simple types.
Daniel Veillard3646d642004-06-02 19:19:14 +000011640 */
11641 if (type->attributeUses != NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011642 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011643 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillard3646d642004-06-02 19:19:14 +000011644 "attribute uses already builded.\n",
11645 NULL, NULL);
11646 return (-1);
11647 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011648 if (type->baseType == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011649 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011650 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011651 "complex type '%s' has no base type.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011652 type->name, NULL);
11653 return (-1);
11654 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011655 baseType = type->baseType;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011656 if (baseType == anyType)
11657 baseIsAnyType = 1;
11658 /*
11659 * Inherit the attribute uses of the base type.
11660 */
11661 /*
11662 * NOTE: It is allowed to "extend" the anyType complex type.
11663 */
11664 if (!baseIsAnyType) {
11665 if (baseType != NULL) {
11666 for (cur = baseType->attributeUses; cur != NULL; cur = cur->next) {
11667 tmp = (xmlSchemaAttributeLinkPtr)
11668 xmlMalloc(sizeof(xmlSchemaAttributeLink));
11669 if (tmp == NULL) {
11670 xmlSchemaPErrMemory(ctxt,
11671 "building attribute uses of complexType", NULL);
11672 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000011673 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011674 tmp->attr = cur->attr;
11675 tmp->next = NULL;
11676 if (type->attributeUses == NULL) {
11677 type->attributeUses = tmp;
11678 } else
11679 lastBaseUse->next = tmp;
11680 lastBaseUse = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000011681 }
11682 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011683 }
11684 if ((type->subtypes != NULL) &&
11685 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
11686 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011687 /*
11688 * type --> (<simpleContent>|<complexContent>)
11689 * --> (<restriction>|<extension>) --> attributes
11690 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011691 attrs = type->subtypes->subtypes->attributes;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011692 } else {
11693 /* Short hand form of the complexType. */
11694 attrs = type->attributes;
11695 }
11696 /*
11697 * Handle attribute wildcards.
11698 */
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000011699 err = xmlSchemaBuildCompleteAttributeWildcard(ctxt,
11700 attrs, &type->attributeWildcard);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011701 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011702 * NOTE: During the parse time, the wildcard is created on the complexType
11703 * directly, if encountered in a <restriction> or <extension> element.
Daniel Veillard01fa6152004-06-29 17:04:39 +000011704 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011705 if (err == -1) {
11706 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
11707 "Internal error: xmlSchemaBuildAttributeValidation: "
11708 "failed to build an intersected attribute wildcard.\n",
11709 NULL, NULL);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000011710 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011711 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011712
11713 if ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
11714 ((baseIsAnyType) ||
11715 ((baseType != NULL) &&
11716 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
11717 (baseType->attributeWildcard != NULL)))) {
11718 if (type->attributeWildcard != NULL) {
11719 /*
11720 * Union the complete wildcard with the base wildcard.
11721 */
11722 if (xmlSchemaUnionWildcards(ctxt, type->attributeWildcard,
11723 baseType->attributeWildcard) == -1)
11724 return (-1);
11725 } else {
11726 /*
11727 * Just inherit the wildcard.
11728 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011729 /*
11730 * NOTE: This is the only case where an attribute
11731 * wildcard is shared.
11732 */
11733 if (type->flags & XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD)
11734 type->flags ^= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011735 type->attributeWildcard = baseType->attributeWildcard;
Daniel Veillard50355f02004-06-08 17:52:16 +000011736 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011737 }
11738
11739 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
11740 if (type->attributeWildcard != NULL) {
11741 /*
11742 * Derivation Valid (Restriction, Complex)
11743 * 4.1 The {base type definition} must also have one.
11744 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011745 if (baseType->attributeWildcard == NULL) {
11746 xmlSchemaPCustomErr(ctxt,
11747 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
11748 NULL, type, NULL,
11749 "The type has an attribute wildcard, "
11750 "but the base type %s does not have one",
11751 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11752 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011753 return (1);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011754 } else if (xmlSchemaIsWildcardNsConstraintSubset(
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011755 type->attributeWildcard, baseType->attributeWildcard) == 0) {
11756 /* 4.2 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011757 xmlSchemaPCustomErr(ctxt,
11758 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
11759 NULL, type, NULL,
11760 "The attribute wildcard is not a valid "
11761 "subset of the wildcard in the base type %s",
11762 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11763 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011764 return (1);
11765 }
11766 /* 4.3 Unless the {base type definition} is the ·ur-type
11767 * definition·, the complex type definition's {attribute
11768 * wildcard}'s {process contents} must be identical to or
11769 * stronger than the {base type definition}'s {attribute
11770 * wildcard}'s {process contents}, where strict is stronger
11771 * than lax is stronger than skip.
11772 */
11773 if ((type->baseType != anyType) &&
11774 (type->attributeWildcard->processContents <
11775 baseType->attributeWildcard->processContents)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011776 xmlSchemaPCustomErr(ctxt,
11777 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
11778 NULL, type, NULL,
11779 "The 'process contents' of the attribute wildcard is weaker than "
11780 "the one in the base type %s",
11781 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11782 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011783 return (1);
11784 }
11785 }
11786 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
11787 /*
11788 * Derivation Valid (Extension)
11789 * At this point the type and the base have both, either
11790 * no wildcard or a wildcard.
11791 */
11792 if ((baseType->attributeWildcard != NULL) &&
11793 (baseType->attributeWildcard != type->attributeWildcard)) {
11794 /* 1.3 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011795 if (xmlSchemaIsWildcardNsConstraintSubset(
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011796 baseType->attributeWildcard, type->attributeWildcard) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011797 xmlSchemaPCustomErr(ctxt,
11798 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
11799 NULL, type, NULL,
11800 "The attribute wildcard is not a valid "
11801 "superset of the one in the base type %s",
11802 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11803 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011804 return (1);
11805 }
11806 }
11807 }
11808
Daniel Veillard3646d642004-06-02 19:19:14 +000011809 /*
11810 * Gather attribute uses defined by this type.
11811 */
11812 if (attrs != NULL) {
11813 if (xmlSchemaBuildAttributeUsesOwned(ctxt, attrs,
11814 &uses, &lastUse) == -1) {
11815 return (-1);
11816 }
11817 }
11818 /* 3.4.6 -> Complex Type Definition Properties Correct 4.
11819 * "Two distinct attribute declarations in the {attribute uses} must
11820 * not have identical {name}s and {target namespace}s."
11821 *
11822 * For "extension" this is done further down.
11823 */
11824 if ((uses != NULL) && ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
11825 cur = uses;
11826 while (cur != NULL) {
11827 tmp = cur->next;
11828 while (tmp != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011829 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
11830 xmlSchemaGetAttrName(tmp->attr))) &&
11831 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
11832 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
11833
11834 xmlSchemaPAttrUseErr(ctxt,
11835 XML_SCHEMAP_CT_PROPS_CORRECT_4,
11836 NULL, type, NULL, cur->attr,
11837 "Duplicate attribute use %s specified",
11838 xmlSchemaFormatNsUriLocal(&str,
11839 xmlSchemaGetAttrTargetNsURI(tmp->attr),
11840 xmlSchemaGetAttrName(tmp->attr))
11841 );
11842 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000011843 break;
11844 }
11845 tmp = tmp->next;
11846 }
11847 cur = cur->next;
11848 }
11849 }
11850 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
11851 /*
11852 * Derive by restriction.
11853 */
11854 if (baseIsAnyType) {
11855 type->attributeUses = uses;
11856 } else {
11857 int found;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011858 const xmlChar *bEffValue;
11859 int effFixed;
Daniel Veillard3646d642004-06-02 19:19:14 +000011860
11861 cur = uses;
11862 while (cur != NULL) {
11863 found = 0;
11864 base = type->attributeUses;
11865 while (base != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011866 if (xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
11867 xmlSchemaGetAttrName(base->attr)) &&
11868 xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
11869 xmlSchemaGetAttrTargetNsURI(base->attr))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011870
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011871 found = 1;
11872
Daniel Veillard3646d642004-06-02 19:19:14 +000011873 if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
11874 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
11875 /*
11876 * derivation-ok-restriction 2.1.1
Daniel Veillardc0826a72004-08-10 14:17:33 +000011877 */
11878 xmlSchemaPAttrUseErr(ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000011879 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011880 NULL, type, NULL, cur->attr,
11881 "The 'optional' use is inconsistent with a matching "
11882 "'required' use of the base type", NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000011883 } else if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
11884 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
11885 /*
11886 * derivation-ok-restriction 3
11887 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011888 xmlSchemaPCustomErr(ctxt,
11889 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
11890 NULL, type, NULL,
11891 "A matching attribute use for the 'required' "
11892 "attribute use %s of the base type is missing",
11893 xmlSchemaFormatNsUriLocal(&str,
11894 xmlSchemaGetAttrTargetNsURI(base->attr),
11895 xmlSchemaGetAttrName(base->attr)));
11896 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000011897 } else {
11898 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011899 * 2.1.3 [Definition:] Let the effective value
11900 * constraint of an attribute use be its {value
11901 * constraint}, if present, otherwise its {attribute
11902 * declaration}'s {value constraint} .
11903 */
11904 xmlSchemaGetEffectiveValueConstraint(base->attr, &effFixed,
11905 &bEffValue, 0);
11906 /*
11907 * 2.1.3 ... one of the following must be true
11908 *
11909 * 2.1.3.1 B's ·effective value constraint· is
11910 * ·absent· or default.
11911 */
11912 if ((bEffValue != NULL) &&
11913 (effFixed == 1)) {
11914 const xmlChar *rEffValue = NULL;
11915
11916 xmlSchemaGetEffectiveValueConstraint(base->attr, &effFixed,
11917 &rEffValue, 0);
11918 /*
11919 * 2.1.3.2 R's ·effective value constraint· is
11920 * fixed with the same string as B's.
11921 */
11922 if ((effFixed == 0) ||
11923 (! xmlStrEqual(rEffValue, bEffValue))) {
11924 xmlSchemaPAttrUseErr(ctxt,
11925 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
11926 NULL, type, NULL, cur->attr,
11927 "The effective value constraint of the "
11928 "attribute use is inconsistent with "
11929 "its correspondent of the base type",
11930 NULL);
11931 }
11932 }
11933 /*
11934 * TODO: derivation-ok-restriction 2.1.2 ({type definition} must be validly derived)
11935 */
11936 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000011937 * Override the attribute use.
11938 */
11939 base->attr = cur->attr;
11940 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011941
Daniel Veillard3646d642004-06-02 19:19:14 +000011942 break;
11943 }
11944 base = base->next;
11945 }
11946
11947 if (!found) {
11948 if (cur->attr->occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
11949 /*
11950 * derivation-ok-restriction 2.2
11951 */
11952 if ((type->attributeWildcard != NULL) &&
11953 xmlSchemaMatchesWildcardNs(type->attributeWildcard,
11954 cur->attr->targetNamespace))
11955 found = 1;
11956
11957 if (!found) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011958 xmlSchemaPAttrUseErr(ctxt,
11959 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
11960 NULL, type, NULL, cur->attr,
11961 "Neither a matching attribute use, "
11962 "nor a matching wildcard in the base type does exist",
11963 NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000011964 } else {
11965 /*
11966 * Add the attribute use.
11967 *
11968 * Note that this may lead to funny derivation error reports, if
11969 * multiple equal attribute uses exist; but this is not
11970 * allowed anyway, and it will be reported beforehand.
11971 */
11972 tmp = cur;
11973 if (prev != NULL)
11974 prev->next = cur->next;
11975 else
11976 uses = cur->next;
11977 cur = cur->next;
11978 if (type->attributeUses == NULL) {
11979 type->attributeUses = tmp;
11980 } else
11981 lastBaseUse->next = tmp;
11982 lastBaseUse = tmp;
11983
11984 continue;
11985 }
11986 }
11987 }
11988 prev = cur;
11989 cur = cur->next;
11990 }
11991 if (uses != NULL)
11992 xmlSchemaFreeAttributeUseList(uses);
11993 }
11994 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
11995 /*
11996 * The spec allows only appending, and not other kinds of extensions.
11997 *
11998 * This ensures: Schema Component Constraint: Derivation Valid (Extension) : 1.2
11999 */
12000 if (uses != NULL) {
12001 if (type->attributeUses == NULL) {
12002 type->attributeUses = uses;
12003 } else
12004 lastBaseUse->next = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000012005 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012006 } else {
12007 /*
Daniel Veillard50355f02004-06-08 17:52:16 +000012008 * Derive implicitely from the ur-type.
12009 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012010 type->attributeUses = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000012011 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012012 /*
12013 * 3.4.6 -> Complex Type Definition Properties Correct
12014 */
12015 if (type->attributeUses != NULL) {
12016 cur = type->attributeUses;
12017 prev = NULL;
12018 while (cur != NULL) {
12019 /*
12020 * 4. Two distinct attribute declarations in the {attribute uses} must
12021 * not have identical {name}s and {target namespace}s.
Daniel Veillard50355f02004-06-08 17:52:16 +000012022 *
Daniel Veillard3646d642004-06-02 19:19:14 +000012023 * Note that this was already done for "restriction" and types derived from
12024 * the ur-type.
Daniel Veillard50355f02004-06-08 17:52:16 +000012025 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012026 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
12027 tmp = cur->next;
12028 while (tmp != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012029 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
12030 xmlSchemaGetAttrName(tmp->attr))) &&
12031 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
12032 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012033
Daniel Veillardc0826a72004-08-10 14:17:33 +000012034 xmlSchemaPAttrUseErr(ctxt,
12035 XML_SCHEMAP_CT_PROPS_CORRECT_4,
12036 NULL, type, NULL, tmp->attr,
12037 "Duplicate attribute use specified", NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000012038 break;
12039 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012040 tmp = tmp->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000012041 }
12042 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012043 /*
12044 * 5. Two distinct attribute declarations in the {attribute uses} must
12045 * not have {type definition}s which are or are derived from ID.
12046 */
12047 if ((cur->attr->subtypes != NULL) &&
Daniel Veillard01fa6152004-06-29 17:04:39 +000012048 (xmlSchemaIsDerivedFromBuiltInType(ctxt, (xmlSchemaTypePtr) cur->attr, XML_SCHEMAS_ID))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012049 if (id != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012050 xmlSchemaPAttrUseErr(ctxt,
12051 XML_SCHEMAP_CT_PROPS_CORRECT_5,
12052 NULL, type, NULL, cur->attr,
12053 "There must not exist more than one attribute use, "
12054 "declared of type 'ID' or derived from it",
12055 NULL);
12056 FREE_AND_NULL(str)
Daniel Veillard50355f02004-06-08 17:52:16 +000012057 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012058 id = cur;
12059 }
12060 /*
12061 * Remove "prohibited" attribute uses. The reason this is done at this late
12062 * stage is to be able to catch dublicate attribute uses. So we had to keep
12063 * prohibited uses in the list as well.
12064 */
12065 if (cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
12066 tmp = cur;
12067 if (prev == NULL)
12068 type->attributeUses = cur->next;
12069 else
12070 prev->next = cur->next;
12071 cur = cur->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000012072 xmlFree(tmp);
Daniel Veillard3646d642004-06-02 19:19:14 +000012073 } else {
12074 prev = cur;
12075 cur = cur->next;
12076 }
12077 }
12078 }
12079 /*
12080 * TODO: This check should be removed if we are 100% sure of
12081 * the base type attribute uses already being built.
12082 */
12083 if ((baseType != NULL) && (!baseIsAnyType) &&
12084 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
12085 (baseType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012086 xmlSchemaPErr(ctxt, baseType->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012087 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012088 "attribute uses not builded on base type '%s'.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +000012089 baseType->name, NULL);
12090 }
12091 return (0);
12092}
12093
12094/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000012095 * xmlSchemaTypeFinalContains:
12096 * @schema: the schema
12097 * @type: the type definition
12098 * @final: the final
12099 *
12100 * Evaluates if a type definition contains the given "final".
12101 * This does take "finalDefault" into account as well.
12102 *
12103 * Returns 1 if the type does containt the given "final",
12104 * 0 otherwise.
12105 */
12106static int
12107xmlSchemaTypeFinalContains(xmlSchemaPtr schema, xmlSchemaTypePtr type, int final)
12108{
12109 int tfinal = final, tflags = type->flags;
12110
12111 if (type == NULL)
12112 return (0);
12113 if (type->flags & XML_SCHEMAS_TYPE_FINAL_DEFAULT) {
12114 switch (final) {
12115 case XML_SCHEMAS_TYPE_FINAL_RESTRICTION:
12116 tfinal = XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
12117 break;
12118 case XML_SCHEMAS_TYPE_FINAL_EXTENSION:
12119 tfinal = XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
12120 break;
12121 case XML_SCHEMAS_TYPE_FINAL_LIST:
12122 tfinal = XML_SCHEMAS_FINAL_DEFAULT_LIST;
12123 break;
12124 case XML_SCHEMAS_TYPE_FINAL_UNION:
12125 tfinal = XML_SCHEMAS_FINAL_DEFAULT_UNION;
12126 break;
12127 }
12128 tflags = schema->flags;
12129 }
12130 if (tflags & tfinal)
12131 return (1);
12132 else
12133 return (0);
12134
12135}
12136
12137/**
12138 * xmlSchemaGetUnionSimpleTypeMemberTypes:
12139 * @type: the Union Simple Type
12140 *
12141 * Returns a list of member types of @type if existing,
12142 * returns NULL otherwise.
12143 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012144static xmlSchemaTypeLinkPtr
Daniel Veillard01fa6152004-06-29 17:04:39 +000012145xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
12146{
12147 while (type != NULL) {
12148 if (type->memberTypes != NULL)
12149 return (type->memberTypes);
12150 else
12151 type = type->baseType;
12152 }
12153 return (NULL);
12154}
12155
12156/**
12157 * xmlSchemaGetListSimpleTypeItemType:
12158 * @type: the simple type definition
12159 *
12160 * Returns the item type definition of the list simple type.
12161 */
12162static xmlSchemaTypePtr
12163xmlSchemaGetListSimpleTypeItemType(xmlSchemaTypePtr type)
12164{
12165 if ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)
12166 return (NULL);
12167 /*
12168 * Note: In libxml2, the built-in types do not reflect
12169 * the datatype hierarchy (yet?) - we have to treat them
12170 * in a special way.
12171 */
12172 if (type->type == XML_SCHEMA_TYPE_BASIC)
12173 return (xmlSchemaGetBuiltInListSimpleTypeItemType(type));
12174 if (type->subtypes->type == XML_SCHEMA_TYPE_LIST)
12175 /* 1 If the <list> alternative is chosen, then the type
12176 * definition ·resolved· to by the ·actual value· of the
12177 * itemType [attribute] of <list>, if present, otherwise
12178 * the type definition corresponding to the <simpleType>
12179 * among the [children] of <list>.
12180 */
12181 return (type->subtypes->subtypes);
12182 else {
12183 /* 2 If the <restriction> option is chosen, then the
12184 * {item type definition} of the {base type definition}.
12185 */
12186 return (xmlSchemaGetListSimpleTypeItemType(type->baseType));
12187 }
12188}
12189
12190/**
12191 * xmlSchemaCheckCOSSTDerivedOK:
12192 * @type: the derived simple type definition
12193 * @baseType: the base type definition
12194 *
12195 * Checks wheter @type can be validly
12196 * derived from @baseType.
12197 *
12198 * Returns 0 on success, an positive error code otherwise.
12199 */
12200static int
12201xmlSchemaCheckCOSSTDerivedOK(xmlSchemaPtr schema,
12202 xmlSchemaTypePtr type,
12203 xmlSchemaTypePtr baseType,
12204 int subset)
12205{
12206 /*
12207 * Schema Component Constraint: Type Derivation OK (Simple)
12208 *
12209 *
12210 * 1 They are the same type definition.
12211 * TODO: The identy check might have to be more complex than this.
12212 */
12213 if (type == baseType)
12214 return (0);
12215 /*
12216 * 2.1 restriction is not in the subset, or in the {final}
12217 * of its own {base type definition};
12218 */
12219 if ((subset & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) ||
12220 (xmlSchemaTypeFinalContains(schema,
12221 type->baseType, XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
12222 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
12223 }
12224 /* 2.2 */
12225 if (type->baseType == baseType) {
12226 /*
12227 * 2.2.1 D's ·base type definition· is B.
12228 */
12229 return (0);
12230 }
12231 /*
12232 * 2.2.2 D's ·base type definition· is not the ·ur-type definition·
12233 * and is validly derived from B given the subset, as defined by this
12234 * constraint.
12235 */
12236 if ((type->baseType != xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE)) &&
12237 (xmlSchemaCheckCOSSTDerivedOK(schema, type->baseType, baseType, subset) == 0)) {
12238 return (0);
12239 }
12240 /*
12241 * 2.2.3 D's {variety} is list or union and B is the ·simple ur-type
12242 * definition·.
12243 */
12244 if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
12245 (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)) &&
12246 (baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE))) {
12247 return (0);
12248 }
12249 /*
12250 * 2.2.4 B's {variety} is union and D is validly derived from a type
12251 * definition in B's {member type definitions} given the subset, as
12252 * defined by this constraint.
12253 *
12254 * NOTE: This seems not to involve built-in types, since there is no
12255 * built-in Union Simple Type.
12256 */
12257 if (baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
12258 xmlSchemaTypeLinkPtr cur;
12259
12260 cur = baseType->memberTypes;
12261 while (cur != NULL) {
12262 if (xmlSchemaCheckCOSSTDerivedOK(schema, type,
12263 cur->type, subset) == 0)
12264 return (0);
12265 cur = cur->next;
12266 }
12267 }
12268
12269 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
12270}
12271
12272
12273/**
12274 * xmlSchemaCheckSTPropsCorrect:
12275 * @ctxt: the schema parser context
12276 * @type: the simple type definition
12277 *
12278 * Checks st-props-correct.
12279 *
12280 * Returns 0 if the properties are correct,
12281 * if not, a positive error code and -1 on internal
12282 * errors.
12283 */
12284static int
12285xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
12286 xmlSchemaTypePtr type)
12287{
12288 xmlSchemaTypePtr baseType = type->baseType, anySimpleType,
12289 anyType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012290 xmlChar *str = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012291
Daniel Veillardc0826a72004-08-10 14:17:33 +000012292 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012293 /*
12294 * Schema Component Constraint: Simple Type Definition Properties Correct
12295 *
12296 * NOTE: This is somehow redundant, since we actually built a simple type
12297 * to have all the needed information; this acts as an self test.
12298 */
12299 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
12300 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
12301 /*
12302 * TODO: 1 The values of the properties of a simple type definition must be as
12303 * described in the property tableau in Datatype definition, modulo the
12304 * impact of Missing Sub-components (§5.3).
12305 */
12306 /* Base type: If the datatype has been ·derived· by ·restriction·
12307 * then the Simple Type Definition component from which it is ·derived·,
12308 * otherwise the Simple Type Definition for anySimpleType (§4.1.6).
12309 */
12310 if (baseType == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012311 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012312 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012313 NULL, type, NULL,
12314 "No base type existent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012315 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
12316 }
12317 if ((baseType->type != XML_SCHEMA_TYPE_SIMPLE) &&
12318 ((baseType->type != XML_SCHEMA_TYPE_BASIC) ||
12319 (baseType == anyType))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012320 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012321 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012322 NULL, type, NULL,
12323 "The base type %s is not a simple type",
12324 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
12325 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012326 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
12327 }
12328 if ((baseType != anySimpleType) &&
12329 (type->subtypes->type != XML_SCHEMA_TYPE_RESTRICTION)) {
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 "A type, derived by list or union, must have"
12334 "the simple ur-type definition as base type, not %s",
12335 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
12336 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012337 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
12338 }
12339 /*
12340 * Variety: One of {atomic, list, union}.
12341 */
12342 if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
12343 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) &&
12344 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012345 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012346 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012347 NULL, type, NULL,
12348 "The variety is absent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012349 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
12350 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000012351 /* TODO: Finish this. Hmm, is this finished? */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012352
12353 /*
12354 * 2 All simple type definitions must be derived ultimately from the ·simple
12355 * ur-type definition (so· circular definitions are disallowed). That is, it
12356 * must be possible to reach a built-in primitive datatype or the ·simple
12357 * ur-type definition· by repeatedly following the {base type definition}.
12358 */
12359 baseType = type->baseType;
12360 while ((baseType != NULL) && (baseType->type != XML_SCHEMA_TYPE_BASIC)) {
12361 if (baseType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
12362 xmlSchemaTypeFixup(baseType, ctxt, NULL);
12363 if (baseType == anySimpleType)
12364 break;
12365 else if (baseType == type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012366 xmlSchemaPCustomErr(ctxt,
12367 XML_SCHEMAP_ST_PROPS_CORRECT_2,
12368 NULL, type, NULL,
12369 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012370 return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
12371 }
12372 baseType = baseType->baseType;
12373 }
12374 /*
12375 * 3 The {final} of the {base type definition} must not contain restriction.
12376 */
12377 if (xmlSchemaTypeFinalContains(ctxt->schema, baseType,
12378 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012379 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012380 XML_SCHEMAP_ST_PROPS_CORRECT_3,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012381 NULL, type, NULL,
12382 "The 'final' of its base type %s must not contain "
12383 "'restriction'",
12384 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
12385 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012386 return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
12387 }
12388 return (0);
12389}
12390
12391/**
12392 * xmlSchemaCheckDerivationValidSimpleRestriction:
12393 * @ctxt: the schema parser context
12394 * @type: the simple type definition
12395 *
12396 * Checks if the given @type (simpleType) is derived
12397 * validly by restriction.
12398 *
12399 * Returns -1 on internal errors, 0 if the type is validly derived,
12400 * a positive error code otherwise.
12401 */
12402static int
12403xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012404 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012405{
Daniel Veillardc0826a72004-08-10 14:17:33 +000012406 xmlChar *str = NULL;
12407
12408 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012409
12410 if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
12411 xmlSchemaPErr(ctxt, type->node,
12412 XML_ERR_INTERNAL_ERROR,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012413 "xmlSchemaCheckDerivationValidSimpleRestriction: The given "
12414 "type '%s' is not a user-derived simpleType.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012415 type->name, NULL);
12416 return (-1);
12417 }
12418
12419 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
12420 xmlSchemaTypePtr primitive;
12421 /*
12422 * 1.1 The {base type definition} must be an atomic simple
12423 * type definition or a built-in primitive datatype.
12424 */
12425 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012426 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012427 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012428 NULL, type, NULL,
12429 "The base type %s is not an atomic simple type",
12430 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
12431 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012432 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
12433 }
12434 /* 1.2 The {final} of the {base type definition} must not contain
12435 * restriction.
12436 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000012437 /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012438 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
12439 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012440 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012441 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012442 NULL, type, NULL,
12443 "The final of its base type %s must not contain 'restriction'",
12444 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
12445 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012446 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
12447 }
12448
12449 /*
12450 * 1.3.1 DF must be an allowed constraining facet for the {primitive
12451 * type definition}, as specified in the appropriate subsection of 3.2
12452 * Primitive datatypes.
12453 */
12454 if (type->facets != NULL) {
12455 xmlSchemaFacetPtr facet;
12456 int ok = 1;
12457
12458 primitive = xmlSchemaGetPrimitiveType(type);
12459 if (primitive == NULL) {
12460 xmlSchemaPErr(ctxt, type->node,
12461 XML_ERR_INTERNAL_ERROR,
12462 "xmlSchemaCheckDerivationValidSimpleRestriction: failed "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012463 "to get primitive type of type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012464 type->name, NULL);
12465 return (-1);
12466 }
12467 facet = type->facets;
12468 do {
12469 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012470 ok = 0;
12471 xmlSchemaPIllegalFacetAtomicErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012472 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012473 NULL, type, primitive, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012474 }
12475 facet = facet->next;
12476 } while (facet != NULL);
12477 if (ok == 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +000012478 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012479 }
12480 /*
12481 * TODO: 1.3.2 (facet derivation)
12482 */
12483 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
12484 xmlSchemaTypePtr itemType = NULL;
12485
12486 itemType = xmlSchemaGetListSimpleTypeItemType(type);
12487 if (itemType == NULL) {
12488 xmlSchemaPErr(ctxt, type->node,
12489 XML_ERR_INTERNAL_ERROR,
12490 "Internal error: xmlSchemaCheckDerivationValidSimpleRestriction: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012491 "failed to evaluate the item type of type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012492 type->name, NULL);
12493 return (-1);
12494 }
12495 /*
12496 * 2.1 The {item type definition} must have a {variety} of atomic or
12497 * union (in which case all the {member type definitions}
12498 * must be atomic).
12499 */
12500 if (((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
12501 ((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012502 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012503 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012504 NULL, type, NULL,
12505 "The item type %s must have a variety of atomic or union",
12506 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1));
12507 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012508 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
12509 } else if (itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
12510 xmlSchemaTypeLinkPtr member;
12511
12512 member = itemType->memberTypes;
12513 while (member != NULL) {
12514 if ((member->type->flags &
12515 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012516 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012517 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012518 NULL, type, NULL,
12519 "The item type is a union type, but the "
12520 "member type %s of this item type is not atomic",
12521 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
12522 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012523 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
12524 }
12525 member = member->next;
12526 }
12527 }
12528
12529 if (type->baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE)) {
12530 xmlSchemaFacetPtr facet;
12531 /*
12532 * This is the case if we have: <simpleType><list ..
12533 */
12534 /*
12535 * 2.3.1
12536 * 2.3.1.1 The {final} of the {item type definition} must not
12537 * contain list.
12538 */
12539 if (xmlSchemaTypeFinalContains(ctxt->schema,
12540 itemType, XML_SCHEMAS_TYPE_FINAL_LIST)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012541 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012542 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012543 NULL, type, NULL,
12544 "The final of its item type %s must not contain 'list'",
12545 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1));
12546 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012547 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
12548 }
12549 /*
12550 * 2.3.1.2 The {facets} must only contain the whiteSpace
12551 * facet component.
12552 */
12553 if (type->facets != NULL) {
12554 facet = type->facets;
12555 do {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012556 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
12557 xmlSchemaPIllegalFacetListUnionErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012558 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012559 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012560 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
12561 }
12562 facet = facet->next;
12563 } while (facet != NULL);
12564 }
12565 /*
12566 * TODO: Datatypes states:
12567 * A ·list· datatype can be ·derived· from an ·atomic· datatype
12568 * whose ·lexical space· allows space (such as string or anyURI)or
12569 * a ·union· datatype any of whose {member type definitions}'s
12570 * ·lexical space· allows space.
12571 */
12572 } else {
12573 /*
12574 * This is the case if we have: <simpleType><restriction ...
12575 */
12576 /*
12577 * 2.3.2
12578 * 2.3.2.1 The {base type definition} must have a {variety} of list.
12579 */
12580 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012581 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012582 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012583 NULL, type, NULL,
12584 "The base type %s must be a list type",
12585 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
12586 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012587 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
12588 }
12589 /*
12590 * 2.3.2.2 The {final} of the {base type definition} must not
12591 * contain restriction.
12592 */
12593 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
12594 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012595 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012596 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012597 NULL, type, NULL,
12598 "The final of the base type %s must not contain 'restriction'",
12599 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
12600 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012601 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
12602 }
12603 /*
12604 * 2.3.2.3 The {item type definition} must be validly derived
12605 * from the {base type definition}'s {item type definition} given
12606 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6).
12607 */
12608 {
12609 xmlSchemaTypePtr baseItemType;
12610
12611 baseItemType = xmlSchemaGetListSimpleTypeItemType(type->baseType);
12612 if (baseItemType == NULL) {
12613 xmlSchemaPErr(ctxt, type->node,
12614 XML_ERR_INTERNAL_ERROR,
12615 "xmlSchemaCheckDerivationValidSimpleRestriction: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012616 "List simple type '%s': Failed to "
12617 "evaluate the item type of its base type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012618 type->name, type->baseType->name);
12619 return (-1);
12620 }
12621 if ((itemType != baseItemType) &&
12622 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema, itemType,
12623 baseItemType, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012624 xmlChar *strBIT = NULL, *strBT = NULL;
12625 xmlSchemaPCustomErrExt(ctxt,
12626 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
12627 NULL, type, NULL,
12628 "The item type %s is not validly derived from the "
12629 "item type %s of the base type %s",
12630 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1),
12631 xmlSchemaFormatItemForReport(&strBIT, NULL, baseItemType, NULL, 1),
12632 xmlSchemaFormatItemForReport(&strBT, NULL, type->baseType, NULL, 1));
12633
12634 FREE_AND_NULL(str)
12635 FREE_AND_NULL(strBIT)
12636 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012637 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
12638 }
12639 }
12640
12641 if (type->facets != NULL) {
12642 xmlSchemaFacetPtr facet;
12643 int ok = 1;
12644 /*
12645 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
12646 * and enumeration facet components are allowed among the {facets}.
12647 */
12648 facet = type->facets;
12649 do {
12650 switch (facet->type) {
12651 case XML_SCHEMA_FACET_LENGTH:
12652 case XML_SCHEMA_FACET_MINLENGTH:
12653 case XML_SCHEMA_FACET_MAXLENGTH:
12654 case XML_SCHEMA_FACET_WHITESPACE:
12655 /*
12656 * TODO: 2.5.1.2 List datatypes
12657 * The value of ·whiteSpace· is fixed to the value collapse.
12658 */
12659 case XML_SCHEMA_FACET_PATTERN:
12660 case XML_SCHEMA_FACET_ENUMERATION:
12661 break;
12662 default: {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012663 xmlSchemaPIllegalFacetListUnionErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012664 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012665 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012666 /*
12667 * We could return, but it's nicer to report all
12668 * invalid facets.
12669 */
12670 ok = 0;
12671 }
12672 }
12673 facet = facet->next;
12674 } while (facet != NULL);
12675 if (ok == 0)
12676 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
12677 /*
12678 * TODO: 2.3.2.5 For each facet in the {facets} (call this DF), if there
12679 * is a facet of the same kind in the {facets} of the {base type
12680 * definition} (call this BF),then the DF's {value} must be a valid
12681 * restriction of BF's {value} as defined in [XML Schemas: Datatypes].
12682 */
12683 }
12684
12685
12686 }
12687 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
12688 /*
12689 * 3.1 The {member type definitions} must all have {variety} of
12690 * atomic or list.
12691 */
12692 xmlSchemaTypeLinkPtr member;
12693
12694 member = type->memberTypes;
12695 while (member != NULL) {
12696 if (((member->type->flags &
12697 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
12698 ((member->type->flags &
12699 XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012700 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012701 XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012702 NULL, type, NULL,
12703 "The member type %s is neither an atomic, nor a list type",
12704 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
12705 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012706 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
12707 }
12708 member = member->next;
12709 }
12710 /*
12711 * 3.3.1 If the {base type definition} is the ·simple ur-type
12712 * definition·
12713 */
12714 if (type->baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE)) {
12715 /*
12716 * 3.3.1.1 All of the {member type definitions} must have a
12717 * {final} which does not contain union.
12718 */
12719 member = type->memberTypes;
12720 while (member != NULL) {
12721 if (xmlSchemaTypeFinalContains(ctxt->schema, member->type,
12722 XML_SCHEMAS_TYPE_FINAL_UNION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012723 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012724 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012725 NULL, type, NULL,
12726 "The final of member type %s contains 'union'",
12727 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
12728 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012729 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
12730 }
12731 member = member->next;
12732 }
12733 /*
12734 * 3.3.1.2 The {facets} must be empty.
12735 */
12736 if (type->facetSet != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012737 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012738 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012739 NULL, type, NULL,
12740 "No facets allowed", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012741 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
12742 }
12743 } else {
12744 /*
12745 * 3.3.2.1 The {base type definition} must have a {variety} of union.
12746 */
12747 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012748 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012749 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012750 NULL, type, NULL,
12751 "The base type %s is not a union type",
12752 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
12753 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012754 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
12755 }
12756 /*
12757 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
12758 */
12759 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
12760 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012761 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012762 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012763 NULL, type, NULL,
12764 "The final of its base type %s must not contain 'restriction'",
12765 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
12766 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012767 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
12768 }
12769 /*
12770 * 3.3.2.3 The {member type definitions}, in order, must be validly
12771 * derived from the corresponding type definitions in the {base
12772 * type definition}'s {member type definitions} given the empty set,
12773 * as defined in Type Derivation OK (Simple) (§3.14.6).
12774 */
12775 {
12776 xmlSchemaTypeLinkPtr baseMember;
12777
12778 /*
12779 * OPTIMIZE: if the type is restricting, it has no local defined
12780 * member types and inherits the member types of the base type;
12781 * thus a check for equality can be skipped.
12782 */
12783 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000012784 * Even worse: I cannot see a scenario where a restricting
Daniel Veillard01fa6152004-06-29 17:04:39 +000012785 * union simple type can have other member types as the member
12786 * types of it's base type. This check seems not necessary with
12787 * respect to the derivation process in libxml2.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000012788 * But necessary if constructing types with an API.
Daniel Veillard01fa6152004-06-29 17:04:39 +000012789 */
12790 if (type->memberTypes != NULL) {
12791 member = type->memberTypes;
12792 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
12793 if ((member == NULL) && (baseMember != NULL)) {
12794 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012795 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012796 "Internal error: "
12797 "xmlSchemaCheckDerivationValidSimpleRestriction "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012798 "(3.3.2.3), union simple type '%s', unequal number "
Daniel Veillard01fa6152004-06-29 17:04:39 +000012799 "of member types in the base type\n",
12800 type->name, NULL);
12801 }
12802 while (member != NULL) {
12803 if (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 "
12809 "of member types in the base type.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012810 type->name, NULL);
12811 }
12812 if ((member->type != baseMember->type) &&
12813 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema,
12814 member->type, baseMember->type, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012815 xmlChar *strBMT = NULL, *strBT = NULL;
12816
12817 xmlSchemaPCustomErrExt(ctxt,
12818 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
12819 NULL, type, NULL,
12820 "The member type %s is not validly derived from its "
12821 "corresponding member type %s of the base type %s",
12822 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1),
12823 xmlSchemaFormatItemForReport(&strBMT, NULL, baseMember->type, NULL, 1),
12824 xmlSchemaFormatItemForReport(&strBT, NULL, type->baseType, NULL, 1));
12825 FREE_AND_NULL(str)
12826 FREE_AND_NULL(strBMT)
12827 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012828 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
12829 }
12830 member = member->next;
12831 baseMember = baseMember->next;
12832 }
12833 }
12834 }
12835 /*
12836 * 3.3.2.4 Only pattern and enumeration facet components are
12837 * allowed among the {facets}.
12838 */
12839 if (type->facets != NULL) {
12840 xmlSchemaFacetPtr facet;
12841 int ok = 1;
12842
12843 facet = type->facets;
12844 do {
12845 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
12846 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012847 xmlSchemaPIllegalFacetListUnionErr(ctxt,
12848 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
12849 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012850 ok = 0;
12851 }
12852 facet = facet->next;
12853 } while (facet != NULL);
12854 if (ok == 0)
12855 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
12856
12857 }
12858 /*
12859 * TODO: 3.3.2.5 (facet derivation)
12860 */
12861 }
12862 }
12863
12864 return (0);
12865}
12866
12867/**
12868 * xmlSchemaCheckSRCSimpleType:
12869 * @ctxt: the schema parser context
12870 * @type: the simple type definition
12871 *
12872 * Checks crc-simple-type constraints.
12873 *
12874 * Returns 0 if the constraints are satisfied,
12875 * if not a positive error code and -1 on internal
12876 * errors.
12877 */
12878static int
12879xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
12880 xmlSchemaTypePtr type)
12881{
12882 /*
12883 * NOTE: src-simple-type 2-4 are redundant, since the checks
12884 * were are done for the corresponding <restriction>, <list> and <union>
12885 * elements, but W3C wants a <simpleType> error as well, so it gets one.
12886 * Maby this can be skipped in the future, if we get sure it's not needed.
12887 */
12888 if (type->subtypes == NULL) {
12889 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012890 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012891 "Internal error: xmlSchemaCheckSRCSimpleType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012892 "no subtype on simple type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012893 type->name, NULL);
12894 return (-1);
12895 }
12896 /*
12897 * src-simple-type.1 The corresponding simple type definition, if any,
12898 * must satisfy the conditions set out in Constraints on Simple Type
12899 * Definition Schema Components (§3.14.6).
12900 */
12901 if ((xmlSchemaCheckSTPropsCorrect(ctxt, type) != 0) ||
12902 (xmlSchemaCheckCOSSTRestricts(ctxt, type) != 0)) {
12903 /*
12904 * TODO: Removed this, since it got annoying to get an
12905 * extra error report, if anything failed until now.
12906 * Enable this if needed.
12907 */
12908 /*
12909 xmlSchemaPErr(ctxt, type->node,
12910 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012911 "Simple type '%s' does not satisfy the constraints "
Daniel Veillard01fa6152004-06-29 17:04:39 +000012912 "on simple type definitions.\n",
12913 type->name, NULL);
12914 */
12915 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_1);
12916 }
12917
12918 if (type->subtypes->type == XML_SCHEMA_TYPE_RESTRICTION) {
12919 /*
12920 * src-simple-type.2 If the <restriction> alternative is chosen,
12921 * either it must have a base [attribute] or a <simpleType> among its
12922 * [children], but not both.
12923 */
William M. Brack2f2a6632004-08-20 23:09:47 +000012924 /*
12925 * XML_SCHEMAP_SRC_SIMPLE_TYPE_2
12926 * NOTE: This was removed, since this will be already handled
12927 * in the parse function for <restriction>.
12928 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012929 } else if (type->subtypes->type == XML_SCHEMA_TYPE_LIST) {
12930 /* src-simple-type.3 If the <list> alternative is chosen, either it must have
12931 * an itemType [attribute] or a <simpleType> among its [children],
12932 * but not both.
12933 * NOTE: baseType is set to the local simple type definiton,
12934 * if existent, at parse time. This is a hack and not nice.
12935 */
William M. Brack2f2a6632004-08-20 23:09:47 +000012936 /*
12937 * TODO: Remove this, and add the check to the parse function of <list>.
12938 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012939 if (((type->subtypes->base == NULL) &&
12940 (type->baseType == NULL)) ||
12941 ((type->subtypes->base != NULL) &&
12942 (type->subtypes->baseType != NULL))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012943 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012944 XML_SCHEMAP_SRC_SIMPLE_TYPE_3,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012945 NULL, type, NULL,
12946 "Either the attribute 'itemType' or the <simpleType> child "
12947 "must be present on the <list> child ", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012948 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_3);
12949 }
12950
12951
12952 } else if (type->subtypes->type == XML_SCHEMA_TYPE_UNION) {
12953 xmlSchemaTypeLinkPtr member;
12954 xmlSchemaTypePtr ancestor, anySimpleType;
12955
12956 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
12957
12958 /* src-simple-type.4 Circular union type definition is disallowed. That is, if
12959 * the <union> alternative is chosen, there must not be any entries
12960 * in the memberTypes [attribute] at any depth which resolve to the
12961 * component corresponding to the <simpleType>.
12962 */
12963 member = type->memberTypes;
12964 while (member != NULL) {
12965 ancestor = member->type;
12966 while ((ancestor != NULL) && (ancestor->type != XML_SCHEMA_TYPE_BASIC)) {
12967 if (ancestor->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
12968 xmlSchemaTypeFixup(ancestor, ctxt, NULL);
12969 if (ancestor == anySimpleType)
12970 break;
12971 else if (ancestor == type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012972 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012973 XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012974 NULL, type, NULL,
12975 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012976 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
12977 } else if (ancestor->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
12978 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000012979 * TODO, FIXME: Although a list simple type must not have a union ST
Daniel Veillard01fa6152004-06-29 17:04:39 +000012980 * type as item type, which in turn has a list ST as member
12981 * type, we will assume this here as well, since this check
12982 * was not yet performed.
12983 */
12984
12985 }
12986 ancestor = ancestor->baseType;
12987 }
12988 member = member->next;
12989 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012990 }
12991
12992 return (0);
12993}
12994
William M. Brack2f2a6632004-08-20 23:09:47 +000012995#if 0 /* Not yet used code for CT schema validation */
12996static int
12997xmlSchemaCheckCVCSimpleType(xmlSchemaValidCtxtPtr ctxt,
12998 const xmlChar * value,
12999 xmlSchemaTypePtr type,
13000 int fireErrors)
13001{
13002 int ret;
13003 /*
13004 * 3.14.4 Simple Type Definition Validation Rules
13005 * Validation Rule: String Valid
13006 */
13007 /*
13008 * 1 It is schema-valid with respect to that definition as defined
13009 * by Datatype Valid in [XML Schemas: Datatypes].
13010 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013011 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type, value,
13012 fireErrors, 1, 1, 1);
William M. Brack2f2a6632004-08-20 23:09:47 +000013013 return (ret);
13014 /*
13015 * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
13016 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6), then
13017 * the string must be a ·declared entity name·.
13018 */
13019 /*
13020 * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
13021 * given the empty set, as defined in Type Derivation OK (Simple) (§3.14.6),
13022 * then every whitespace-delimited substring of the string must be a ·declared
13023 * entity name·.
13024 */
13025 /*
13026 * 2.3 otherwise no further condition applies.
13027 */
13028
13029 return (0);
13030}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013031#endif
13032
William M. Brack2f2a6632004-08-20 23:09:47 +000013033
13034static int
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013035xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
13036{
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000013037 if (vctxt->pctxt == NULL) {
13038 if (vctxt->schema != NULL)
13039 vctxt->pctxt = xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
13040 else
13041 vctxt->pctxt = xmlSchemaNewParserCtxt("*");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013042 if (vctxt->pctxt == NULL) {
13043 xmlSchemaVErr(vctxt, NULL,
13044 XML_SCHEMAV_INTERNAL,
13045 "Internal error: xmlSchemaCreatePCtxtOnVCtxt, "
13046 "failed to create a temp. parser context.\n",
William M. Brack2f2a6632004-08-20 23:09:47 +000013047 NULL, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013048 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013049 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013050 /* TODO: Pass user data. */
13051 xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error, vctxt->warning, NULL);
13052 }
13053 return (0);
13054}
13055
13056static int
13057xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
13058{
13059 if (ctxt->vctxt == NULL) {
13060 ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
13061 if (ctxt->vctxt == NULL) {
13062 xmlSchemaPErr(ctxt, NULL,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013063 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013064 "Internal error: xmlSchemaCreatePCtxtOnVCtxt, "
13065 "failed to create a temp. validation context.\n",
13066 NULL, NULL);
13067 return (-1);
13068 }
13069 /* TODO: Pass user data. */
13070 xmlSchemaSetValidErrors(ctxt->vctxt, ctxt->error, ctxt->warning, NULL);
13071 }
13072 return (0);
13073}
13074
13075/**
13076 * xmlSchemaCheckCOSValidDefault:
13077 * @ctxt: the schema parser context
13078 * @type: the simple type definition
13079 * @value: the default value
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000013080 * @val: the precomputed value to be returned
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013081 * @node: an optional node (the holder of the value)
13082 *
13083 * Checks the "cos-valid-default" constraints.
13084 *
13085 * Returns 0 if the constraints are satisfied,
13086 * if not, a positive error code and -1 on internal
13087 * errors.
13088 */
13089static int
13090xmlSchemaCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
13091 xmlSchemaValidCtxtPtr vctxt,
13092 xmlSchemaTypePtr type,
13093 const xmlChar *value,
13094 xmlNodePtr node)
13095{
13096 int ret = 0;
13097
13098 /*
13099 * cos-valid-default:
13100 * Schema Component Constraint: Element Default Valid (Immediate)
13101 * For a string to be a valid default with respect to a type
13102 * definition the appropriate case among the following must be true:
13103 */
13104 /*
13105 * NOTE: This has to work without a given node (the holder of the
13106 * value), since it should work on the component, i.e. an underlying
13107 * DOM must not be mandatory.
13108 */
13109 if ((pctxt == NULL) || (vctxt == NULL)) {
13110 xmlSchemaPErr(pctxt, node,
13111 XML_SCHEMAP_INTERNAL,
13112 "Internal error: xmlSchemaCheckCOSValidDefault, "
13113 "bad arguments: the parser and/or validation context is "
13114 "missing.\n",
13115 NULL, NULL);
13116 return (-1);
13117 }
13118 if IS_COMPLEX_TYPE(type) {
William M. Brack2f2a6632004-08-20 23:09:47 +000013119 /*
13120 * Complex type.
13121 *
13122 * 2.1 its {content type} must be a simple type definition or mixed.
13123 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013124 /*
13125 * TODO: Adjust this when the content type will be computed
13126 * correctly.
13127 */
13128 if ((type->contentType != XML_SCHEMA_CONTENT_SIMPLE) &&
13129 (type->contentType != XML_SCHEMA_CONTENT_BASIC) &&
13130 (type->contentType != XML_SCHEMA_CONTENT_MIXED)) {
13131 xmlSchemaPSimpleTypeErr(pctxt,
13132 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
13133 NULL, NULL, node,
13134 type, NULL, NULL,
13135 "If the type of a constraint value is complex, its content "
13136 "type must be mixed or a simple type",
13137 NULL, NULL);
13138 return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
13139 }
13140 if (type->contentType == XML_SCHEMA_CONTENT_MIXED) {
William M. Brack2f2a6632004-08-20 23:09:47 +000013141 /*
13142 * 2.2.2 If the {content type} is mixed, then the {content type}'s
13143 * particle must be ·emptiable· as defined by Particle Emptiable
13144 * (§3.9.6).
13145 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013146
William M. Brack2f2a6632004-08-20 23:09:47 +000013147 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013148 * URGENT TODO: Implement this.
William M. Brack2f2a6632004-08-20 23:09:47 +000013149 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013150 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000013151 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013152 }
13153 /*
13154 * 1 If the type definition is a simple type definition, then the string
13155 * must be ·valid· with respect to that definition as defined by String
13156 * Valid (§3.14.4).
13157 *
13158 * AND
13159 *
13160 * 2.2.1 If the {content type} is a simple type definition, then the
13161 * string must be ·valid· with respect to that simple type definition
13162 * as defined by String Valid (§3.14.4).
13163 */
13164 vctxt->node = node;
13165 vctxt->cur = NULL;
13166 ret = xmlSchemaValidateSimpleTypeValue(vctxt, type, value, 1, 1, 1, 0);
13167 /* ret = xmlSchemaCheckCVCSimpleType(vctxt, elemDecl->value, typeDef, 0); */
13168 if (ret < 0) {
13169 xmlSchemaPErr(pctxt, node,
13170 /* NOTNICE: error code: This function will be used during
13171 * schema construction and xsi:type validation.
13172 */
13173 XML_SCHEMAP_INTERNAL,
13174 "Internal error: xmlSchemaCheckCOSValidDefault, "
13175 "while validating a value constaint value.\n",
13176 NULL, NULL);
13177
13178 }
13179 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +000013180}
13181
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013182#if 0 /* Not yet used code for CT schema validation */
William M. Brack2f2a6632004-08-20 23:09:47 +000013183/**
13184 * xmlSchemaGetSTContentOfCT:
13185 * @ctxt: the schema parser context
13186 * @type: the complex type definition
13187 *
13188 *
13189 * Returns the corresponding simple type for the content of
13190 * the complex type.
13191 */
13192static xmlSchemaTypePtr
13193xmlSchemaGetSTContentOfCT(xmlSchemaParserCtxtPtr ctxt,
13194 xmlSchemaTypePtr type)
13195{
13196 xmlSchemaTypePtr orig = type, anyType;
13197
13198 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
13199 while ((type != NULL) && (type != anyType) &&
13200 (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
13201 if (type->type == XML_SCHEMA_TYPE_SIMPLE)
13202 return(type);
13203 type = type->baseType;
13204 }
13205 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013206 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000013207 NULL, orig, NULL,
13208 "Internal error: xmlSchemaGetSTContentTypeOfCT, "
13209 "no simple type for the content of complex type '%s' could be "
13210 "computed", orig->name);
13211 return (NULL);
13212}
13213
13214
William M. Brack2f2a6632004-08-20 23:09:47 +000013215
William M. Brack2f2a6632004-08-20 23:09:47 +000013216
13217/**
13218 * xmlSchemaCheckCOSCTExtends:
13219 * @ctxt: the schema parser context
13220 * @type: the complex type definition
13221 *
13222 * Schema Component Constraint: Derivation Valid (Extension)
13223 *
13224 * Returns 0 if the constraints are satisfied, a positive
13225 * error code if not and -1 if an internal error occured.
13226 */
13227static int
13228xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
13229 xmlSchemaTypePtr type)
13230{
13231 xmlSchemaTypePtr base;
13232 /*
13233 * 1 If the {base type definition} is a complex type definition,
13234 * then all of the following must be true:
13235 */
13236 base = type->baseType;
13237 if (base == NULL) {
13238 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013239 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000013240 NULL, type, NULL,
13241 "Internal error: xmlSchemaCheckCOSCTExtends, "
13242 "the complex type '%s' has no base type", type->name);
13243 return (-1);
13244 }
13245 if (base->type == XML_SCHEMA_TYPE_COMPLEX) {
13246 /*
13247 * 1.1 The {final} of the {base type definition} must not
13248 * contain extension.
13249 */
13250 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
13251 xmlSchemaPCustomErr(ctxt,
13252 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
13253 NULL, type, NULL,
13254 "The 'final' of the base type definition "
13255 "contains extension", NULL);
13256 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
13257 }
13258 /*
13259 * 1.2 Its {attribute uses} must be a subset of the {attribute uses}
13260 * of the complex type definition itself, that is, for every attribute
13261 * use in the {attribute uses} of the {base type definition}, there
13262 * must be an attribute use in the {attribute uses} of the complex
13263 * type definition itself whose {attribute declaration} has the same
13264 * {name}, {target namespace} and {type definition} as its attribute
13265 * declaration
13266 *
13267 * NOTE: This will be already satisfied by the way the attribute uses
13268 * are extended in xmlSchemaBuildAttributeValidation; thus this check
13269 * is not needed.
13270 */
13271
13272 /*
13273 * 1.3 If it has an {attribute wildcard}, the complex type definition
13274 * must also have one, and the base type definition's {attribute
13275 * wildcard}'s {namespace constraint} must be a subset of the complex
13276 * type definition's {attribute wildcard}'s {namespace constraint},
13277 * as defined by Wildcard Subset (§3.10.6).
13278 *
13279 * This is already checked in xmlSchemaBuildAttributeValidation; thus
13280 * this check is not needed.
13281 */
13282
13283 /*
13284 * 1.4 One of the following must be true:
13285 *
13286 * 1.4.1 The {content type} of the {base type definition} and the
13287 * {content type} of the complex type definition itself must be the same
13288 * simple type definition
13289 */
13290
13291
13292
13293 } else {
13294 /*
13295 * 2 If the {base type definition} is a simple type definition,
13296 * then all of the following must be true:
13297 */
13298 /*
13299 * 2.1 The {content type} must be the same simple type definition.
13300 */
13301 /*
13302 * 2.2 The {final} of the {base type definition} must not contain
13303 * extension
13304 */
13305 }
13306
13307}
13308
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013309static int
13310xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
13311 xmlSchemaTypePtr type)
13312{
13313 xmlSchemaTypePtr base, content;
13314 int OK = 0;
13315
13316 /*
13317 * TODO: Adjust the error codes here, as I used
13318 * XML_SCHEMAP_SRC_CT_1 only yet.
13319 */
13320 /*
13321 * Schema Representation Constraint:
13322 * Complex Type Definition Representation OK
13323 */
13324 base = type->baseType;
13325 if (base == NULL) {
13326 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL, NULL, type, NULL,
13327 "Internal error: xmlSchemaCheckSRCCT, '%s', no base type",
13328 type->name);
13329 return (-1);
13330 }
13331
13332 if (type->subtypes != NULL) {
13333 if (type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
13334 if IS_COMPLEX_TYPE(base) {
13335 /*
13336 * 1 If the <complexContent> alternative is chosen, the type definition
13337 * ·resolved· to by the ·actual value· of the base [attribute]
13338 * must be a complex type definition;
13339 */
13340 xmlSchemaPCustomErr(ctxt,
13341 XML_SCHEMAP_SRC_CT_1,
13342 NULL, type, NULL,
13343 "The base type is not a complex type", NULL);
13344 return (XML_SCHEMAP_SRC_CT_1);
13345 }
13346 } else if (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
13347
13348 if IS_SIMPLE_TYPE(base) {
13349 if (type->flags &
13350 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
13351 /*
13352 * 2.1.3 only if the <extension> alternative is also
13353 * chosen, a simple type definition.
13354 */
13355 /* TODO: Change error code to ..._SRC_CT_2_1_3. */
13356 xmlSchemaPCustomErr(ctxt,
13357 XML_SCHEMAP_SRC_CT_1,
13358 NULL, type, NULL,
13359 "A complex type (simple content) cannot restrict "
13360 "an other simple type",
13361 NULL);
13362 return (XML_SCHEMAP_SRC_CT_1);
13363 }
13364 OK = 1;
13365
13366 } else { /* if IS_SIMPLE_TYPE(base) */
13367 if (base->contentType = XML_SCHEMA_CONTENT_MIXED) {
13368 /*
13369 * 2.1.2 only if the <restriction> alternative is also
13370 * chosen, a complex type definition whose {content type}
13371 * is mixed and a particle emptyable.
13372 */
13373 /*
13374 * FIXME TODO: Check for *empiable particle* is missing.
13375 */
13376 if ((type->flags &
13377 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) == 0) {
13378 xmlSchemaPCustomErr(ctxt,
13379 XML_SCHEMAP_SRC_CT_1,
13380 NULL, type, NULL,
13381 "A complex type (simple content) cannot "
13382 "extend an other complex type which has a "
13383 "content type of: 'mixed' and emptiable particle",
13384 NULL);
13385 return (XML_SCHEMAP_SRC_CT_1);
13386 }
13387 /*
13388 * NOTE: This will be fired as well, if the base type
13389 * is *'anyType'*.
13390 * NOTE: type->subtypes->subtypes will be the
13391 * <restriction> item.
13392 */
13393 if (type->subtypes->subtypes == NULL) {
13394 /* Yes, this is paranoid programming. */
13395 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
13396 NULL, type, NULL,
13397 "Internal error: xmlSchemaCheckSRCCT, "
13398 "'%s', <simpleContent> has no <restriction>",
13399 type->name);
13400 return (-1);
13401 }
13402 /*
13403 * 2.2 If clause 2.1.2 above is satisfied, then there
13404 * must be a <simpleType> among the [children] of
13405 * <restriction>.
13406 */
13407 if (type->subtypes->subtypes->type !=
13408 XML_SCHEMA_TYPE_SIMPLE) {
13409 /* TODO: Change error code to ..._SRC_CT_2_2. */
13410 xmlSchemaPCustomErr(ctxt,
13411 XML_SCHEMAP_SRC_CT_1,
13412 NULL, type, NULL,
13413 "A <simpleType> is expected among the children "
13414 "of <restriction>", NULL);
13415 return (XML_SCHEMAP_SRC_CT_1);
13416 }
13417 OK = 1;
13418 } else { /* if (base->contentType = XML_SCHEMA_CONTENT_MIXED)*/
13419 /*
13420 * 2.1.1 a complex type definition whose {content type} is a
13421 * simple type definition;
13422 */
13423 if (base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) {
13424 xmlSchemaPCustomErr(ctxt,
13425 XML_SCHEMAP_SRC_CT_1,
13426 NULL, type, NULL,
13427 "A complex type (simple content) cannot "
13428 "be derived from the complex type '%s'",
13429 base->name);
13430 return (XML_SCHEMAP_SRC_CT_1);
13431 }
13432 content = base->contentTypeDef;
13433 if (content == NULL) {
13434 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
13435 NULL, type, NULL,
13436 "Internal error: xmlSchemaCheckSRCCT, "
13437 "'%s', base type has no content type",
13438 type->name);
13439 return (-1);
13440 }
13441 if (content->type != XML_SCHEMA_TYPE_SIMPLE) {
13442 xmlSchemaPCustomErr(ctxt,
13443 XML_SCHEMAP_SRC_CT_1,
13444 NULL, type, NULL,
13445 "A complex type (simple content) cannot "
13446 "be derived from the complex type '%s'",
13447 base->name);
13448 return (XML_SCHEMAP_SRC_CT_1);
13449 }
13450 }
13451 }
13452 }
13453 }
13454 /*
13455 * TODO: 3 The corresponding complex type definition component must
13456 * satisfy the conditions set out in Constraints on Complex Type
13457 * Definition Schema Components (§3.4.6);
13458 *
13459 * TODO: 4 If clause 2.2.1 or clause 2.2.2 in the correspondence specification
13460 * above for {attribute wildcard} is satisfied, the intensional
13461 * intersection must be expressible, as defined in Attribute Wildcard
13462 * Intersection (§3.10.6).
13463 */
13464
13465}
William M. Brack2f2a6632004-08-20 23:09:47 +000013466#endif
13467
Daniel Veillard01fa6152004-06-29 17:04:39 +000013468/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013469 * xmlSchemaGroupDefFixup:
13470 * @typeDecl: the schema model group definition
13471 * @ctxt: the schema parser context
13472 *
13473 * Fixes model group definitions.
13474 */
13475static void
13476xmlSchemaGroupDefFixup(xmlSchemaTypePtr group,
13477 xmlSchemaParserCtxtPtr ctxt,
13478 const xmlChar * name ATTRIBUTE_UNUSED)
13479{
13480 group->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
13481 if ((group->ref != NULL) && (group->subtypes == NULL)) {
13482 xmlSchemaTypePtr groupDef;
13483 /*
13484 * Resolve the reference.
13485 */
13486 groupDef = xmlSchemaGetGroup(ctxt->schema, group->ref,
13487 group->refNs);
13488 if (groupDef == NULL) {
13489 xmlSchemaPResCompAttrErr(ctxt,
13490 XML_SCHEMAP_SRC_RESOLVE,
13491 NULL, group, NULL,
13492 "ref", group->ref, group->refNs,
13493 XML_SCHEMA_TYPE_GROUP, NULL);
13494 return;
13495 }
13496 group->subtypes = groupDef;
13497 }
13498}
13499
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013500#if 0 /* Enable when the content type will be computed. */
13501static int
13502xmlSchemaComputeContentType(xmlSchemaParserCtxtPtr ctxt,
13503 xmlSchemaTypePtr type)
13504{
13505 xmlSchemaTypePtr base, res = NULL;
13506
13507 base = type->baseType;
13508 if (base == NULL) {
13509 xmlSchemaPCustomErr(ctxt,
13510 XML_SCHEMAP_INTERNAL,
13511 NULL, type, NULL,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000013512 "Internal error: xmlSchemaComputeContentType, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013513 "the complex type '%s' has no base type", type->name);
13514 return (-1);
13515 }
13516 if (IS_ANYTYPE(base) || (type->subtypes->type ==
13517 XML_SCHEMA_TYPE_COMPLEX_CONTENT)) {
13518 xmlSchemaTypePtr start;
13519 /*
13520 * Effective 'mixed'.
13521 */
13522 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
13523 type->contentType = XML_SCHEMA_CONTENT_MIXED;
13524 /*
13525 * Effective content.
13526 */
13527 if (IS_ANYTYPE(base))
13528 start = type;
13529 else
13530 start = type->subtypes;
13531
13532 } else { /* if XML_SCHEMA_TYPE_COMPLEX_CONTENT */
13533 xmlSchemaTypePtr baseContentItem;
13534
13535 /*
13536 * Complex type with simple content.
13537 */
13538 if IS_COMPLEX_TYPE(base) {
13539 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
13540 /*
13541 * Summary: a complex type (simple content) can *restrict*
13542 * a complex type with the following content type:
13543 * 1. 'mixed' and an emptiable particle
13544 * 2. simple type
13545 */
13546 if (base->contentType == XML_SCHEMA_CONTENT_MIXED) {
13547 /*
13548 * 2 if the {content type} of the base type is mixed and a
13549 * particle which is ·emptiable·,
13550 * [...]
13551 * then starting from the simple type definition
13552 * corresponding to the <simpleType> among the [children]
13553 * of <restriction> (**which must be present**)
13554 *
13555 * FIXME TODO: Handle "emptiable particle".
13556 */
13557 res = type->subtypes->subtypes;
13558 if (res == NULL) {
13559 xmlSchemaPCustomErr(ctxt,
13560 XML_SCHEMAP_INTERNAL,
13561 NULL, type, NULL,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000013562 "Internal error: xmlSchemaComputeContentType, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013563 "CT '%s' (restricting): <simpleContent> has no "
13564 "<restriction>",
13565 type->name);
13566 return (-1);
13567 }
13568
13569 res->subtypes;
13570 if (res == NULL) {
13571 xmlSchemaPCustomErr(ctxt,
13572 XML_SCHEMAP_INTERNAL,
13573 NULL, type, NULL,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000013574 "Internal error: xmlSchemaComputeContentType, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013575 "CT '%s' (restricting): <restriction> has no "
13576 "mandatory <simpleType>",
13577 type->name);
13578 return (-1);
13579 }
13580 } else {
13581 baseContentItem = base->contentTypeDef;
13582 if (baseContentItem == NULL) {
13583 xmlSchemaPCustomErr(ctxt,
13584 XML_SCHEMAP_INTERNAL,
13585 NULL, type, NULL,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000013586 "Internal error: xmlSchemaComputeContentType, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013587 "CT '%s' (restricting), the base type has no "
13588 "content type", type->name);
13589 return (-1);
13590 }
13591 if IS_SIMPLE_TYPE(baseContentItem) {
13592 /*
13593 * 1 If the base type is a complex type whose own
13594 * {content type} is a simple type and the <restriction>
13595 * alternative is chosen
13596 */
13597 /* type->subtypes->subtypes will be the restriction item.*/
13598 res = type->subtypes->subtypes;
13599 if (res == NULL) {
13600 xmlSchemaPCustomErr(ctxt,
13601 XML_SCHEMAP_INTERNAL,
13602 NULL, type, NULL,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000013603 "Internal error: xmlSchemaComputeContentType, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013604 "CT '%s' (restricting): <simpleType> has no "
13605 "<restriction>", type->name);
13606 return (-1);
13607 }
13608 /*
13609 * 1.1 the simple type definition corresponding to the
13610 * <simpleType> among the [children] of <restriction>if
13611 * there is one;
13612 */
13613 res = res->subtypes;
13614 if (res == NULL) {
13615 /*
13616 * 1.2 otherwise the {content type}
13617 * of the base type .
13618 */
13619 res = baseContentItem;
13620 }
13621 }
13622 }
13623 /*
13624 * SPECIAL TODO: If *restricting* the spec wants us to
13625 * create an *additional* simple type which restricts the
13626 * located simple type; we won't do this yet, and look how
13627 * far we get with it.
13628 */
13629 } else { /* if XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION */
13630 /*
13631 * Summary: a complex type (simple content) can *extend*
13632 * only a complex base with a simple type as content.
13633 */
13634 /*
13635 * 3 If the type definition ·resolved· to by the ·actual
13636 * value· of the base [attribute] is a complex type
13637 * definition (whose own {content type} *must be* a simple
13638 * type definition, see below) and the *<extension>*
13639 * alternative is chosen, then the {content type} of that
13640 * complex type definition;
13641 */
13642 res = base->contentTypeDef;
13643 if (res == NULL) {
13644 xmlSchemaPCustomErr(ctxt,
13645 XML_SCHEMAP_INTERNAL,
13646 NULL, type, NULL,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000013647 "Internal error: xmlSchemaComputeContentType, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013648 "CT '%s' (extending), the base type has no content "
13649 "type", type->name);
13650 return (-1);
13651 }
13652 if (! IS_SIMPLE_TYPE(res)) {
13653 xmlSchemaPCustomErr(ctxt,
13654 XML_SCHEMAP_INTERNAL,
13655 NULL, type, NULL,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000013656 "Internal error: xmlSchemaComputeContentType, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013657 "CT '%s' (extending), the content type of the "
13658 "base is not a simple type", type->name);
13659 return (-1);
13660 }
13661 }
13662 } else /* if IS_COMPLEX_TYPE(base) */
13663 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
13664 /*
13665 * 4 otherwise (the type definition ·resolved· to by the
13666 * ·actual value· of the base [attribute] is a simple type
13667 * definition and the <extension> alternative is chosen),
13668 * then that simple type definition.
13669 */
13670 res = base;
13671 }
13672 type->contentTypeDef = res;
13673 if (res == NULL) {
13674 xmlSchemaPCustomErr(ctxt,
13675 XML_SCHEMAP_INTERNAL,
13676 NULL, type, NULL,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000013677 "Internal error: xmlSchemaComputeContentType, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013678 "'%s', the content type could not be determined",
13679 type->name);
13680 return (-1);
13681 }
13682
13683 }
13684
13685}
13686#endif
13687
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013688/**
Daniel Veillard4255d502002-04-16 15:50:10 +000013689 * xmlSchemaTypeFixup:
13690 * @typeDecl: the schema type definition
13691 * @ctxt: the schema parser context
13692 *
13693 * Fixes the content model of the type.
13694 */
13695static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013696xmlSchemaTypeFixup(xmlSchemaTypePtr item,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013697 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000013698{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013699 xmlSchemaTypePtr ctxtType;
13700
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013701 if (item == NULL)
Daniel Veillard82bbbd42003-05-11 20:16:09 +000013702 return;
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013703 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000013704 * Do not fixup built-in types.
13705 */
13706 if (item->type == XML_SCHEMA_TYPE_BASIC)
13707 return;
13708 /*
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013709 * Do not allow the following types to be typefixed, prior to
13710 * the corresponding simple/complex types.
13711 */
13712 if (ctxt->ctxtType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013713 switch (item->type) {
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013714 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
13715 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
13716 case XML_SCHEMA_TYPE_UNION:
13717 case XML_SCHEMA_TYPE_RESTRICTION:
13718 case XML_SCHEMA_TYPE_EXTENSION:
13719 return;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013720 default:
13721 break;
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013722 }
13723 }
Daniel Veillard4255d502002-04-16 15:50:10 +000013724 if (name == NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013725 name = item->name;
13726 if (item->contentType == XML_SCHEMA_CONTENT_UNKNOWN) {
13727 switch (item->type) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013728 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013729 if (item->subtypes != NULL) {
13730 if (item->subtypes->contentType ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013731 XML_SCHEMA_CONTENT_UNKNOWN) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013732 xmlSchemaTypeFixup(item->subtypes, ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013733 NULL);
13734 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013735 item->contentType =
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013736 XML_SCHEMA_CONTENT_SIMPLE;
13737 /* item->subtypes->contentType; */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013738 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013739 break;
13740 }
13741 case XML_SCHEMA_TYPE_RESTRICTION:{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013742 xmlSchemaTypePtr base = NULL;
13743
13744 ctxt->ctxtType->flags |=
13745 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013746 if (item->baseType != NULL)
13747 base = item->baseType;
13748 else if (item->base != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013749 base =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013750 xmlSchemaGetType(ctxt->schema, item->base,
13751 item->baseNs);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013752 if (base == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013753 xmlSchemaPResCompAttrErr(ctxt,
13754 XML_SCHEMAP_SRC_RESOLVE,
William M. Brack2f2a6632004-08-20 23:09:47 +000013755 NULL, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013756 (xmlNodePtr) xmlSchemaGetPropNode(item->node, "base"),
13757 "base", item->base, item->baseNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013758 XML_SCHEMA_TYPE_BASIC, "type definition");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013759 } else if (base->contentType ==
Daniel Veillard3646d642004-06-02 19:19:14 +000013760 XML_SCHEMA_CONTENT_UNKNOWN) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013761 xmlSchemaTypeFixup(base, ctxt, NULL);
13762 }
William M. Brack2f2a6632004-08-20 23:09:47 +000013763 }
13764 ctxt->ctxtType->baseType = base;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013765 if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX) {
13766 /*
13767 * ComplexType restriction.
William M. Brack2f2a6632004-08-20 23:09:47 +000013768 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013769 /*
13770 * Content type.
13771 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013772 if (item->subtypes == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013773 /* 1.1.1 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013774 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
13775 else if ((item->subtypes->subtypes == NULL) &&
13776 ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013777 XML_SCHEMA_TYPE_ALL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013778 || (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013779 XML_SCHEMA_TYPE_SEQUENCE)))
13780 /* 1.1.2 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013781 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
13782 else if ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013783 XML_SCHEMA_TYPE_CHOICE)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013784 && (item->subtypes->subtypes == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +000013785 /* 1.1.3 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013786 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013787 else {
13788 /* 1.2 and 2.X are applied at the other layer */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013789 item->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000013790 XML_SCHEMA_CONTENT_ELEMENTS;
13791 }
13792 } else {
13793 /*
13794 * SimpleType restriction.
13795 */
William M. Brack2f2a6632004-08-20 23:09:47 +000013796 /* TODO: Nothing? */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013797 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013798 break;
13799 }
13800 case XML_SCHEMA_TYPE_EXTENSION:{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013801 xmlSchemaTypePtr base = NULL;
13802 xmlSchemaContentType explicitContentType;
13803
13804 /*
13805 * An extension does exist on a complexType only.
13806 */
13807 ctxt->ctxtType->flags |=
13808 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013809 if (item->recurse) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013810 /* TODO: The word "recursive" should be changed to "circular" here. */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013811 xmlSchemaPCustomErr(ctxt,
13812 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013813 NULL, item, item->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013814 "This item is circular", NULL);
Daniel Veillard2582a332004-04-18 19:49:46 +000013815 return;
13816 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013817 if (item->base != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013818 base =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013819 xmlSchemaGetType(ctxt->schema, item->base,
13820 item->baseNs);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013821 if (base == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013822 xmlSchemaPResCompAttrErr(ctxt,
13823 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013824 NULL, item, item->node,
13825 "base", item->base, item->baseNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013826 XML_SCHEMA_TYPE_BASIC, "type definition");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013827 } else if (base->contentType ==
13828 XML_SCHEMA_CONTENT_UNKNOWN) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013829 item->recurse = 1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013830 xmlSchemaTypeFixup(base, ctxt, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013831 item->recurse = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013832 }
13833 /*
13834 * The type definition ·resolved· to by the ·actual
13835 * value· of the base [attribute]
13836 */
13837 ctxt->ctxtType->baseType = base;
13838 /*
13839 * TODO: This one is still needed for computation of
13840 * the content model by xmlSchemaBuildAContentModel.
13841 * Try to get rid of it.
13842 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013843 item->baseType = base;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013844 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013845 if ((item->subtypes != NULL) &&
13846 (item->subtypes->contentType == XML_SCHEMA_CONTENT_UNKNOWN))
13847 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013848
13849 explicitContentType = XML_SCHEMA_CONTENT_ELEMENTS;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013850 if (item->subtypes == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013851 /* 1.1.1 */
13852 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013853 else if ((item->subtypes->subtypes == NULL) &&
13854 ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013855 XML_SCHEMA_TYPE_ALL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013856 || (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013857 XML_SCHEMA_TYPE_SEQUENCE)))
13858 /* 1.1.2 */
13859 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013860 else if ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013861 XML_SCHEMA_TYPE_CHOICE)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013862 && (item->subtypes->subtypes == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +000013863 /* 1.1.3 */
13864 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
13865 if (base != NULL) {
13866 /* It will be reported later, if the base is missing. */
13867 if (explicitContentType == XML_SCHEMA_CONTENT_EMPTY) {
13868 /* 2.1 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013869 item->contentType = base->contentType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013870 } else if (base->contentType ==
13871 XML_SCHEMA_CONTENT_EMPTY) {
13872 /* 2.2 imbitable ! */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013873 item->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000013874 XML_SCHEMA_CONTENT_ELEMENTS;
13875 } else {
13876 /* 2.3 imbitable pareil ! */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013877 item->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000013878 XML_SCHEMA_CONTENT_ELEMENTS;
13879 }
13880 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013881 break;
13882 }
13883 case XML_SCHEMA_TYPE_COMPLEX:{
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013884 ctxtType = ctxt->ctxtType;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013885 ctxt->ctxtType = item;
13886 /*
13887 * Start with an empty content-type type.
13888 */
13889 if (item->subtypes == NULL)
13890 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
13891
13892 if ((item->subtypes == NULL) ||
13893 ((item->subtypes->type !=
Daniel Veillard01fa6152004-06-29 17:04:39 +000013894 XML_SCHEMA_TYPE_SIMPLE_CONTENT) &&
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013895 (item->subtypes->type !=
Daniel Veillard01fa6152004-06-29 17:04:39 +000013896 XML_SCHEMA_TYPE_COMPLEX_CONTENT))) {
13897 /*
13898 * This case is understood as shorthand for complex
13899 * content restricting the ur-type definition, and
13900 * the details of the mappings should be modified as
13901 * necessary.
13902 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013903 item->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
13904 item->flags |=
Daniel Veillard01fa6152004-06-29 17:04:39 +000013905 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013906 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013907 * Assume that we inherit the content-type type
13908 * from 'anyType', which is 'mixed' and a particle
13909 * emptiable.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013910 */
13911 item->contentType = item->baseType->contentType;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013912 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013913 /*
13914 * Fixup the sub components.
13915 */
13916 if ((item->subtypes != NULL) &&
13917 (item->subtypes->contentType ==
13918 XML_SCHEMA_CONTENT_UNKNOWN)) {
13919 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013920 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013921 if (item->flags & XML_SCHEMAS_TYPE_MIXED) {
13922 item->contentType = XML_SCHEMA_CONTENT_MIXED;
13923 } else if (item->subtypes != NULL) {
13924 /*
13925 * Use the content-type type of the model groups
13926 * defined, if 'mixed' is not set. If 'mixed' is set
13927 * it will expand the content-type by allowing character
13928 * content to appear.
13929 */
13930 item->contentType =
13931 item->subtypes->contentType;
13932 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013933
13934 /*
13935 * Some optimization for validation:
13936 * If there are no facets beside the "whitespace" facet,
13937 * then a value needs not to checked against against a
13938 * facet, thus no computed value is needed.
13939 * TODO URGENT: This is just a workaround, we need to
13940 * introduce the correct usage of contentType to store the
13941 * facets in!
13942 */
Daniel Veillardd3210bc2005-01-28 17:56:39 +000013943 if ((item->baseType != NULL) &&
13944 (item->baseType->flags &
13945 XML_SCHEMAS_TYPE_FACETSNEEDVALUE))
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013946 item->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
13947 else {
13948 xmlSchemaFacetLinkPtr cur;
13949
13950 for (cur = item->facetSet; cur != NULL;
13951 cur = cur->next) {
13952 if (cur->facet->type != XML_SCHEMA_FACET_WHITESPACE) {
13953 item->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
13954 break;
13955 }
13956 }
13957 }
13958
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013959 xmlSchemaBuildAttributeValidation(ctxt, item);
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000013960 xmlSchemaCheckDefaults(item, ctxt, item->name);
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013961 ctxt->ctxtType = ctxtType;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013962 break;
13963 }
13964 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013965 if (item->subtypes == NULL) {
13966 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
13967 if (item->flags & XML_SCHEMAS_TYPE_MIXED)
13968 item->contentType =
Daniel Veillard1aefc862004-03-04 11:40:48 +000013969 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013970 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013971 if (item->flags & XML_SCHEMAS_TYPE_MIXED) {
13972 item->contentType =
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013973 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillard3646d642004-06-02 19:19:14 +000013974 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013975 xmlSchemaTypeFixup(item->subtypes, ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013976 NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013977 if (item->subtypes != NULL)
13978 item->contentType =
13979 item->subtypes->contentType;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013980 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013981 /*
13982 * Removed due to implementation of the build of attribute uses.
13983 */
13984 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013985 if (item->attributes == NULL)
13986 item->attributes =
13987 item->subtypes->attributes;
Daniel Veillard3646d642004-06-02 19:19:14 +000013988 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013989 }
13990 break;
13991 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013992 case XML_SCHEMA_TYPE_SIMPLE:
13993 /*
13994 * Simple Type Definition Schema Component
13995 *
13996 */
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013997 ctxtType = ctxt->ctxtType;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013998 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
13999 if (item->subtypes->contentType ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000014000 XML_SCHEMA_CONTENT_UNKNOWN) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014001 ctxt->ctxtType = item;
14002 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014003 }
14004 /* Fixup base type */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014005 if ((item->baseType != NULL) &&
14006 (item->baseType->contentType ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000014007 XML_SCHEMA_CONTENT_UNKNOWN)) {
14008 /* OPTIMIZE: Actually this one will never by hit, since
14009 * the base type is already type-fixed in <restriction>.
14010 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014011 ctxt->ctxtType = item;
14012 xmlSchemaTypeFixup(item->baseType, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014013 }
14014 /* Base type:
14015 * 2 If the <list> or <union> alternative is chosen,
14016 * then the ·simple ur-type definition·.
14017 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014018 if (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000014019 XML_SCHEMA_TYPE_LIST) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014020 item->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
14021 item->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
14022 } else if (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000014023 XML_SCHEMA_TYPE_UNION) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014024 item->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
14025 item->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
14026 } else if (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000014027 XML_SCHEMA_TYPE_RESTRICTION) {
14028 xmlSchemaFacetLinkPtr facet, cur, last = NULL;
14029
14030 /*
14031 * Variety
14032 * If the <restriction> alternative is chosen, then the
14033 * {variety} of the {base type definition}.
14034 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014035 if (item->baseType != NULL) {
14036 if (item->baseType->flags &
Daniel Veillard01fa6152004-06-29 17:04:39 +000014037 XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014038 item->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
14039 else if (item->baseType->flags &
Daniel Veillard01fa6152004-06-29 17:04:39 +000014040 XML_SCHEMAS_TYPE_VARIETY_LIST)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014041 item->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
14042 else if (item->baseType->flags &
Daniel Veillard01fa6152004-06-29 17:04:39 +000014043 XML_SCHEMAS_TYPE_VARIETY_UNION)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014044 item->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014045 /*
14046 * Schema Component Constraint: Simple Type Restriction
14047 * (Facets)
14048 * NOTE: Satisfaction of 1 and 2 arise from the fixup
14049 * applied beforehand.
14050 *
14051 * 3 The {facets} of R are the union of S and the {facets}
14052 * of B, eliminating duplicates. To eliminate duplicates,
14053 * when a facet of the same kind occurs in both S and the
14054 * {facets} of B, the one in the {facets} of B is not
14055 * included, with the exception of enumeration and pattern
14056 * facets, for which multiple occurrences with distinct values
14057 * are allowed.
14058 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014059 if (item->baseType->facetSet != NULL) {
14060 last = item->facetSet;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014061 if (last != NULL)
14062 while (last->next != NULL)
14063 last = last->next;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000014064 cur = item->baseType->facetSet;
14065 for (; cur != NULL; cur = cur->next) {
14066 /*
14067 * Base patterns won't be add here:
14068 * they are ORed in a type and
14069 * ANDed in derived types. This will
14070 * happed at validation level by
14071 * walking the base axis of the type.
14072 */
14073 if (cur->facet->type ==
14074 XML_SCHEMA_FACET_PATTERN)
14075 continue;
14076 facet = NULL;
14077 if ((item->facetSet != NULL) &&
14078 /* REMOVED: a check for
14079 * XML_SCHEMA_FACET_PATTERN was already
14080 * performed above.
14081
14082 * (cur->facet->type !=
14083 * XML_SCHEMA_FACET_PATTERN) &&
Daniel Veillard01fa6152004-06-29 17:04:39 +000014084 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000014085 (cur->facet->type !=
14086 XML_SCHEMA_FACET_ENUMERATION)) {
14087 facet = item->facetSet;
14088 do {
14089 if (cur->facet->type ==
14090 facet->facet->type)
14091 break;
14092 facet = facet->next;
14093 } while (facet != NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014094 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000014095 if (facet == NULL) {
14096 facet = (xmlSchemaFacetLinkPtr)
14097 xmlMalloc(sizeof(xmlSchemaFacetLink));
14098 if (facet == NULL) {
14099 xmlSchemaPErrMemory(ctxt,
14100 "fixing simpleType", NULL);
14101 return;
14102 }
14103 /*
14104 * The facets are not copied but referenced
14105 * via the facet link.
14106 */
14107 facet->facet = cur->facet;
14108 facet->next = NULL;
14109 if (last == NULL)
14110 item->facetSet = facet;
14111 else
14112 last->next = facet;
14113 last = facet;
14114 }
14115 }
14116 }
14117 /*
14118 * Some optimization for validation:
14119 * If there are no facets beside the "whitespace" facet,
14120 * then a value needs not to checked against against a
14121 * facet, thus no computed value is needed.
14122 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000014123 if (item->baseType->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000014124 item->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
14125 else {
14126 for (cur = item->facetSet; cur != NULL;
14127 cur = cur->next) {
14128 if (cur->facet->type != XML_SCHEMA_FACET_WHITESPACE) {
14129 item->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
14130 break;
14131 }
14132 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014133 }
14134 }
14135 }
14136 /*
14137 * Check constraints.
14138 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014139 xmlSchemaCheckSRCSimpleType(ctxt, item);
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000014140 xmlSchemaCheckDefaults(item, ctxt, item->name);
Daniel Veillard4e5d6652004-06-29 21:01:12 +000014141 ctxt->ctxtType = ctxtType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014142 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014143 case XML_SCHEMA_TYPE_SEQUENCE:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014144 case XML_SCHEMA_TYPE_ALL:
14145 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014146 item->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014147 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014148 case XML_SCHEMA_TYPE_GROUP:
14149 /*
14150 * TODO: Handling was moved to xmlSchemaGroupDefFixup.
14151 */
14152 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014153 case XML_SCHEMA_TYPE_LIST:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014154 xmlSchemaParseListRefFixup(item, ctxt);
14155 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014156 break;
14157 case XML_SCHEMA_TYPE_UNION:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014158 xmlSchemaParseUnionRefCheck(item, ctxt);
14159 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014160 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014161 case XML_SCHEMA_TYPE_BASIC:
14162 case XML_SCHEMA_TYPE_ANY:
14163 case XML_SCHEMA_TYPE_FACET:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014164 case XML_SCHEMA_TYPE_UR:
14165 case XML_SCHEMA_TYPE_ELEMENT:
14166 case XML_SCHEMA_TYPE_ATTRIBUTE:
14167 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
William M. Brack29aa7722004-05-12 00:27:56 +000014168 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014169 case XML_SCHEMA_TYPE_NOTATION:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014170 case XML_SCHEMA_FACET_MININCLUSIVE:
14171 case XML_SCHEMA_FACET_MINEXCLUSIVE:
14172 case XML_SCHEMA_FACET_MAXINCLUSIVE:
14173 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
14174 case XML_SCHEMA_FACET_TOTALDIGITS:
14175 case XML_SCHEMA_FACET_FRACTIONDIGITS:
14176 case XML_SCHEMA_FACET_PATTERN:
14177 case XML_SCHEMA_FACET_ENUMERATION:
14178 case XML_SCHEMA_FACET_WHITESPACE:
14179 case XML_SCHEMA_FACET_LENGTH:
14180 case XML_SCHEMA_FACET_MAXLENGTH:
14181 case XML_SCHEMA_FACET_MINLENGTH:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014182 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
14183 if (item->subtypes != NULL)
14184 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014185 break;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000014186 case XML_SCHEMA_TYPE_IDC_UNIQUE:
14187 case XML_SCHEMA_TYPE_IDC_KEY:
14188 case XML_SCHEMA_TYPE_IDC_KEYREF:
14189 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014190 }
14191 }
Daniel Veillard8651f532002-04-17 09:06:27 +000014192#ifdef DEBUG_TYPE
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014193 if (item->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014194 xmlGenericError(xmlGenericErrorContext,
14195 "Type of %s : %s:%d :", name,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014196 item->node->doc->URL,
14197 xmlGetLineNo(item->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +000014198 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014199 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000014200 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014201 switch (item->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014202 case XML_SCHEMA_CONTENT_SIMPLE:
14203 xmlGenericError(xmlGenericErrorContext, "simple\n");
14204 break;
14205 case XML_SCHEMA_CONTENT_ELEMENTS:
14206 xmlGenericError(xmlGenericErrorContext, "elements\n");
14207 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000014208 case XML_SCHEMA_CONTENT_UNKNOWN:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014209 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
14210 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000014211 case XML_SCHEMA_CONTENT_EMPTY:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014212 xmlGenericError(xmlGenericErrorContext, "empty\n");
14213 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000014214 case XML_SCHEMA_CONTENT_MIXED:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014215 xmlGenericError(xmlGenericErrorContext, "mixed\n");
14216 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014217 /* Removed, since not used. */
14218 /*
Daniel Veillard8651f532002-04-17 09:06:27 +000014219 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014220 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
14221 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014222 */
Daniel Veillard8651f532002-04-17 09:06:27 +000014223 case XML_SCHEMA_CONTENT_BASIC:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014224 xmlGenericError(xmlGenericErrorContext, "basic\n");
14225 break;
14226 default:
14227 xmlGenericError(xmlGenericErrorContext,
14228 "not registered !!!\n");
14229 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000014230 }
14231#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000014232}
14233
14234/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000014235 * xmlSchemaCheckFacet:
14236 * @facet: the facet
14237 * @typeDecl: the schema type definition
14238 * @ctxt: the schema parser context or NULL
14239 * @name: name of the type
14240 *
14241 * Checks the default values types, especially for facets
14242 *
14243 * Returns 0 if okay or -1 in cae of error
14244 */
14245int
14246xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014247 xmlSchemaTypePtr typeDecl,
14248 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000014249{
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +000014250 xmlSchemaTypePtr nonNegativeIntegerType = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014251 int ret = 0, reuseValCtxt = 0;
14252
Daniel Veillardce682bc2004-11-05 17:22:25 +000014253 if ((facet == NULL) || (typeDecl == NULL))
14254 return(-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014255 /*
14256 * TODO: will the parser context be given if used from
14257 * the relaxNG module?
14258 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000014259
14260 if (nonNegativeIntegerType == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014261 nonNegativeIntegerType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000014262 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000014263 }
14264 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014265 case XML_SCHEMA_FACET_MININCLUSIVE:
14266 case XML_SCHEMA_FACET_MINEXCLUSIVE:
14267 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardf4b05d02004-07-05 13:10:37 +000014268 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
14269 case XML_SCHEMA_FACET_ENUMERATION: {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014270 /*
14271 * Okay we need to validate the value
14272 * at that point.
14273 */
14274 xmlSchemaValidCtxtPtr vctxt;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014275 xmlSchemaTypePtr base;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000014276
14277 /* 4.3.5.5 Constraints on enumeration Schema Components
14278 * Schema Component Constraint: enumeration valid restriction
14279 * It is an ·error· if any member of {value} is not in the
14280 * ·value space· of {base type definition}.
14281 *
14282 * minInclusive, maxInclusive, minExclusive, maxExclusive:
14283 * The value ·must· be in the
14284 * ·value space· of the ·base type·.
14285 */
14286 /*
14287 * This function is intended to deliver a compiled value
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000014288 * on the facet. In this implementation of XML Schemata the
14289 * type holding a facet, won't be a built-in type.
14290 * Thus to ensure that other API
Daniel Veillardf4b05d02004-07-05 13:10:37 +000014291 * calls (relaxng) do work, if the given type is a built-in
14292 * type, we will assume that the given built-in type *is
14293 * already* the base type.
14294 */
14295 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
14296 base = typeDecl->baseType;
14297 if (base == NULL) {
14298 xmlSchemaPErr(ctxt, typeDecl->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014299 XML_SCHEMAP_INTERNAL,
Daniel Veillardf4b05d02004-07-05 13:10:37 +000014300 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000014301 "the type '%s' has no base type.\n",
Daniel Veillardf4b05d02004-07-05 13:10:37 +000014302 typeDecl->name, NULL);
14303 return (-1);
14304 }
14305 } else
14306 base = typeDecl;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014307 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014308 * This avoids perseverative creation of the
14309 * validation context if a parser context is
14310 * used.
Daniel Veillard01fa6152004-06-29 17:04:39 +000014311 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014312 if (ctxt != NULL) {
14313 reuseValCtxt = 1;
14314 if (ctxt->vctxt == NULL) {
14315 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
14316 return (-1);
14317 }
14318 vctxt = ctxt->vctxt;
14319 } else {
14320 vctxt = xmlSchemaNewValidCtxt(NULL);
14321 if (vctxt == NULL) {
14322 xmlSchemaPErr(ctxt, typeDecl->node,
14323 XML_SCHEMAP_INTERNAL,
14324 "Internal error: xmlSchemaCheckFacet, "
14325 "creating a new validation context.\n",
14326 NULL, NULL);
14327 return (-1);
14328 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014329 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014330
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014331 vctxt->node = facet->node;
14332 vctxt->cur = NULL;
14333 /*
14334 * NOTE: This call does not check the content nodes,
14335 * since they are not available:
14336 * facet->node is just the node holding the facet
14337 * definition, *not* the attribute holding the *value*
14338 * of the facet.
14339 */
14340 ret = xmlSchemaValidateSimpleTypeValue(vctxt, base,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000014341 facet->value, 0, 1, 1, 0);
Daniel Veillardf4b05d02004-07-05 13:10:37 +000014342 if (ret > 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014343 /* error code */
14344 if (ctxt != NULL) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000014345 xmlChar *str = NULL;
14346
14347 xmlSchemaPCustomErrExt(ctxt,
14348 XML_SCHEMAP_INVALID_FACET_VALUE,
14349 NULL, (xmlSchemaTypePtr) facet, facet->node,
14350 "The value '%s' of the facet does not validate "
14351 "against the base type '%s'",
14352 facet->value,
14353 xmlSchemaFormatQName(&str,
14354 base->targetNamespace, base->name), NULL);
14355 FREE_AND_NULL(str)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014356 }
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000014357 /* xmlSchemaFacetTypeToString(facet->type), */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014358 ret = -1;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000014359 } else if (ret < 0) {
14360 xmlSchemaPErrExt(ctxt, facet->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014361 XML_SCHEMAP_INTERNAL,
Daniel Veillardf4b05d02004-07-05 13:10:37 +000014362 NULL, NULL, NULL,
14363 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000014364 "failed to validate the value '%s' name of the "
14365 "facet '%s' against the base type '%s'.\n",
Daniel Veillardf4b05d02004-07-05 13:10:37 +000014366 facet->value,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014367 xmlSchemaFacetTypeToString(facet->type),
Daniel Veillardf4b05d02004-07-05 13:10:37 +000014368 base->name, NULL, NULL);
14369 ret = -1;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000014370 } else {
14371 if (vctxt->value != NULL) {
14372 facet->val = vctxt->value;
14373 vctxt->value = NULL;
14374 } else {
14375 xmlChar *str;
14376 /*
14377 * Ensure computed values even for type string.
14378 * TODO OPTIMIZE MEMORY: The value will be hold twice,
14379 * by the facet->value and by the computed value.
14380 */
14381 str = xmlStrdup(facet->value);
14382 if (xmlSchemaPostCreateVal(vctxt, typeDecl,
14383 BAD_CAST str, &(facet->val)) == -1) {
14384 FREE_AND_NULL(str)
14385 xmlSchemaPErr(ctxt, typeDecl->node,
14386 XML_SCHEMAP_INTERNAL,
14387 "Internal error: xmlSchemaCheckFacet, "
14388 "post-creating a computed value.\n",
14389 NULL, NULL);
14390 /* Note that we don't return a failure yet.*/
14391 }
14392 }
14393 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014394 if (reuseValCtxt == 0)
14395 xmlSchemaFreeValidCtxt(vctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014396 break;
14397 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014398 case XML_SCHEMA_FACET_PATTERN:
14399 facet->regexp = xmlRegexpCompile(facet->value);
14400 if (facet->regexp == NULL) {
14401 xmlSchemaPErr(ctxt, typeDecl->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014402 XML_SCHEMAP_REGEXP_INVALID,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014403 "Type definition '%s': The value '%s' of the "
14404 "facet 'pattern' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000014405 name, facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014406 ret = -1;
14407 }
14408 break;
14409 case XML_SCHEMA_FACET_TOTALDIGITS:
14410 case XML_SCHEMA_FACET_FRACTIONDIGITS:
14411 case XML_SCHEMA_FACET_LENGTH:
14412 case XML_SCHEMA_FACET_MAXLENGTH:
14413 case XML_SCHEMA_FACET_MINLENGTH:{
14414 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000014415
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014416 tmp =
14417 xmlSchemaValidatePredefinedType(nonNegativeIntegerType,
14418 facet->value,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +000014419 &(facet->val));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014420 if (tmp != 0) {
14421 /* error code */
14422 if (ctxt != NULL) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000014423 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014424 XML_SCHEMAP_INVALID_FACET_VALUE,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000014425 NULL, (xmlSchemaTypePtr) facet, facet->node,
14426 "The value '%s' of the facet is not a valid "
14427 "nonNegativeInteger", facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014428 }
14429 ret = -1;
14430 }
14431 break;
14432 }
14433 case XML_SCHEMA_FACET_WHITESPACE:{
14434 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
14435 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
14436 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
14437 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
14438 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
14439 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
14440 } else {
14441 if (ctxt != NULL) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000014442 /* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */
14443 xmlSchemaPCustomErr(ctxt,
14444 XML_SCHEMAP_INVALID_FACET_VALUE,
14445 NULL, (xmlSchemaTypePtr) facet, facet->node,
14446 "The value '%s' of the facet is not a valid",
14447 facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014448 }
14449 ret = -1;
14450 }
14451 }
14452 default:
14453 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000014454 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014455 return (ret);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000014456}
14457
14458/**
Daniel Veillard4255d502002-04-16 15:50:10 +000014459 * xmlSchemaCheckDefaults:
14460 * @typeDecl: the schema type definition
14461 * @ctxt: the schema parser context
14462 *
14463 * Checks the default values types, especially for facets
14464 */
14465static void
14466xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014467 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000014468{
Daniel Veillard4255d502002-04-16 15:50:10 +000014469 if (name == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014470 name = typeDecl->name;
14471 /*
14472 * NOTE: It is intended to use the facets list, instead
14473 * of facetSet.
14474 */
14475 if (typeDecl->facets != NULL) {
14476 xmlSchemaFacetPtr facet = typeDecl->facets;
14477
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014478 /*
14479 * Temporarily assign the "schema" to the validation context
14480 * of the parser context. This is needed for NOTATION validation.
14481 */
14482 if (ctxt->vctxt == NULL) {
14483 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
14484 return;
14485 }
14486 ctxt->vctxt->schema = ctxt->schema;
14487
Daniel Veillard01fa6152004-06-29 17:04:39 +000014488 while (facet != NULL) {
14489 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
14490 facet = facet->next;
14491 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000014492
14493 ctxt->vctxt->schema = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014494 }
Daniel Veillard4255d502002-04-16 15:50:10 +000014495}
14496
14497/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014498 * xmlSchemaGetCircModelGrDefRef:
14499 * @ctxtGr: the searched model group
14500 * @list: the list of model groups to be processed
14501 *
14502 * This one is intended to be used by
14503 * xmlSchemaCheckGroupDefCircular only.
14504 *
14505 * Returns the circular model group definition reference, otherwise NULL.
14506 */
14507static xmlSchemaTypePtr
14508xmlSchemaGetCircModelGrDefRef(xmlSchemaTypePtr ctxtGrDef,
14509 xmlSchemaTypePtr gr)
14510{
14511 xmlSchemaTypePtr circ = NULL;
14512 int marked;
14513 /*
14514 * We will search for an model group reference which
14515 * references the context model group definition.
14516 */
14517 while (gr != NULL) {
14518 if (((gr->type == XML_SCHEMA_TYPE_GROUP) ||
14519 (gr->type == XML_SCHEMA_TYPE_ALL) ||
14520 (gr->type == XML_SCHEMA_TYPE_SEQUENCE) ||
14521 (gr->type == XML_SCHEMA_TYPE_CHOICE)) &&
14522 (gr->subtypes != NULL)) {
14523 marked = 0;
14524 if ((gr->type == XML_SCHEMA_TYPE_GROUP) &&
14525 (gr->ref != NULL)) {
14526 if (gr->subtypes == ctxtGrDef)
14527 return (gr);
14528 else if (gr->subtypes->flags &
14529 XML_SCHEMAS_TYPE_MARKED) {
14530 gr = gr->next;
14531 continue;
14532 } else {
14533 /*
14534 * Mark to avoid infinite recursion on
14535 * circular references not yet examined.
14536 */
14537 gr->subtypes->flags |= XML_SCHEMAS_TYPE_MARKED;
14538 marked = 1;
14539 }
14540 if (gr->subtypes->subtypes != NULL)
14541 circ = xmlSchemaGetCircModelGrDefRef(ctxtGrDef,
14542 gr->subtypes->subtypes);
14543 /*
14544 * Unmark the visited model group definition.
14545 */
14546 if (marked)
14547 gr->subtypes->flags ^= XML_SCHEMAS_TYPE_MARKED;
14548 if (circ != NULL)
14549 return (circ);
14550 } else {
14551 circ = xmlSchemaGetCircModelGrDefRef(ctxtGrDef,
14552 (xmlSchemaTypePtr) gr->subtypes);
14553 if (circ != NULL)
14554 return (circ);
14555 }
14556
14557 }
14558 gr = gr->next;
14559 }
14560 return (NULL);
14561}
14562
14563/**
14564 * xmlSchemaCheckGroupDefCircular:
14565 * attrGr: the model group definition
14566 * @ctxt: the parser context
14567 * @name: the name
14568 *
14569 * Checks for circular references to model group definitions.
14570 */
14571static void
14572xmlSchemaCheckGroupDefCircular(xmlSchemaTypePtr modelGrDef,
14573 xmlSchemaParserCtxtPtr ctxt,
14574 const xmlChar * name ATTRIBUTE_UNUSED)
14575{
14576 /*
14577 * Schema Component Constraint: Model Group Correct
14578 * 2 Circular groups are disallowed. That is, within the {particles}
14579 * of a group there must not be at any depth a particle whose {term}
14580 * is the group itself.
14581 */
14582 /*
14583 * NOTE: "gr->subtypes" holds the referenced group.
14584 */
14585 if ((modelGrDef->type != XML_SCHEMA_TYPE_GROUP) ||
14586 ((modelGrDef->flags & XML_SCHEMAS_TYPE_GLOBAL) == 0) ||
14587 (modelGrDef->subtypes == NULL))
14588 return;
14589 else {
14590 xmlSchemaTypePtr circ;
14591
14592 circ = xmlSchemaGetCircModelGrDefRef(modelGrDef, modelGrDef->subtypes);
14593 if (circ != NULL) {
14594 /*
14595 * TODO: Report the referenced attr group as QName.
14596 */
14597 xmlSchemaPCustomErr(ctxt,
14598 XML_SCHEMAP_MG_PROPS_CORRECT_2,
14599 NULL, NULL, circ->node,
14600 "Circular reference to the model group definition '%s' "
14601 "defined", modelGrDef->name);
14602 /*
14603 * NOTE: We will cut the reference to avoid further
14604 * confusion of the processor.
14605 * TODO: SPEC: Does the spec define how to process here?
14606 */
14607 circ->subtypes = NULL;
14608 }
14609 }
14610}
14611
14612
14613/**
14614 * xmlSchemaGetCircAttrGrRef:
14615 * @ctxtGr: the searched attribute group
14616 * @attr: the current attribute list to be processed
14617 *
14618 * This one is intended to be used by
14619 * xmlSchemaCheckSRCAttributeGroupCircular only.
14620 *
14621 * Returns the circular attribute grou reference, otherwise NULL.
14622 */
14623static xmlSchemaAttributeGroupPtr
14624xmlSchemaGetCircAttrGrRef(xmlSchemaAttributeGroupPtr ctxtGr,
14625 xmlSchemaAttributePtr attr)
14626{
14627 xmlSchemaAttributeGroupPtr circ = NULL, gr;
14628 int marked;
14629 /*
14630 * We will search for an attribute group reference which
14631 * references the context attribute group.
14632 */
14633 while (attr != NULL) {
14634 marked = 0;
14635 if (attr->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
14636 gr = (xmlSchemaAttributeGroupPtr) attr;
14637 if (gr->refItem != NULL) {
14638 if (gr->refItem == ctxtGr)
14639 return (gr);
14640 else if (gr->refItem->flags &
14641 XML_SCHEMAS_ATTRGROUP_MARKED) {
14642 attr = attr->next;
14643 continue;
14644 } else {
14645 /*
14646 * Mark as visited to avoid infinite recursion on
14647 * circular references not yet examined.
14648 */
14649 gr->refItem->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
14650 marked = 1;
14651 }
14652 }
14653 if (gr->attributes != NULL)
14654 circ = xmlSchemaGetCircAttrGrRef(ctxtGr, gr->attributes);
14655 /*
14656 * Unmark the visited group's attributes.
14657 */
14658 if (marked)
14659 gr->refItem->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
14660 if (circ != NULL)
14661 return (circ);
14662 }
14663 attr = attr->next;
14664 }
14665 return (NULL);
14666}
14667
14668/**
14669 * xmlSchemaCheckSRCAttributeGroupCircular:
14670 * attrGr: the attribute group definition
14671 * @ctxt: the parser context
14672 * @name: the name
14673 *
14674 * Checks for circular references of attribute groups.
14675 */
14676static void
14677xmlSchemaCheckAttributeGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
14678 xmlSchemaParserCtxtPtr ctxt,
14679 const xmlChar * name ATTRIBUTE_UNUSED)
14680{
14681 /*
14682 * Schema Representation Constraint:
14683 * Attribute Group Definition Representation OK
14684 * 3 Circular group reference is disallowed outside <redefine>.
14685 * That is, unless this element information item's parent is
14686 * <redefine>, then among the [children], if any, there must
14687 * not be an <attributeGroup> with ref [attribute] which resolves
14688 * to the component corresponding to this <attributeGroup>. Indirect
14689 * circularity is also ruled out. That is, when QName resolution
14690 * (Schema Document) (§3.15.3) is applied to a ·QName· arising from
14691 * any <attributeGroup>s with a ref [attribute] among the [children],
14692 * it must not be the case that a ·QName· is encountered at any depth
14693 * which resolves to the component corresponding to this <attributeGroup>.
14694 */
14695 /*
14696 * Only global components can be referenced.
14697 */
14698 if (((attrGr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) == 0) ||
14699 (attrGr->attributes == NULL))
14700 return;
14701 else {
14702 xmlSchemaAttributeGroupPtr circ;
14703
14704 circ = xmlSchemaGetCircAttrGrRef(attrGr, attrGr->attributes);
14705 if (circ != NULL) {
14706 /*
14707 * TODO: Report the referenced attr group as QName.
14708 */
14709 xmlSchemaPCustomErr(ctxt,
14710 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
14711 NULL, NULL, circ->node,
14712 "Circular reference to the attribute group '%s' "
14713 "defined", attrGr->name);
14714 /*
14715 * NOTE: We will cut the reference to avoid further
14716 * confusion of the processor.
14717 * BADSPEC: The spec should define how to process in this case.
14718 */
14719 circ->attributes = NULL;
14720 circ->refItem = NULL;
14721 }
14722 }
14723}
14724
14725/**
Daniel Veillard13e04c62002-04-23 17:51:29 +000014726 * xmlSchemaAttrGrpFixup:
14727 * @attrgrpDecl: the schema attribute definition
14728 * @ctxt: the schema parser context
14729 * @name: the attribute name
14730 *
14731 * Fixes finish doing the computations on the attributes definitions
14732 */
14733static void
Daniel Veillard3646d642004-06-02 19:19:14 +000014734xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014735 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +000014736{
14737 if (name == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000014738 name = attrgrp->name;
14739 if (attrgrp->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014740 return;
Daniel Veillard3646d642004-06-02 19:19:14 +000014741 if (attrgrp->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014742 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +000014743
Daniel Veillardc0826a72004-08-10 14:17:33 +000014744 ref = xmlSchemaGetAttributeGroup(ctxt->schema, attrgrp->ref,
14745 attrgrp->refNs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014746 if (ref == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014747 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014748 XML_SCHEMAP_SRC_RESOLVE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014749 NULL, (xmlSchemaTypePtr) attrgrp, attrgrp->node,
14750 "ref", attrgrp->ref, attrgrp->refNs,
14751 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014752 return;
14753 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014754 attrgrp->refItem = ref;
14755 /*
14756 * Check for self reference!
14757 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014758 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000014759 attrgrp->attributes = ref->attributes;
14760 attrgrp->attributeWildcard = ref->attributeWildcard;
14761 }
Daniel Veillard13e04c62002-04-23 17:51:29 +000014762}
14763
14764/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014765 * xmlSchemaAttrCheckValConstr:
14766 * @item: an schema attribute declaration/use
14767 * @ctxt: a schema parser context
14768 * @name: the name of the attribute
14769 *
14770 * Validates the value constraints of an attribute declaration/use.
Daniel Veillard4255d502002-04-16 15:50:10 +000014771 *
14772 * Fixes finish doing the computations on the attributes definitions
14773 */
14774static void
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014775xmlSchemaCheckAttrValConstr(xmlSchemaAttributePtr item,
14776 xmlSchemaParserCtxtPtr ctxt,
14777 const xmlChar * name ATTRIBUTE_UNUSED)
14778{
14779
14780 /*
14781 * a-props-correct
14782 * Schema Component Constraint: Attribute Declaration Properties Correct
14783 *
14784 * 2 if there is a {value constraint}, the canonical lexical
14785 * representation of its value must be ·valid· with respect
14786 * to the {type definition} as defined in String Valid (§3.14.4).
14787 */
14788
14789 if (item->defValue != NULL) {
14790 int ret;
14791 xmlNodePtr node;
14792 xmlSchemaTypePtr type;
14793
14794 if (item->subtypes == NULL) {
14795 xmlSchemaPErr(ctxt, item->node,
14796 XML_SCHEMAP_INTERNAL,
14797 "Internal error: xmlSchemaCheckAttrValConstr, "
14798 "type is missing... skipping validation of "
14799 "value constraint", NULL, NULL);
14800 return;
14801 }
14802
14803 /*
14804 * TODO: Try to avoid creating a new context.
14805 * TODO: This all is not very performant.
14806 */
14807 type = item->subtypes;
14808 /*
14809 * Ensure there's validation context.
14810 */
14811 if (ctxt->vctxt == NULL) {
14812 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1) {
14813 xmlSchemaPErr(ctxt, item->node,
14814 XML_SCHEMAP_INTERNAL,
14815 "Internal error: xmlSchemaCheckAttrValConstr, "
14816 "creating a new validation context.\n",
14817 NULL, NULL);
14818 return;
14819 }
14820 }
14821
14822 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
14823 node = (xmlNodePtr) xmlHasProp(item->node, BAD_CAST "fixed");
14824 else
14825 node = (xmlNodePtr) xmlHasProp(item->node, BAD_CAST "default");
14826 ctxt->vctxt->node = node;
14827 ctxt->vctxt->cur = NULL;
14828 /*
14829 * NOTE: This call does not check the content nodes,
14830 * since they are not available:
14831 * facet->node is just the node holding the facet
14832 * definition, *not* the attribute holding the *value*
14833 * of the facet.
14834 */
14835 ret = xmlSchemaValidateSimpleTypeValue(ctxt->vctxt, type,
14836 item->defValue, 0, 1, 1, 0);
14837 if (ret == 0) {
14838 /*
14839 * Store the computed value.
14840 */
14841 item->defVal = ctxt->vctxt->value;
14842 ctxt->vctxt->value = NULL;
14843 } else if (ret > 0) {
14844 if (ctxt != NULL) {
14845 xmlSchemaPSimpleTypeErr(ctxt,
14846 XML_SCHEMAP_A_PROPS_CORRECT_2,
14847 NULL, NULL, node,
14848 type, NULL, item->defValue,
14849 NULL, NULL, NULL);
14850 }
14851 } else if (ret < 0) {
14852 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
14853 NULL, NULL, node,
14854 "Internal error: xmlSchemaAttrCheckValConstr, "
14855 "failed to validate the value constraint of the "
14856 "attribute decl/use against the type '%s'",
14857 type->name);
14858 }
14859 }
14860}
14861
14862#if 0 /* Not used yet. */
14863static int
14864xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
14865 xmlSchemaElementPtr edecl)
14866{
14867 /*
14868 * TODO: 1 The values of the properties of an element declaration must be as
14869 * described in the property tableau in The Element Declaration Schema
14870 * Component (§3.3.1), modulo the impact of Missing Sub-components (§5.3).
14871 */
14872 /*
14873 * 2 If there is a {value constraint}, the canonical lexical
14874 * representation of its value must be ·valid· with respect to the {type
14875 * definition} as defined in Element Default Valid (Immediate) (§3.3.6).
14876 *
14877 * NOTE: This is done in xmlSchemaCheckElemValConstr.
14878 */
14879 /*
14880 * 3 If there is a non-·absent· {substitution group affiliation},
14881 * then {scope} must be global.
14882 *
14883 * NOTE: This is done in xmlSchemaParseElement.
14884 * TODO: Move it to this layer here.
14885 */
14886 /*
14887 * TODO: 4 If there is a {substitution group affiliation}, the {type definition}
14888 * of the element declaration must be validly derived from the {type
14889 * definition} of the {substitution group affiliation}, given the value
14890 * of the {substitution group exclusions} of the {substitution group
14891 * affiliation}, as defined in Type Derivation OK (Complex) (§3.4.6)
14892 * (if the {type definition} is complex) or as defined in
14893 * Type Derivation OK (Simple) (§3.14.6) (if the {type definition} is
14894 * simple).
14895 */
14896 /*
14897 * TODO: 5 If the {type definition} or {type definition}'s {content type}
14898 * is or is derived from ID then there must not be a {value constraint}.
14899 * Note: The use of ID as a type definition for elements goes beyond
14900 * XML 1.0, and should be avoided if backwards compatibility is desired
14901 */
14902 /*
14903 * TODO: 6 Circular substitution groups are disallowed. That is, it must not
14904 * be possible to return to an element declaration by repeatedly following
14905 * the {substitution group affiliation} property.
14906 */
14907}
14908#endif
14909
14910/**
14911 * xmlSchemaCheckElemValConstr:
14912 * @item: an schema element declaration/particle
14913 * @ctxt: a schema parser context
14914 * @name: the name of the attribute
14915 *
14916 * Validates the value constraints of an element declaration.
14917 *
14918 * Fixes finish doing the computations on the element declarations.
14919 */
14920static void
14921xmlSchemaCheckElemValConstr(xmlSchemaElementPtr decl,
14922 xmlSchemaParserCtxtPtr ctxt,
14923 const xmlChar * name ATTRIBUTE_UNUSED)
14924{
14925 if (decl->value != NULL) {
14926 int ret;
14927 xmlNodePtr node = NULL;
14928 xmlSchemaTypePtr type;
14929
14930 /*
14931 * 2 If there is a {value constraint}, the canonical lexical
14932 * representation of its value must be ·valid· with respect to the {type
14933 * definition} as defined in Element Default Valid (Immediate) (§3.3.6).
14934 */
14935 if (decl->subtypes == NULL) {
14936 xmlSchemaPErr(ctxt, decl->node,
14937 XML_SCHEMAP_INTERNAL,
14938 "Internal error: xmlSchemaCheckElemValConstr, "
14939 "type is missing... skipping validation of "
14940 "the value constraint", NULL, NULL);
14941 return;
14942 }
14943 /*
14944 * Ensure there's a validation context.
14945 */
14946 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
14947 return;
14948
14949 type = decl->subtypes;
14950
14951 if (decl->node != NULL) {
14952 if (decl->flags & XML_SCHEMAS_ELEM_FIXED)
14953 node = (xmlNodePtr) xmlHasProp(decl->node, BAD_CAST "fixed");
14954 else
14955 node = (xmlNodePtr) xmlHasProp(decl->node, BAD_CAST "default");
14956 }
14957 ctxt->vctxt->node = node;
14958 ctxt->vctxt->cur = NULL;
14959 ret = xmlSchemaCheckCOSValidDefault(ctxt, ctxt->vctxt, type, decl->value,
14960 node);
14961 if (ret == 0) {
14962 /*
14963 * Consume the computed value.
14964 */
14965 decl->defVal = ctxt->vctxt->value;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000014966 ctxt->vctxt->value = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014967 } else if (ret < 0) {
14968 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
14969 NULL, NULL, node,
14970 "Internal error: xmlSchemaElemCheckValConstr, "
14971 "failed to validate the value constraint of the "
14972 "element declaration '%s'",
14973 decl->name);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000014974 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014975 }
14976}
14977
14978/**
14979 * xmlSchemaAttrFixup:
14980 * @item: an schema attribute declaration/use.
14981 * @ctxt: a schema parser context
14982 * @name: the name of the attribute
14983 *
14984 * Fixes finish doing the computations on attribute declarations/uses.
14985 */
14986static void
14987xmlSchemaAttrFixup(xmlSchemaAttributePtr item,
14988 xmlSchemaParserCtxtPtr ctxt,
14989 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000014990{
Daniel Veillardc0826a72004-08-10 14:17:33 +000014991 /*
14992 * TODO: If including this is done twice (!) for every attribute.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014993 * -> Hmm, check if this is still done.
Daniel Veillardc0826a72004-08-10 14:17:33 +000014994 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014995 /*
14996 * The simple type definition corresponding to the <simpleType> element
14997 * information item in the [children], if present, otherwise the simple
14998 * type definition ·resolved· to by the ·actual value· of the type
14999 * [attribute], if present, otherwise the ·simple ur-type definition·.
15000 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015001 if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
Daniel Veillardc0826a72004-08-10 14:17:33 +000015002 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015003 item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
15004 if (item->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015005 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015006 if (item->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015007 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000015008
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015009 type = xmlSchemaGetType(ctxt->schema, item->typeName,
15010 item->typeNs);
15011 if ((type == NULL) || (! IS_SIMPLE_TYPE(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015012 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015013 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015014 NULL, (xmlSchemaTypePtr) item, item->node,
15015 "type", item->typeName, item->typeNs,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015016 XML_SCHEMA_TYPE_SIMPLE, NULL);
15017 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015018 item->subtypes = type;
15019
15020 } else if (item->ref != NULL) {
15021 xmlSchemaAttributePtr decl;
Daniel Veillard4255d502002-04-16 15:50:10 +000015022
Daniel Veillardc0826a72004-08-10 14:17:33 +000015023 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015024 * We have an attribute use here; assign the referenced
15025 * attribute declaration.
15026 */
15027 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000015028 * TODO: Evaluate, what errors could occur if the declaration is not
15029 * found. It might be possible that the "typefixup" might crash if
15030 * no ref declaration was found.
15031 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015032 decl = xmlSchemaGetAttribute(ctxt->schema, item->ref, item->refNs);
15033 if (decl == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015034 xmlSchemaPResCompAttrErr(ctxt,
15035 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015036 NULL, (xmlSchemaTypePtr) item, item->node,
15037 "ref", item->ref, item->refNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015038 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015039 return;
15040 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015041 item->refDecl = decl;
15042 xmlSchemaAttrFixup(decl, ctxt, NULL);
15043
15044 item->subtypes = decl->subtypes;
15045 /*
15046 * Attribute Use Correct
15047 * au-props-correct.2: If the {attribute declaration} has a fixed
15048 * {value constraint}, then if the attribute use itself has a
15049 * {value constraint}, it must also be fixed and its value must match
15050 * that of the {attribute declaration}'s {value constraint}.
15051 */
15052 if ((decl->flags & XML_SCHEMAS_ATTR_FIXED) &&
15053 (item->defValue != NULL)) {
15054 if (((item->flags & XML_SCHEMAS_ATTR_FIXED) == 0) ||
15055 (!xmlStrEqual(item->defValue, decl->defValue))) {
15056 xmlSchemaPCustomErr(ctxt,
15057 XML_SCHEMAP_AU_PROPS_CORRECT_2,
15058 NULL, NULL, item->node,
15059 "The value constraint must be fixed "
15060 "and match the referenced attribute "
15061 "declarations's value constraint '%s'",
15062 decl->defValue);
15063 }
15064 /*
15065 * FUTURE: One should change the values of the attr. use
15066 * if ever validation should be attempted even if the
15067 * schema itself was not fully valid.
15068 */
15069 }
Daniel Veillard3646d642004-06-02 19:19:14 +000015070 } else {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015071 item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
15072 }
Daniel Veillard4255d502002-04-16 15:50:10 +000015073}
15074
15075/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015076 * xmlSchemaResolveIDCKeyRef:
15077 * @idc: the identity-constraint definition
15078 * @ctxt: the schema parser context
15079 * @name: the attribute name
15080 *
15081 * Resolve keyRef references to key/unique IDCs.
15082 */
15083static void
15084xmlSchemaResolveIDCKeyRef(xmlSchemaIDCPtr idc,
15085 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000015086 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015087{
15088 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
15089 return;
15090 if (idc->ref->name != NULL) {
15091 idc->ref->item = (xmlSchemaBasicItemPtr) xmlHashLookup2(
15092 ctxt->schema->idcDef,
15093 idc->ref->name,
15094 idc->ref->targetNamespace);
15095 if (idc->ref->item == NULL) {
15096 /*
15097 * TODO: It is actually not an error to fail to resolve.
15098 */
15099 xmlSchemaPResCompAttrErr(ctxt,
15100 XML_SCHEMAP_SRC_RESOLVE,
15101 NULL, (xmlSchemaTypePtr) idc, idc->node,
15102 "refer", idc->ref->name,
15103 idc->ref->targetNamespace,
15104 XML_SCHEMA_TYPE_IDC_KEYREF, NULL);
15105 return;
15106 }
15107 }
15108}
15109
15110/**
Daniel Veillard4255d502002-04-16 15:50:10 +000015111 * xmlSchemaParse:
15112 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000015113 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000015114 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +000015115 * XML Shema struture which can be used to validate instances.
15116 * *WARNING* this interface is highly subject to change
15117 *
15118 * Returns the internal XML Schema structure built from the resource or
15119 * NULL in case of error
15120 */
15121xmlSchemaPtr
15122xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
15123{
15124 xmlSchemaPtr ret = NULL;
15125 xmlDocPtr doc;
Daniel Veillardbd2904b2003-11-25 15:38:59 +000015126 xmlNodePtr root;
Daniel Veillarddda22c12004-01-24 08:31:30 +000015127 int preserve = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000015128
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015129 /*
15130 * This one is used if the schema to be parsed was specified via
15131 * the API; i.e. not automatically by the validated instance document.
15132 */
15133
Daniel Veillard4255d502002-04-16 15:50:10 +000015134 xmlSchemaInitTypes();
15135
Daniel Veillard6045c902002-10-09 21:13:59 +000015136 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +000015137 return (NULL);
15138
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000015139 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000015140 ctxt->counter = 0;
15141 ctxt->container = NULL;
15142
15143 /*
15144 * First step is to parse the input document into an DOM/Infoset
15145 */
Daniel Veillard6045c902002-10-09 21:13:59 +000015146 if (ctxt->URL != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000015147 doc = xmlReadFile((const char *) ctxt->URL, NULL,
15148 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015149 if (doc == NULL) {
15150 xmlSchemaPErr(ctxt, NULL,
15151 XML_SCHEMAP_FAILED_LOAD,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015152 "xmlSchemaParse: could not load '%s'.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015153 ctxt->URL, NULL);
15154 return (NULL);
15155 }
Daniel Veillard6045c902002-10-09 21:13:59 +000015156 } else if (ctxt->buffer != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000015157 doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
15158 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015159 if (doc == NULL) {
15160 xmlSchemaPErr(ctxt, NULL,
15161 XML_SCHEMAP_FAILED_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015162 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015163 NULL, NULL);
15164 return (NULL);
15165 }
15166 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard65765282004-01-08 16:59:30 +000015167 ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
Daniel Veillard9d751502003-10-29 13:21:47 +000015168 } else if (ctxt->doc != NULL) {
15169 doc = ctxt->doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000015170 preserve = 1;
Daniel Veillard6045c902002-10-09 21:13:59 +000015171 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015172 xmlSchemaPErr(ctxt, NULL,
15173 XML_SCHEMAP_NOTHING_TO_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015174 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015175 NULL, NULL);
15176 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000015177 }
15178
15179 /*
15180 * Then extract the root and Schema parse it
15181 */
15182 root = xmlDocGetRootElement(doc);
15183 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015184 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
15185 XML_SCHEMAP_NOROOT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015186 "The schema has no document element.\n", NULL, NULL);
Daniel Veillarddda22c12004-01-24 08:31:30 +000015187 if (!preserve) {
15188 xmlFreeDoc(doc);
15189 }
Daniel Veillard4255d502002-04-16 15:50:10 +000015190 return (NULL);
15191 }
15192
15193 /*
15194 * Remove all the blank text nodes
15195 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +000015196 xmlSchemaCleanupDoc(ctxt, root);
Daniel Veillard4255d502002-04-16 15:50:10 +000015197
15198 /*
15199 * Then do the parsing for good
15200 */
15201 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillard1d913862003-11-21 00:28:39 +000015202 if (ret == NULL) {
Daniel Veillarddda22c12004-01-24 08:31:30 +000015203 if (!preserve) {
15204 xmlFreeDoc(doc);
15205 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015206 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +000015207 }
Daniel Veillard4255d502002-04-16 15:50:10 +000015208 ret->doc = doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000015209 ret->preserve = preserve;
Daniel Veillard4255d502002-04-16 15:50:10 +000015210 ctxt->schema = ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015211 ctxt->ctxtType = NULL;
15212 ctxt->parentItem = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000015213 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +000015214 * Then fixup all attributes declarations
15215 */
15216 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
15217
15218 /*
15219 * Then fixup all attributes group declarations
15220 */
15221 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
15222 ctxt);
15223
15224 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015225 * Resolve identity-constraint keyRefs.
15226 */
15227 xmlHashScan(ret->idcDef, (xmlHashScanner) xmlSchemaResolveIDCKeyRef, ctxt);
15228
15229 /*
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015230 * Check attribute groups for circular references.
15231 */
15232 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner)
15233 xmlSchemaCheckAttributeGroupCircular, ctxt);
15234
15235 /*
15236 * Then fixup all model group definitions.
15237 */
15238 xmlHashScan(ret->groupDecl, (xmlHashScanner) xmlSchemaGroupDefFixup, ctxt);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015239
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015240 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000015241 * Then fix references of element declaration; apply constraints.
15242 */
15243 xmlHashScanFull(ret->elemDecl,
15244 (xmlHashScannerFull) xmlSchemaRefFixupCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000015245
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000015246 /*
15247 * We will stop here if the schema was not valid to avoid internal errors
15248 * on missing sub-components. This is not conforming to the spec, since it
15249 * allows missing components, but it might make further processing crash.
15250 * So see it as a very strict handling, which might be made more lax in the
15251 * future.
15252 */
15253 if (ctxt->nberrors != 0)
15254 goto exit;
15255 /*
15256 * Then fixup all types properties
15257 */
15258 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015259 /*
15260 * Check model groups defnitions for circular references.
15261 */
15262 xmlHashScan(ret->groupDecl, (xmlHashScanner)
15263 xmlSchemaCheckGroupDefCircular, ctxt);
15264
Daniel Veillard4255d502002-04-16 15:50:10 +000015265 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015266 * Then build the content model for all complex types
Daniel Veillard4255d502002-04-16 15:50:10 +000015267 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015268 xmlHashScan(ret->typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015269 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000015270
15271 /*
15272 * Then check the defaults part of the type like facets values
15273 */
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000015274 /* OLD: xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaCheckDefaults, ctxt); */
Daniel Veillard4255d502002-04-16 15:50:10 +000015275
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015276 /*
15277 * Validate the value constraint of attribute declarations/uses.
15278 */
15279 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaCheckAttrValConstr, ctxt);
15280
15281 /*
15282 * Validate the value constraint of element declarations.
15283 */
15284 xmlHashScan(ret->elemDecl, (xmlHashScanner) xmlSchemaCheckElemValConstr, ctxt);
15285
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000015286exit:
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000015287 if (ctxt->nberrors != 0) {
15288 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015289 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000015290 }
Daniel Veillard4255d502002-04-16 15:50:10 +000015291 return (ret);
15292}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015293
Daniel Veillard4255d502002-04-16 15:50:10 +000015294/**
Daniel Veillard01c13b52002-12-10 15:19:08 +000015295 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +000015296 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +000015297 * @err: the error callback
15298 * @warn: the warning callback
15299 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +000015300 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000015301 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000015302 */
15303void
15304xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015305 xmlSchemaValidityErrorFunc err,
15306 xmlSchemaValidityWarningFunc warn, void *ctx)
15307{
Daniel Veillard4255d502002-04-16 15:50:10 +000015308 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015309 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000015310 ctxt->error = err;
15311 ctxt->warning = warn;
15312 ctxt->userData = ctx;
15313}
15314
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000015315/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000015316 * xmlSchemaGetParserErrors:
15317 * @ctxt: a XMl-Schema parser context
15318 * @err: the error callback result
15319 * @warn: the warning callback result
15320 * @ctx: contextual data for the callbacks result
15321 *
15322 * Get the callback information used to handle errors for a parser context
15323 *
15324 * Returns -1 in case of failure, 0 otherwise
15325 */
15326int
15327xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
15328 xmlSchemaValidityErrorFunc * err,
15329 xmlSchemaValidityWarningFunc * warn, void **ctx)
15330{
15331 if (ctxt == NULL)
15332 return(-1);
15333 if (err != NULL)
15334 *err = ctxt->error;
15335 if (warn != NULL)
15336 *warn = ctxt->warning;
15337 if (ctx != NULL)
15338 *ctx = ctxt->userData;
15339 return(0);
15340}
15341
15342/**
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000015343 * xmlSchemaFacetTypeToString:
15344 * @type: the facet type
15345 *
15346 * Convert the xmlSchemaTypeType to a char string.
15347 *
15348 * Returns the char string representation of the facet type if the
15349 * type is a facet and an "Internal Error" string otherwise.
15350 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000015351static const xmlChar *
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000015352xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
15353{
15354 switch (type) {
15355 case XML_SCHEMA_FACET_PATTERN:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000015356 return (BAD_CAST "pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015357 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000015358 return (BAD_CAST "maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015359 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000015360 return (BAD_CAST "maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015361 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000015362 return (BAD_CAST "minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015363 case XML_SCHEMA_FACET_MININCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000015364 return (BAD_CAST "minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015365 case XML_SCHEMA_FACET_WHITESPACE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000015366 return (BAD_CAST "whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015367 case XML_SCHEMA_FACET_ENUMERATION:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000015368 return (BAD_CAST "enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015369 case XML_SCHEMA_FACET_LENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000015370 return (BAD_CAST "length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015371 case XML_SCHEMA_FACET_MAXLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000015372 return (BAD_CAST "maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015373 case XML_SCHEMA_FACET_MINLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000015374 return (BAD_CAST "minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015375 case XML_SCHEMA_FACET_TOTALDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000015376 return (BAD_CAST "totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015377 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000015378 return (BAD_CAST "fractionDigits");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000015379 default:
15380 break;
15381 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000015382 return (BAD_CAST "Internal Error");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000015383}
15384
Daniel Veillardc0826a72004-08-10 14:17:33 +000015385static int
15386xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
15387{
15388 xmlSchemaTypePtr anc;
15389
15390 /*
15391 * The normalization type can be changed only for types which are derived
15392 * from xsd:string.
15393 */
15394 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000015395 if (type->builtInType == XML_SCHEMAS_STRING)
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000015396 return(XML_SCHEMAS_FACET_PRESERVE);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000015397 else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000015398 return(XML_SCHEMAS_FACET_REPLACE);
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000015399 else if (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)
15400 /*
15401 * Note that we assume a whitespace of preserve for anySimpleType.
15402 */
15403 return(XML_SCHEMAS_FACET_PRESERVE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015404 else {
15405 /*
15406 * For all ·atomic· datatypes other than string (and types ·derived·
15407 * by ·restriction· from it) the value of whiteSpace is fixed to
15408 * collapse
15409 */
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000015410 return(XML_SCHEMAS_FACET_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015411 }
15412 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
15413 /*
15414 * For list types the facet "whiteSpace" is fixed to "collapse".
15415 */
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000015416 return (XML_SCHEMAS_FACET_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015417 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000015418 return (XML_SCHEMAS_FACET_UNKNOWN);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015419 } else if (type->facetSet != NULL) {
15420 xmlSchemaTypePtr anyST;
15421 xmlSchemaFacetLinkPtr lin;
15422
15423 /*
15424 * Atomic types.
15425 */
15426 anyST = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
15427 anc = type->baseType;
15428 do {
15429 /*
15430 * For all ·atomic· datatypes other than string (and types ·derived·
15431 * by ·restriction· from it) the value of whiteSpace is fixed to
15432 * collapse
15433 */
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000015434 if ((anc->builtInType == XML_SCHEMAS_STRING) ||
15435 (anc->builtInType == XML_SCHEMAS_NORMSTRING)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015436
15437 lin = type->facetSet;
15438 do {
15439 if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000015440 return(lin->facet->whitespace);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015441 break;
15442 }
15443 lin = lin->next;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000015444 } while (lin != NULL);
15445 if (anc->builtInType == XML_SCHEMAS_NORMSTRING)
15446 return (XML_SCHEMAS_FACET_REPLACE);
15447 else
15448 return (XML_SCHEMAS_FACET_PRESERVE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015449 }
15450 anc = anc->baseType;
15451 } while (anc != anyST);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000015452 return (XML_SCHEMAS_FACET_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015453 }
15454 return (-1);
15455}
15456
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000015457/**
Daniel Veillard377e1a92004-04-16 16:30:05 +000015458 * xmlSchemaValidateFacetsInternal:
15459 * @ctxt: a schema validation context
Daniel Veillardc0826a72004-08-10 14:17:33 +000015460 * @type: the type holding the facets
Daniel Veillard377e1a92004-04-16 16:30:05 +000015461 * @facets: the list of facets to check
15462 * @value: the lexical repr of the value to validate
15463 * @val: the precomputed value
William M. Bracke7091952004-05-11 15:09:58 +000015464 * @fireErrors: if 0, only internal errors will be fired;
15465 * otherwise all errors will be fired.
Daniel Veillard377e1a92004-04-16 16:30:05 +000015466 *
15467 * Check a value against all facet conditions
15468 *
15469 * Returns 0 if the element is schemas valid, a positive error code
15470 * number otherwise and -1 in case of internal or API error.
15471 */
15472static int
15473xmlSchemaValidateFacetsInternal(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015474 xmlSchemaTypePtr type,
15475 const xmlChar * value,
15476 unsigned long length,
15477 int fireErrors)
Daniel Veillard377e1a92004-04-16 16:30:05 +000015478{
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000015479 int ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015480 xmlNodePtr node;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000015481 xmlSchemaTypePtr biType; /* The build-in type. */
Daniel Veillardc0826a72004-08-10 14:17:33 +000015482 xmlSchemaTypePtr tmpType;
15483 xmlSchemaFacetLinkPtr facetLink;
Daniel Veillardc7e3cc42004-09-28 12:33:52 +000015484 int retFacet;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015485 xmlSchemaFacetPtr facet;
15486 unsigned long len = 0;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000015487 xmlSchemaWhitespaceValueType ws;
15488
15489 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
15490 xmlSchemaTypePtr tp;
15491 /*
15492 * TODO: Get rid of this case: the complex type still holds facets in some
15493 * cases.
15494 */
15495 tp = xmlSchemaGetSimpleContentType(type);
15496 ws = (xmlSchemaWhitespaceValueType) xmlSchemaGetWhiteSpaceFacetValue(tp);
15497 } else
15498 ws = (xmlSchemaWhitespaceValueType) xmlSchemaGetWhiteSpaceFacetValue(type);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000015499
Daniel Veillardc0826a72004-08-10 14:17:33 +000015500#ifdef DEBUG_UNION_VALIDATION
15501 printf("Facets of type: '%s'\n", (const char *) type->name);
15502 printf(" fireErrors: %d\n", fireErrors);
15503#endif
15504
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015505 node = ctxt->node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015506 /*
15507 * NOTE: Do not jump away, if the facetSet of the given type is
15508 * empty: until now, "pattern" facets of the *base types* need to
15509 * be checked as well.
15510 */
15511 biType = type->baseType;
15512 while ((biType != NULL) && (biType->type != XML_SCHEMA_TYPE_BASIC))
15513 biType = biType->baseType;
15514 if (biType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015515 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015516 "Internal error: xmlSchemaValidateFacetsInternal, "
15517 "the base type axis of the given type '%s' does not resolve to "
15518 "a built-in type.\n",
15519 type->name, NULL);
15520 return (-1);
15521 }
15522
15523 if (type->facetSet != NULL) {
15524 facetLink = type->facetSet;
15525 while (facetLink != NULL) {
15526 facet = facetLink->facet;
15527 /*
15528 * Skip the pattern "whiteSpace": it is used to
15529 * format the character content beforehand.
15530 */
15531 switch (facet->type) {
15532 case XML_SCHEMA_FACET_WHITESPACE:
15533 case XML_SCHEMA_FACET_PATTERN:
15534 case XML_SCHEMA_FACET_ENUMERATION:
15535 break;
15536 case XML_SCHEMA_FACET_LENGTH:
15537 case XML_SCHEMA_FACET_MINLENGTH:
15538 case XML_SCHEMA_FACET_MAXLENGTH:
15539 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
15540 ret = xmlSchemaValidateListSimpleTypeFacet(facet,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000015541 value, length, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015542 len = length;
15543 } else
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000015544 ret = xmlSchemaValidateLengthFacetWhtsp(facet,
15545 (xmlSchemaValType) biType->builtInType,
15546 value, ctxt->value, &len, ws);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015547 break;
15548 default:
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000015549 ret = xmlSchemaValidateFacetWhtsp(facet, ws,
15550 biType->builtInType, value, ctxt->value, ws);
15551 /*
15552 * ret = xmlSchemaValidateFacet(biType, facet, value,
15553 * ctxt->value);
15554 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015555 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000015556 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015557 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015558 "Internal error: xmlSchemaValidateFacetsInternal, "
15559 "validating facet of type '%s'.\n",
15560 type->name, NULL);
15561 break;
15562 } else if ((ret > 0) && (fireErrors)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015563 xmlSchemaVFacetErr(ctxt, ret, node, value, len,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015564 type, facet, NULL, NULL, NULL, NULL);
15565 }
15566
15567 facetLink = facetLink->next;
15568 }
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000015569
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000015570 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000015571 if (ret >= 0) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000015572 xmlSchemaWhitespaceValueType fws;
15573 /*
15574 * Process enumerations. Facet values are in the value space
15575 * of the defining type's base type. This seems to be a bug in the
15576 * XML Schema 1.0 spec. For use, the normalized value is only
15577 * significant for enumerations. We need to localize the base type for eatch
15578 * enumeration facet, thus walk the ancestor type axis.
15579 */
15580 tmpType = type;
15581 do {
15582 /*
15583 * Use the whitespace type of the base type.
15584 */
15585 if (tmpType->type == XML_SCHEMA_TYPE_COMPLEX)
15586 /* TODO: Get rid of this case. */
15587 fws = (xmlSchemaWhitespaceValueType)
15588 xmlSchemaGetWhiteSpaceFacetValue(
15589 xmlSchemaGetSimpleContentType(tmpType));
15590 else
15591 fws = (xmlSchemaWhitespaceValueType)
15592 xmlSchemaGetWhiteSpaceFacetValue(tmpType->baseType);
15593 retFacet = 0;
15594 for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
15595 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
15596 continue;
15597 retFacet = xmlSchemaValidateFacetWhtsp(facet, fws,
15598 biType->builtInType, value, ctxt->value, ws);
15599 if (retFacet == 0)
15600 break;
15601 else if (retFacet < 0) {
15602 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
15603 "Internal error: xmlSchemaValidateFacetsInternal, "
15604 "validating enumeration facet '%s' of type '%s'.\n",
15605 facet->value, tmpType->name);
15606 ret = -1;
15607 break;
15608 }
15609 }
15610 if (retFacet <= 0)
15611 break;
15612 if (tmpType->type == XML_SCHEMA_TYPE_COMPLEX)
15613 /* TODO: Get rid of this case. */
15614 tmpType = xmlSchemaGetSimpleContentType(tmpType);
15615 else
15616 tmpType = tmpType->baseType;
15617 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
15618 if (retFacet > 0) {
15619 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
15620 if (fireErrors) {
15621 xmlSchemaVFacetErr(ctxt, ret, node, value, 0, type, NULL,
15622 NULL, NULL, NULL, NULL);
15623 }
15624 }
15625 }
15626
15627 if (ret >= 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015628 /*
15629 * Process patters. Pattern facets are ORed at type level
15630 * and ANDed if derived. Walk the base type axis.
15631 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000015632 tmpType = type;
15633 facet = NULL;
15634 do {
15635 retFacet = 0;
15636 for (facetLink = tmpType->facetSet; facetLink != NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015637 facetLink = facetLink->next) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015638 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
15639 continue;
15640 retFacet = xmlSchemaValidateFacet(biType, facetLink->facet,
15641 value, ctxt->value);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015642 if (retFacet == 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +000015643 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015644 else if (retFacet < 0) {
15645 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
15646 "Internal error: xmlSchemaValidateFacetsInternal, "
15647 "validating 'pattern' facet '%s' of type '%s'.\n",
15648 facetLink->facet->value, tmpType->name);
15649 ret = -1;
15650 break;
15651 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +000015652 /* Save the last non-validating facet. */
15653 facet = facetLink->facet;
15654 }
15655 if (retFacet != 0)
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000015656 break;
15657 if (tmpType->type == XML_SCHEMA_TYPE_COMPLEX)
15658 /* TODO: Get rid of this case. */
15659 tmpType = xmlSchemaGetSimpleContentType(tmpType);
15660 else
15661 tmpType = tmpType->baseType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015662 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015663 if (retFacet > 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000015664 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
15665 if (fireErrors) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015666 xmlSchemaVFacetErr(ctxt, ret, node, value, 0, type, facet,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015667 NULL, NULL, NULL, NULL);
15668 }
15669 }
15670 }
15671
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000015672 return (ret);
15673}
15674
Daniel Veillard4255d502002-04-16 15:50:10 +000015675/************************************************************************
15676 * *
15677 * Simple type validation *
15678 * *
15679 ************************************************************************/
Daniel Veillard377e1a92004-04-16 16:30:05 +000015680
Daniel Veillard4255d502002-04-16 15:50:10 +000015681
15682/************************************************************************
15683 * *
15684 * DOM Validation code *
15685 * *
15686 ************************************************************************/
15687
Daniel Veillard4255d502002-04-16 15:50:10 +000015688static int xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015689 xmlNodePtr elem,
Daniel Veillard3646d642004-06-02 19:19:14 +000015690 xmlSchemaTypePtr type);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015691static int xmlSchemaValidateElementByType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015692 xmlSchemaTypePtr type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000015693 int isNil,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015694 int valSimpleContent);
Daniel Veillard4255d502002-04-16 15:50:10 +000015695
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015696static void xmlSchemaBeginElement(xmlSchemaValidCtxtPtr vctxt);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000015697static int xmlSchemaEndElement(xmlSchemaValidCtxtPtr vctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015698
15699#ifdef ELEM_INFO_ENABLED
15700/**
15701 * xmlSchemaGetFreshElemInfo:
15702 * @vctxt: the schema validation context
15703 *
15704 * Creates/reuses and initializes the element info item for
15705 * the currect tree depth.
15706 *
15707 * Returns the element info item or NULL on API or internal errors.
15708 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000015709static xmlSchemaNodeInfoPtr
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000015710xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt,
15711 int depth)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015712{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000015713 xmlSchemaNodeInfoPtr info = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015714
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000015715 if (depth > vctxt->sizeElemInfos) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015716 xmlSchemaVErr(vctxt, NULL, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000015717 "Internal error: xmlSchemaGetFreshElemInfo, "
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015718 "an inconsistent depth encountered.\n",
15719 NULL, NULL);
15720 return (NULL);
15721 }
15722 if (vctxt->elemInfos == NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000015723 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
15724 xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015725 if (vctxt->elemInfos == NULL) {
15726 xmlSchemaVErrMemory(vctxt,
15727 "allocating the element info array", NULL);
15728 return (NULL);
15729 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000015730 memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015731 vctxt->sizeElemInfos = 10;
15732 } else if (vctxt->sizeElemInfos == vctxt->depth) {
15733 int i = vctxt->sizeElemInfos;
15734
15735 vctxt->sizeElemInfos *= 2;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000015736 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015737 xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000015738 sizeof(xmlSchemaNodeInfoPtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015739 if (vctxt->elemInfos == NULL) {
15740 xmlSchemaVErrMemory(vctxt,
15741 "re-allocating the element info array", NULL);
15742 return (NULL);
15743 }
15744 /*
15745 * We need the new memory to be NULLed.
15746 * TODO: Use memset instead?
15747 */
15748 for (; i < vctxt->sizeElemInfos; i++)
15749 vctxt->elemInfos[i] = NULL;
15750 } else
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000015751 info = vctxt->elemInfos[depth];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015752
15753 if (info == NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000015754 info = (xmlSchemaNodeInfoPtr)
15755 xmlMalloc(sizeof(xmlSchemaNodeInfo));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015756 if (info == NULL) {
15757 xmlSchemaVErrMemory(vctxt,
15758 "allocating an element info", NULL);
15759 return (NULL);
15760 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000015761 vctxt->elemInfos[depth] = info;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015762 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000015763 memset(info, 0, sizeof(xmlSchemaNodeInfo));
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000015764 info->depth = depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015765
15766 return (info);
15767}
15768#endif /* ELEM_INFO_ENABLED */
15769
Daniel Veillard3646d642004-06-02 19:19:14 +000015770
15771/**
15772 * xmlSchemaFreeAttrStates:
15773 * @state: a list of attribute states
15774 *
15775 * Free the given list of attribute states
15776 *
15777 */
15778static void
15779xmlSchemaFreeAttributeStates(xmlSchemaAttrStatePtr state)
15780{
15781 xmlSchemaAttrStatePtr tmp;
15782 while (state != NULL) {
15783 tmp = state;
15784 state = state->next;
15785 xmlFree(tmp);
15786 }
15787}
15788
Daniel Veillard4255d502002-04-16 15:50:10 +000015789/**
15790 * xmlSchemaRegisterAttributes:
15791 * @ctxt: a schema validation context
15792 * @attrs: a list of attributes
15793 *
15794 * Register the list of attributes as the set to be validated on that element
15795 *
15796 * Returns -1 in case of error, 0 otherwise
15797 */
15798static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015799xmlSchemaRegisterAttributes(xmlSchemaValidCtxtPtr ctxt, xmlAttrPtr attrs)
15800{
Daniel Veillard3646d642004-06-02 19:19:14 +000015801 xmlSchemaAttrStatePtr tmp;
15802
15803 ctxt->attr = NULL;
15804 ctxt->attrTop = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000015805 while (attrs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015806 if ((attrs->ns != NULL) &&
15807 (xmlStrEqual(attrs->ns->href, xmlSchemaInstanceNs))) {
15808 attrs = attrs->next;
15809 continue;
15810 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000015811 tmp = (xmlSchemaAttrStatePtr)
15812 xmlMalloc(sizeof(xmlSchemaAttrState));
15813 if (tmp == NULL) {
15814 xmlSchemaVErrMemory(ctxt, "registering attributes", NULL);
15815 return (-1);
15816 }
Daniel Veillard3646d642004-06-02 19:19:14 +000015817 tmp->attr = attrs;
15818 tmp->state = XML_SCHEMAS_ATTR_UNKNOWN;
15819 tmp->next = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015820 tmp->decl = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000015821 if (ctxt->attr == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015822 ctxt->attr = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000015823 else
15824 ctxt->attrTop->next = tmp;
15825 ctxt->attrTop = tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015826 attrs = attrs->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000015827 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015828 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000015829}
15830
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015831#if 0 /* Currently not used */
Daniel Veillard4255d502002-04-16 15:50:10 +000015832/**
Daniel Veillard4255d502002-04-16 15:50:10 +000015833 * xmlSchemaValidateCheckNodeList
15834 * @nodelist: the list of nodes
15835 *
15836 * Check the node list is only made of text nodes and entities pointing
15837 * to text nodes
15838 *
15839 * Returns 1 if true, 0 if false and -1 in case of error
15840 */
15841static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015842xmlSchemaValidateCheckNodeList(xmlNodePtr nodelist)
15843{
Daniel Veillard4255d502002-04-16 15:50:10 +000015844 while (nodelist != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015845 if (nodelist->type == XML_ENTITY_REF_NODE) {
15846 TODO /* implement recursion in the entity content */
15847 }
15848 if ((nodelist->type != XML_TEXT_NODE) &&
15849 (nodelist->type != XML_COMMENT_NODE) &&
15850 (nodelist->type != XML_PI_NODE) &&
William M. Bracke7091952004-05-11 15:09:58 +000015851 (nodelist->type != XML_CDATA_SECTION_NODE)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015852 return (0);
15853 }
15854 nodelist = nodelist->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000015855 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015856 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +000015857}
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015858#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000015859
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015860static void
15861xmlSchemaPostSchemaAssembleFixup(xmlSchemaParserCtxtPtr ctxt)
15862{
15863 int i, nbItems;
15864 xmlSchemaTypePtr item, *items;
15865
15866
15867 /*
15868 * During the Assemble of the schema ctxt->curItems has
15869 * been filled with the relevant new items. Fix those up.
15870 */
15871 nbItems = ctxt->assemble->nbItems;
15872 items = (xmlSchemaTypePtr *) ctxt->assemble->items;
15873
15874 for (i = 0; i < nbItems; i++) {
15875 item = items[i];
15876 switch (item->type) {
15877 case XML_SCHEMA_TYPE_ATTRIBUTE:
15878 xmlSchemaAttrFixup((xmlSchemaAttributePtr) item, ctxt, NULL);
15879 break;
15880 case XML_SCHEMA_TYPE_ELEMENT:
15881 xmlSchemaRefFixupCallback((xmlSchemaElementPtr) item, ctxt,
15882 NULL, NULL, NULL);
15883 break;
15884 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
15885 xmlSchemaAttrGrpFixup((xmlSchemaAttributeGroupPtr) item,
15886 ctxt, NULL);
15887 break;
15888 case XML_SCHEMA_TYPE_GROUP:
15889 xmlSchemaGroupDefFixup(item, ctxt, NULL);
15890 default:
15891 break;
15892 }
15893 }
15894 /*
15895 * Circularity checks.
15896 */
15897 for (i = 0; i < nbItems; i++) {
15898 item = items[i];
15899 switch (item->type) {
15900 case XML_SCHEMA_TYPE_GROUP:
15901 xmlSchemaCheckGroupDefCircular(item, ctxt, NULL);
15902 break;
15903 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
15904 xmlSchemaCheckAttributeGroupCircular(
15905 (xmlSchemaAttributeGroupPtr) item, ctxt, NULL);
15906 break;
15907 default:
15908 break;
15909 }
15910 }
15911 /*
15912 * Fixup for all other item.
15913 * TODO: Hmm, not sure if starting from complex/simple types,
15914 * all subsequent items will be reached.
15915 */
15916 for (i = 0; i < nbItems; i++) {
15917 item = items[i];
15918 switch (item->type) {
15919 case XML_SCHEMA_TYPE_SIMPLE:
15920 case XML_SCHEMA_TYPE_COMPLEX:
15921 xmlSchemaTypeFixup(item, ctxt, NULL);
15922 break;
15923 default:
15924 break;
15925 }
15926 }
15927 /*
15928 * Check facet values. Note that facets are
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000015929 * hold by simple type components only (and
15930 * by complex types in the current implementation).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015931 */
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000015932 /* OLD:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015933 for (i = 0; i < nbItems; i++) {
15934 item = items[i];
15935 switch (item->type) {
15936 case XML_SCHEMA_TYPE_SIMPLE:
15937 case XML_SCHEMA_TYPE_COMPLEX:
15938 xmlSchemaCheckDefaults(item, ctxt, NULL);
15939 break;
15940 default:
15941 break;
15942 }
15943 }
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000015944 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015945 /*
15946 * Build the content model for complex types.
15947 */
15948 for (i = 0; i < nbItems; i++) {
15949 item = items[i];
15950 switch (item->type) {
15951 case XML_SCHEMA_TYPE_COMPLEX:
15952 xmlSchemaBuildContentModel(item, ctxt, NULL);
15953 break;
15954 default:
15955 break;
15956 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015957 }
15958 /*
15959 * Validate value contraint values.
15960 */
15961 for (i = 0; i < nbItems; i++) {
15962 item = items[i];
15963 switch (item->type) {
15964 case XML_SCHEMA_TYPE_ATTRIBUTE:
15965 xmlSchemaCheckAttrValConstr((xmlSchemaAttributePtr) item, ctxt, NULL);
15966 break;
15967 case XML_SCHEMA_TYPE_ELEMENT:
15968 xmlSchemaCheckElemValConstr((xmlSchemaElementPtr) item, ctxt, NULL);
15969 break;
15970 default:
15971 break;
15972 }
15973 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015974}
15975
15976/**
15977 * xmlSchemaAssembleByLocation:
15978 * @pctxt: a schema parser context
15979 * @vctxt: a schema validation context
15980 * @schema: the existing schema
15981 * @node: the node that fired the assembling
15982 * @nsName: the namespace name of the new schema
15983 * @location: the location of the schema
15984 *
15985 * Expands an existing schema by an additional schema.
15986 *
15987 * Returns 0 if the new schema is correct, a positive error code
15988 * number otherwise and -1 in case of an internal or API error.
15989 */
15990static int
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015991xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
15992 xmlSchemaPtr schema,
15993 xmlNodePtr node,
15994 const xmlChar *nsName,
15995 const xmlChar *location)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015996{
15997 const xmlChar *targetNs, *oldtns;
15998 xmlDocPtr doc, olddoc;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015999 int oldflags, ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016000 xmlNodePtr docElem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016001 xmlSchemaParserCtxtPtr pctxt;
16002
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016003 /*
16004 * This should be used:
16005 * 1. on <import>(s)
16006 * 2. if requested by the validated instance
16007 * 3. if requested via the API
16008 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016009 if ((vctxt == NULL) || (schema == NULL))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016010 return (-1);
16011 /*
16012 * Create a temporary parser context.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016013 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016014 if ((vctxt->pctxt == NULL) &&
16015 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1)) {
16016 xmlSchemaVErr(vctxt, node,
16017 XML_SCHEMAV_INTERNAL,
16018 "Internal error: xmlSchemaAssembleByLocation, "
16019 "failed to create a temp. parser context.\n",
16020 NULL, NULL);
16021 return (-1);
16022 }
16023 pctxt = vctxt->pctxt;
16024 /*
16025 * Set the counter to produce unique names for anonymous items.
16026 */
16027 pctxt->counter = schema->counter;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016028 /*
16029 * Acquire the schema document.
16030 */
16031 ret = xmlSchemaAcquireSchemaDoc(pctxt, schema, node,
16032 nsName, location, &doc, &targetNs, 0);
16033 if (ret != 0) {
16034 if (doc != NULL)
16035 xmlFreeDoc(doc);
16036 } else if (doc != NULL) {
16037 docElem = xmlDocGetRootElement(doc);
16038 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016039 * Create new assemble info.
16040 */
16041 if (pctxt->assemble == NULL) {
16042 pctxt->assemble = xmlSchemaNewAssemble();
16043 if (pctxt->assemble == NULL) {
16044 xmlSchemaVErrMemory(vctxt,
16045 "Memory error: xmlSchemaAssembleByLocation, "
16046 "allocating assemble info", NULL);
16047 xmlFreeDoc(doc);
16048 return (-1);
16049 }
16050 }
16051 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016052 * Save and reset the context & schema.
16053 */
16054 oldflags = schema->flags;
16055 oldtns = schema->targetNamespace;
16056 olddoc = schema->doc;
16057
16058 xmlSchemaClearSchemaDefaults(schema);
16059 schema->targetNamespace = targetNs;
16060 /* schema->nbCurItems = 0; */
16061 pctxt->schema = schema;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016062 pctxt->ctxtType = NULL;
16063 pctxt->parentItem = NULL;
16064
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016065 xmlSchemaParseSchemaDefaults(pctxt, schema, docElem);
16066 xmlSchemaParseSchemaTopLevel(pctxt, schema, docElem->children);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016067 xmlSchemaPostSchemaAssembleFixup(pctxt);
16068 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016069 * Set the counter of items.
16070 */
16071 schema->counter = pctxt->counter;
16072 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016073 * Free the list of assembled components.
16074 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016075 pctxt->assemble->nbItems = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016076 /*
16077 * Restore the context & schema.
16078 */
16079 schema->flags = oldflags;
16080 schema->targetNamespace = oldtns;
16081 schema->doc = olddoc;
16082 ret = pctxt->err;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016083 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016084 return (ret);
16085}
16086
16087/**
16088 * xmlSchemaAssembleByXSIAttr:
16089 * @vctxt: a schema validation context
16090 * @xsiAttr: an xsi attribute
16091 * @noNamespace: whether a schema with no target namespace is exptected
16092 *
16093 * Expands an existing schema by an additional schema using
16094 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
16095 * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
16096 * must be set to 1.
16097 *
16098 * Returns 0 if the new schema is correct, a positive error code
16099 * number otherwise and -1 in case of an internal or API error.
16100 */
16101static int
16102xmlSchemaAssembleByXSIAttr(xmlSchemaValidCtxtPtr vctxt,
16103 xmlAttrPtr xsiAttr,
16104 int noNamespace)
16105{
16106 xmlChar *value;
16107 const xmlChar *cur, *end;
16108 const xmlChar *nsname = NULL, *location;
16109 int count = 0;
16110 int ret = 0;
16111
16112 if (xsiAttr == NULL) {
16113 xmlSchemaVCustomErr(vctxt, XML_SCHEMAV_INTERNAL,
16114 NULL, NULL,
16115 "Internal error: xmlSchemaAssembleByXSIAttr, "
16116 "bad arguments", NULL);
16117 return (-1);
16118 }
16119 /*
16120 * Parse the value; we will assume an even number of values
16121 * to be given (this is how Xerces and XSV work).
16122 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016123 value = xmlNodeGetContent((xmlNodePtr) xsiAttr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016124 cur = value;
16125 do {
16126 if (noNamespace != 1) {
16127 /*
16128 * Get the namespace name.
16129 */
16130 while (IS_BLANK_CH(*cur))
16131 cur++;
16132 end = cur;
16133 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
16134 end++;
16135 if (end == cur)
16136 break;
16137 count++;
16138 nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
16139 cur = end;
16140 }
16141 /*
16142 * Get the URI.
16143 */
16144 while (IS_BLANK_CH(*cur))
16145 cur++;
16146 end = cur;
16147 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
16148 end++;
16149 if (end == cur)
16150 break;
16151 count++;
16152 location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016153 cur = end;
16154 ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016155 xsiAttr->parent, nsname, location);
16156 if (ret == -1) {
16157 xmlSchemaVCustomErr(vctxt,
16158 XML_SCHEMAV_INTERNAL,
16159 (xmlNodePtr) xsiAttr, NULL,
16160 "Internal error: xmlSchemaAssembleByXSIAttr, "
16161 "assembling schemata", NULL);
16162 if (value != NULL)
16163 xmlFree(value);
16164 return (-1);
16165 }
16166 } while (*cur != 0);
16167 if (value != NULL)
16168 xmlFree(value);
16169 return (ret);
16170}
16171
16172/**
16173 * xmlSchemaAssembleByXSIElem:
16174 * @vctxt: a schema validation context
16175 * @elem: an element node possibly holding xsi attributes
16176 * @noNamespace: whether a schema with no target namespace is exptected
16177 *
16178 * Assembles an existing schema by an additional schema using
16179 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attributes
16180 * of the given @elem.
16181 *
16182 * Returns 0 if the new schema is correct, a positive error code
16183 * number otherwise and -1 in case of an internal or API error.
16184 */
16185static int
16186xmlSchemaAssembleByXSIElem(xmlSchemaValidCtxtPtr vctxt,
16187 xmlNodePtr elem)
16188{
16189 int ret = 0, retNs = 0;
16190 xmlAttrPtr attr;
16191
16192 attr = xmlHasNsProp(elem, BAD_CAST "schemaLocation", xmlSchemaInstanceNs);
16193 if (attr != NULL) {
16194 retNs = xmlSchemaAssembleByXSIAttr(vctxt, attr, 0);
16195 if (retNs == -1)
16196 return (-1);
16197 }
16198 attr = xmlHasNsProp(elem, BAD_CAST "noNamespaceSchemaLocation", xmlSchemaInstanceNs);
16199 if (attr != NULL) {
16200 ret = xmlSchemaAssembleByXSIAttr(vctxt, attr, 1);
16201 if (ret == -1)
16202 return (-1);
16203 }
16204 if (retNs != 0)
16205 return (retNs);
16206 else
16207 return (ret);
16208}
16209
Daniel Veillard4255d502002-04-16 15:50:10 +000016210/**
Daniel Veillard4255d502002-04-16 15:50:10 +000016211 * xmlSchemaValidateCallback:
16212 * @ctxt: a schema validation context
16213 * @name: the name of the element detected (might be NULL)
16214 * @type: the type
16215 *
16216 * A transition has been made in the automata associated to an element
16217 * content model
16218 */
16219static void
16220xmlSchemaValidateCallback(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016221 const xmlChar * name ATTRIBUTE_UNUSED,
16222 xmlSchemaTypePtr type, xmlNodePtr node)
16223{
Daniel Veillard4255d502002-04-16 15:50:10 +000016224 xmlSchemaTypePtr oldtype = ctxt->type;
16225 xmlNodePtr oldnode = ctxt->node;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016226
Daniel Veillard4255d502002-04-16 15:50:10 +000016227#ifdef DEBUG_CONTENT
Daniel Veillard8651f532002-04-17 09:06:27 +000016228 xmlGenericError(xmlGenericErrorContext,
16229 "xmlSchemaValidateCallback: %s, %s, %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016230 name, type->name, node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +000016231#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016232 /*
16233 * @type->type will be XML_SCHEMA_TYPE_ANY or XML_SCHEMA_TYPE_ELEMENT.
16234 */
Daniel Veillard4255d502002-04-16 15:50:10 +000016235 ctxt->type = type;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016236 ctxt->node = node;
16237 ctxt->cur = node->children;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016238
16239#ifdef ELEM_INFO_ENABLED
16240 xmlSchemaBeginElement(ctxt);
16241#endif
16242
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016243 /*
16244 * Assemble new schemata using xsi.
16245 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016246 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016247 int ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016248
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016249 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
16250 if (ret == -1) {
16251 xmlSchemaVCustomErr(ctxt,
16252 XML_SCHEMAV_INTERNAL,
16253 ctxt->node, NULL,
16254 "Internal error: xmlSchemaValidateElement, "
16255 "assembling schema by xsi", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016256 goto leave;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016257 }
16258 /*
16259 * NOTE: We won't react on schema parser errors here.
16260 * TODO: But a warning would be nice.
16261 */
16262 }
16263 switch (type->type) {
16264 case XML_SCHEMA_TYPE_ELEMENT: {
16265 /*
16266 * NOTE: The build of the content model
16267 * (xmlSchemaBuildAContentModel) ensures that the element
16268 * declaration (and not a reference to it) will be given.
16269 */
16270 if (((xmlSchemaElementPtr) ctxt->type)->ref != NULL) {
16271 /*
16272 * This is paranoid coding ;-)... it should not
16273 * happen here any more.
16274 */
16275 xmlSchemaVCustomErr(ctxt,
16276 XML_SCHEMAV_INTERNAL,
16277 node, NULL,
16278 "Internal error: xmlSchemaValidateCallback, "
16279 "element declaration 'reference' encountered, "
16280 "but an element declaration was expected",
16281 NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016282 goto leave;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016283 }
16284 xmlSchemaValidateElementByDeclaration(ctxt,
16285 (xmlSchemaElementPtr) type);
16286 break;
16287 }
16288 case XML_SCHEMA_TYPE_ANY:
16289 xmlSchemaValidateElementByWildcard(ctxt, type);
16290 break;
16291 default:
16292 break;
16293 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016294leave:
16295
16296#ifdef ELEM_INFO_ENABLED
16297 xmlSchemaEndElement(ctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016298#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000016299 ctxt->type = oldtype;
16300 ctxt->node = oldnode;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016301}
Daniel Veillard4255d502002-04-16 15:50:10 +000016302
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016303static int
16304xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
16305 const xmlChar *value,
16306 xmlSchemaValPtr *val,
16307 xmlNodePtr node)
16308{
16309 int ret;
16310
16311 ret = xmlValidateQName(value, 1);
16312 if (ret != 0)
16313 return (ret);
16314
16315 {
16316 xmlChar *uri = NULL;
16317 xmlChar *local = NULL;
16318 xmlChar *prefix;
16319
16320 local = xmlSplitQName2(value, &prefix);
16321 if (prefix != NULL) {
16322 xmlNsPtr ns;
16323
16324 /*
16325 * TODO: Make this streamable.
16326 */
16327 if ((node == NULL) || (node->doc == NULL)) {
16328 xmlFree(prefix);
16329 xmlFree(local);
16330 return (3);
16331 }
16332
16333 ns = xmlSearchNs(node->doc, node, prefix);
16334 if (ns == NULL) {
16335 xmlFree(prefix);
16336 xmlFree(local);
16337 return (1);
16338 }
16339 }
16340 if (prefix != NULL) {
16341 if (xmlHashLookup2(vctxt->schema->notaDecl, local, uri) == NULL)
16342 ret = 1;
16343 } else if (xmlHashLookup2(vctxt->schema->notaDecl, value,
16344 NULL) == NULL)
16345 ret = 1;
16346
16347 if ((ret == 0) && (val != NULL)) {
16348 if (prefix != NULL) {
16349 (*val) = xmlSchemaNewNOTATIONValue(BAD_CAST local,
16350 BAD_CAST xmlStrdup(uri));
16351 local = NULL;
16352 } else
16353 (*val) = xmlSchemaNewNOTATIONValue(BAD_CAST xmlStrdup(value),
16354 NULL);
16355 if (*val == NULL)
16356 ret = -1;
16357 }
16358 if (local != NULL)
16359 xmlFree(local);
16360 }
16361
16362 return (ret);
16363}
16364
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016365static xmlSchemaTypePtr
16366xmlSchemaGetSimpleContentType(xmlSchemaTypePtr complexType)
16367{
16368 xmlSchemaTypePtr ret;
16369
16370 if (complexType->type != XML_SCHEMA_TYPE_COMPLEX)
16371 return (NULL);
16372 if (complexType->contentTypeDef != NULL)
16373 return (complexType->contentTypeDef);
16374 /*
16375 * TODO: This is only a workaround until the simple content
16376 * type is computed for complex types with simple content.
16377 */
16378 ret = complexType->baseType;
16379 while (ret != NULL) {
16380 if (IS_SIMPLE_TYPE(ret))
16381 return (ret);
16382 if (ret->builtInType == XML_SCHEMAS_ANYTYPE)
16383 return (NULL);
16384 if ((ret->type == XML_SCHEMA_TYPE_COMPLEX) &&
16385 (ret->contentTypeDef != NULL))
16386 ret = ret->contentTypeDef;
16387 else
16388 ret = ret->baseType;
16389 }
16390 return (ret);
16391}
16392
Daniel Veillard01fa6152004-06-29 17:04:39 +000016393/**
16394 * xmlSchemaValidateSimpleTypeValue:
16395 * @ctxt: a schema validation context
16396 * @value: the value to be validated
16397 * @fireErrors: shall errors be reported?
16398 * @applyFacets: shall facets be applied?
Daniel Veillardc0826a72004-08-10 14:17:33 +000016399 * @normalize: shall the value be normalized?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016400 * @checkNodes: shall the content nodes be checked?
Daniel Veillard01fa6152004-06-29 17:04:39 +000016401 *
16402 * Validates a value by the given type (user derived or built-in).
16403 *
16404 * Returns 0 if the value is valid, a positive error code
16405 * number otherwise and -1 in case of an internal or API error.
Daniel Veillard01fa6152004-06-29 17:04:39 +000016406 */
16407static int
16408xmlSchemaValidateSimpleTypeValue(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016409 xmlSchemaTypePtr type,
16410 const xmlChar *value,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016411 int fireErrors,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016412 int applyFacets,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016413 int normalize,
16414 int checkNodes)
Daniel Veillard01fa6152004-06-29 17:04:39 +000016415{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016416 xmlNodePtr node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000016417 int ret = 0;
16418 xmlChar *normValue = NULL;
16419 int wtsp;
16420
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016421 node = ctxt->node;
16422 /* Save the current whitespace normalization type. */
Daniel Veillardc0826a72004-08-10 14:17:33 +000016423 wtsp = ctxt->valueWS;
16424 /*
16425 * Normalize the value.
16426 */
16427 if (normalize &&
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000016428 (ctxt->valueWS != XML_SCHEMAS_FACET_COLLAPSE)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000016429 int norm = xmlSchemaGetWhiteSpaceFacetValue(type);
16430
16431 if ((norm != -1) && (norm > ctxt->valueWS)) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000016432 if (norm == XML_SCHEMAS_FACET_COLLAPSE)
Daniel Veillardc0826a72004-08-10 14:17:33 +000016433 normValue = xmlSchemaCollapseString(value);
16434 else
16435 normValue = xmlSchemaWhiteSpaceReplace(value);
16436 ctxt->valueWS = norm;
16437 if (normValue != NULL)
16438 value = (const xmlChar *) normValue;
16439 }
16440 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016441 /*
16442 * The nodes of a content must be checked only once,
16443 * this is not working since list types will fire this
16444 * multiple times.
16445 */
16446 if ((checkNodes == 1) && (ctxt->cur != NULL)) {
16447 xmlNodePtr cur = ctxt->cur;
16448
16449 do {
16450 switch (cur->type) {
16451 case XML_TEXT_NODE:
16452 case XML_CDATA_SECTION_NODE:
16453 case XML_PI_NODE:
16454 case XML_COMMENT_NODE:
16455 case XML_XINCLUDE_START:
16456 case XML_XINCLUDE_END:
16457 break;
16458 case XML_ENTITY_REF_NODE:
16459 case XML_ENTITY_NODE:
16460 /* TODO: Scour the entities for illegal nodes. */
16461 TODO break;
16462 case XML_ELEMENT_NODE: {
16463 /* NOTE: Changed to an internal error, since the
16464 * existence of an element node will be already checked in
16465 * xmlSchemaValidateElementBySimpleType and in
16466 * xmlSchemaValidateElementByComplexType.
16467 */
16468 xmlSchemaVCustomErr(ctxt,
16469 XML_SCHEMAV_INTERNAL,
16470 /* XML_SCHEMAS_ERR_INVALIDELEM, */
16471 node, type,
16472 "Element '%s' found in simple type content",
16473 cur->name);
16474 return (XML_SCHEMAV_INTERNAL);
16475 }
16476 case XML_ATTRIBUTE_NODE:
16477 case XML_DOCUMENT_NODE:
16478 case XML_DOCUMENT_TYPE_NODE:
16479 case XML_DOCUMENT_FRAG_NODE:
16480 case XML_NOTATION_NODE:
16481 case XML_HTML_DOCUMENT_NODE:
16482 case XML_DTD_NODE:
16483 case XML_ELEMENT_DECL:
16484 case XML_ATTRIBUTE_DECL:
16485 case XML_ENTITY_DECL:
16486 case XML_NAMESPACE_DECL:
16487#ifdef LIBXML_DOCB_ENABLED
16488 case XML_DOCB_DOCUMENT_NODE:
16489#endif
16490 xmlSchemaVCustomErr(ctxt,
16491 XML_SCHEMAV_INTERNAL,
16492 /* XML_SCHEMAS_ERR_INVALIDELEM, */
16493 node, NULL,
16494 "Node of unexpected type found in simple type content",
16495 NULL);
16496 return (XML_SCHEMAV_INTERNAL);
16497 }
16498 cur = cur->next;
16499 } while (cur != NULL);
16500 }
16501
William M. Brack2f2a6632004-08-20 23:09:47 +000016502 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016503 xmlSchemaTypePtr simpType, anyType;
William M. Brack2f2a6632004-08-20 23:09:47 +000016504
16505 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
16506
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016507 simpType = xmlSchemaGetSimpleContentType(type);
16508 if (simpType == NULL) {
16509 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
16510 "Internal error: xmlSchemaValidateSimpleTypeValue, "
16511 "failed to obtain the simple content type of the complex "
16512 "type '%s'\n",
16513 type->name, NULL);
16514 return (-1);
William M. Brack2f2a6632004-08-20 23:09:47 +000016515 }
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016516 ret = xmlSchemaValidateSimpleTypeValue(ctxt, simpType, value, 1, 0, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000016517 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016518 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000016519 "Internal error: xmlSchemaValidateSimpleTypeValue, "
16520 "validating complex type '%s'\n",
16521 type->name, NULL);
16522 } else if ((ret == 0) && (applyFacets) && (type->facetSet != NULL)) {
16523 /*
16524 * Check facets.
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016525 *
16526 * TODO: This is somehow not nice, since if an error occurs
William M. Brack2f2a6632004-08-20 23:09:47 +000016527 * the reported type will be the complex type; the spec
16528 * wants a simple type to be created on the complex type
16529 * if it has a simple content. For now we have to live with
16530 * it.
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016531 */
16532 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000016533 value, 0, fireErrors);
16534 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016535 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000016536 "Internal error: xmlSchemaValidateSimpleTypeValue, "
16537 "validating facets of complex type '%s'\n",
16538 type->name, NULL);
16539 } else if (ret > 0) {
16540 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
William M. Brack2f2a6632004-08-20 23:09:47 +000016541 if (fireErrors)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016542 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
William M. Brack2f2a6632004-08-20 23:09:47 +000016543 }
16544 }
16545 } else if (type->type == XML_SCHEMA_TYPE_BASIC) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016546
16547 if (ctxt->value != NULL) {
16548 xmlSchemaFreeValue(ctxt->value);
16549 ctxt->value = NULL;
16550 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016551 /*
16552 * STREAM-READ-CHILDREN.
16553 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016554 if ((type->builtInType == XML_SCHEMAS_NOTATION) &&
16555 (ctxt->schema != NULL)) {
16556 /*
16557 * NOTATIONs need to be processed here, since they need
16558 * to lookup in the hashtable of NOTATION declarations.
16559 */
16560 ret = xmlSchemaValidateNotation(ctxt, value, &(ctxt->value), node);
16561 } else
16562 ret = xmlSchemaValPredefTypeNodeNoNorm(type, value, &(ctxt->value), node);
Daniel Veillardc0826a72004-08-10 14:17:33 +000016563 if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016564 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
16565 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
16566 else
16567 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000016568 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016569 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016570 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016571 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016572 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000016573 "validating built-in type '%s'\n", type->name, NULL);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000016574 } else if ((ctxt->value == NULL) &&
16575 (type->builtInType == XML_SCHEMAS_STRING) &&
16576 (ctxt->nodeInfo != NULL) &&
16577 (ctxt->nodeInfo->flags & XML_SCHEMA_ELEM_INFO_VALUE_NEEDED)) {
16578#ifdef IDC_VALUE_SUPPORT
16579 xmlChar *valdup;
16580 /*
16581 * Create a precomputed string value for "string" as well if
16582 * requested.
16583 */
16584 valdup = xmlStrdup(value);
16585 ctxt->value = xmlSchemaNewStringValue(XML_SCHEMAS_STRING,
16586 BAD_CAST valdup);
16587 if ((valdup != NULL) && (ctxt->value == NULL))
16588 xmlFree(valdup);
16589#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +000016590 }
16591 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
16592 /* 1.2.1 if {variety} is ·atomic· then the string must ·match·
16593 * a literal in the ·lexical space· of {base type definition}
16594 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016595 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type->baseType, value, 0, 0, 0, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016596 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016597 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016598 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000016599 "validating atomic simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000016600 type->name, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000016601 } else if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016602 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000016603 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016604 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillardc0826a72004-08-10 14:17:33 +000016605 } else if ((applyFacets) && (type->facetSet != NULL)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016606 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000016607 * Check facets.
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016608 */
16609 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016610 value, 0, fireErrors);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016611 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016612 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016613 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000016614 "validating facets of atomic simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000016615 type->name, NULL);
16616 } else if (ret > 0) {
16617 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000016618 /*
16619 Disabled, since the facet validation already reports errors.
16620 if (fireErrors)
16621 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
16622 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000016623 }
16624 }
16625 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
16626
16627 xmlSchemaTypePtr tmpType;
16628 const xmlChar *cur, *end;
16629 xmlChar *tmp;
Daniel Veillardc0826a72004-08-10 14:17:33 +000016630 unsigned long len = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016631
16632 /* 1.2.2 if {variety} is ·list· then the string must be a sequence
16633 * of white space separated tokens, each of which ·match·es a literal
16634 * in the ·lexical space· of {item type definition}
16635 */
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +000016636
Kasimier T. Buchcikde938cd2005-01-13 12:25:57 +000016637 if (value == NULL)
16638 value = BAD_CAST "";
Daniel Veillardc0826a72004-08-10 14:17:33 +000016639 tmpType = xmlSchemaGetListSimpleTypeItemType(type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016640 cur = value;
16641 do {
16642 while (IS_BLANK_CH(*cur))
16643 cur++;
16644 end = cur;
16645 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
16646 end++;
16647 if (end == cur)
16648 break;
16649 tmp = xmlStrndup(cur, end - cur);
16650 len++;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016651 ret = xmlSchemaValidateSimpleTypeValue(ctxt, tmpType, tmp, 0, 1, 0, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016652 xmlFree(tmp);
Daniel Veillardc0826a72004-08-10 14:17:33 +000016653 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016654 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016655 "Internal error: xmlSchemaValidateSimpleTypeValue, "
16656 "validating an item of list simple type '%s'\n",
16657 type->name, NULL);
16658 break;
16659 } else if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016660 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
Daniel Veillardc0826a72004-08-10 14:17:33 +000016661 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016662 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016663 break;
Daniel Veillardc0826a72004-08-10 14:17:33 +000016664 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000016665 cur = end;
16666 } while (*cur != 0);
16667 /*
16668 * Check facets.
16669 */
16670 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016671 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016672 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000016673 "validating list simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000016674 type->name, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000016675 } else if ((ret == 0) && (applyFacets)) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016676 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016677 value, len, fireErrors);
16678 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016679 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016680 "Internal error: xmlSchemaValidateSimpleTypeValue, "
16681 "validating facets of list simple type '%s'\n",
16682 type->name, NULL);
16683 } else if (ret > 0) {
16684 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016685 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000016686 Disabled, since the facet validation already reports errors.
16687 if (fireErrors)
16688 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016689 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000016690 }
16691
Daniel Veillard01fa6152004-06-29 17:04:39 +000016692 }
16693 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
16694 xmlSchemaTypeLinkPtr memberLink;
16695
16696 /*
16697 * TODO: For all datatypes ·derived· by ·union· whiteSpace does
16698 * not apply directly; however, the normalization behavior of ·union·
16699 * types is controlled by the value of whiteSpace on that one of the
16700 * ·memberTypes· against which the ·union· is successfully validated.
16701 *
16702 * This means that the value is normalized by the first validating
16703 * member type, then the facets of the union type are applied. This
16704 * needs changing of the value!
16705 */
16706
16707 /*
16708 * 1.2.3 if {variety} is ·union· then the string must ·match· a
16709 * literal in the ·lexical space· of at least one member of
16710 * {member type definitions}
16711 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000016712#ifdef DEBUG_UNION_VALIDATION
16713 printf("Union ST : '%s'\n", (const char *) type->name);
16714 printf(" fireErrors : %d\n", fireErrors);
16715 printf(" applyFacets: %d\n", applyFacets);
16716#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +000016717 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
16718 if (memberLink == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016719 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016720 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000016721 "union simple type '%s' has no member types\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000016722 type->name, NULL);
16723 ret = -1;
16724 }
16725 if (ret == 0) {
16726 while (memberLink != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016727 ret = xmlSchemaValidateSimpleTypeValue(ctxt, memberLink->type,
16728 value, 0, 1, 1, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016729 if ((ret <= 0) || (ret == 0))
16730 break;
16731 memberLink = memberLink->next;
16732 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000016733 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016734 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016735 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000016736 "validating members of union simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000016737 type->name, NULL);
16738 } else if (ret > 0) {
16739 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
Daniel Veillardc0826a72004-08-10 14:17:33 +000016740 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016741 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillardc0826a72004-08-10 14:17:33 +000016742 }
16743 }
16744 /*
16745 * Apply facets (pattern, enumeration).
16746 */
16747 if ((ret == 0) && (applyFacets) && (type->facetSet != NULL)) {
16748 int mws;
16749 /*
16750 * The normalization behavior of ·union· types is controlled by
16751 * the value of whiteSpace on that one of the ·memberTypes·
16752 * against which the ·union· is successfully validated.
16753 */
16754 if (normValue != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016755 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016756 "Internal error: xmlSchemaValidateSimpleTypeValue, "
16757 "the value was already normalized for the union simple "
16758 "type '%s'.\n", type->name, NULL);
16759 }
16760 mws = xmlSchemaGetWhiteSpaceFacetValue(memberLink->type);
16761 if (mws > ctxt->valueWS) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000016762 if (mws == XML_SCHEMAS_FACET_COLLAPSE)
Daniel Veillardc0826a72004-08-10 14:17:33 +000016763 normValue = xmlSchemaCollapseString(value);
16764 else
16765 normValue = xmlSchemaWhiteSpaceReplace(value);
16766 if (normValue != NULL)
16767 value = (const xmlChar *) normValue;
16768 }
16769
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016770 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016771 value, 0, fireErrors);
16772 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016773 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016774 "Internal error: xmlSchemaValidateSimpleTypeValue, "
16775 "validating facets of union simple type '%s'\n",
16776 type->name, NULL);
16777 } else if (ret > 0) {
16778 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
16779 /*
16780 if (fireErrors)
16781 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
16782 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000016783 }
16784 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000016785 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000016786 ctxt->valueWS = wtsp;
16787 if (normValue != NULL)
16788 xmlFree(normValue);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016789 return (ret);
16790}
16791
16792/**
16793 * xmlSchemaValidateSimpleTypeElement:
16794 * @ctxt: a schema validation context
16795 * @node: the element node to be validated.
16796 *
16797 * Validate the element against a simple type.
16798 *
16799 * Returns 0 if the element is valid, a positive error code
16800 * number otherwise and -1 in case of an internal or API error.
16801 */
16802static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016803xmlSchemaValidateElementBySimpleType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016804 xmlSchemaTypePtr type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000016805 int isNil,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016806 int valSimpleContent)
Daniel Veillard01fa6152004-06-29 17:04:39 +000016807{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016808 xmlSchemaTypePtr oldtype;
16809 xmlNodePtr node;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016810 xmlAttrPtr attr;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016811 xmlNodePtr cur;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016812 int ret = 0, retval = 0;
16813
Daniel Veillard01fa6152004-06-29 17:04:39 +000016814 if ((ctxt == NULL) || (type == NULL)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016815 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_INTERNAL, NULL, NULL,
16816 "Internal error: xmlSchemaValidateElementBySimpleType, "
16817 "bad arguments", NULL);
16818 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016819 }
16820
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016821 oldtype = ctxt->type;
16822 node = ctxt->node;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016823 /*
16824 * cvc-type: 3.1.2 The element information item must have no element
16825 * information item [children].
16826 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016827 /*
16828 * STREAM: Child nodes are processed.
16829 */
16830 cur = node->children;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016831 while (cur != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016832 /*
16833 * TODO: Entities, will they produce elements as well?
16834 */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016835 if (cur->type == XML_ELEMENT_NODE) {
16836 xmlSchemaVCustomErr(ctxt,
16837 XML_SCHEMAV_CVC_TYPE_3_1_2,
16838 node, type,
16839 "No element content allowed", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016840 ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016841 }
16842 cur = cur->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016843 }
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016844
Daniel Veillard01fa6152004-06-29 17:04:39 +000016845 /*
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016846 * cvc-type 3.1.1:
16847 *
16848 * The attributes of must be empty, excepting those whose namespace name
16849 * is identical to http://www.w3.org/2001/XMLSchema-instance and whose local
16850 * name is one of type, nil, schemaLocation or noNamespaceSchemaLocation.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016851 */
16852 /*
16853 * STREAM: Attribute nodes are processed.
16854 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000016855 attr = node->properties;
16856 while (attr != NULL) {
16857 if ((attr->ns == NULL) ||
16858 (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
16859 ((!xmlStrEqual(attr->name, BAD_CAST "type")) &&
16860 (!xmlStrEqual(attr->name, BAD_CAST "nil")) &&
16861 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation")) &&
16862 (!xmlStrEqual
16863 (attr->name, BAD_CAST "noNamespaceSchemaLocation")))) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016864 xmlSchemaVIllegalAttrErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016865 XML_SCHEMAV_CVC_TYPE_3_1_1, attr);
16866 ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016867 }
16868 attr = attr->next;
16869 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016870 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016871 * This will skip validation if the type is 'anySimpleType' and
16872 * if the value was already validated (e.g. default values).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016873 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000016874 if ((! isNil) &&
16875 (valSimpleContent == 1) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016876 ((type->type != XML_SCHEMA_TYPE_BASIC) ||
16877 (type->builtInType != XML_SCHEMAS_ANYSIMPLETYPE))) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016878 xmlChar *value;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016879
16880 value = xmlNodeGetContent(node);
16881 /*
16882 * NOTE: This call will not check the content nodes, since
16883 * this should be checked here already.
16884 */
16885 retval = xmlSchemaValidateSimpleTypeValue(ctxt, type, value,
16886 1, 1, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000016887 if (value != NULL)
16888 xmlFree(value);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016889 if (retval != 0)
16890 ret = retval;
William M. Brack2f2a6632004-08-20 23:09:47 +000016891 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016892 ctxt->type = oldtype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016893 return (ret);
16894}
Daniel Veillard4255d502002-04-16 15:50:10 +000016895
16896/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016897 * xmlSchemaValQNameAcquire:
16898 * @value: the lexical represantation of the QName value
16899 * @node: the node to search for the corresponding namespace declaration
16900 * @nsName: the resulting namespace name if found
16901 *
16902 * Checks that a value conforms to the lexical space of the type QName;
16903 * if valid, the corresponding namespace name is searched and retured
16904 * as a copy in @nsName. The local name is returned in @localName as
16905 * a copy.
16906 *
16907 * Returns 0 if valid, 1 if not valid by type, 2 if no corresponding
16908 * namespace declaration was found in scope; -1 in case of an internal or
16909 * API error.
16910 */
16911static int
16912xmlSchemaValQNameAcquire(const xmlChar *value, xmlNodePtr node,
16913 xmlChar **nsName, xmlChar **localName)
16914{
16915 int ret;
16916 xmlChar *local = NULL;
16917
16918 if ((nsName == NULL) || (localName == NULL) || (node == NULL))
16919 return (-1);
16920 *nsName = NULL;
16921 *localName = NULL;
16922 ret = xmlValidateQName(value, 1);
16923 if (ret == 0) {
16924 xmlChar *prefix;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016925 xmlNsPtr ns;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016926
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016927 /*
16928 * NOTE: xmlSplitQName2 will return a duplicated
16929 * string.
16930 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016931 local = xmlSplitQName2(value, &prefix);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016932 if (local == NULL)
16933 local = xmlStrdup(value);
16934 ns = xmlSearchNs(node->doc, node, prefix);
16935 /*
16936 * A namespace need not to be found if the prefix is NULL.
16937 */
16938 if (ns != NULL) {
16939 /*
16940 * TODO: Is it necessary to duplicate the URI here?
16941 */
16942 *nsName = xmlStrdup(ns->href);
16943 } else if (prefix != NULL) {
16944 xmlFree(prefix);
16945 if (local != NULL)
16946 xmlFree(local);
16947 return (2);
16948 }
16949 *localName = local;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016950 if (prefix != NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016951 xmlFree(prefix);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016952 } else
16953 return (1);
16954 return (ret);
16955}
16956
16957/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016958 * xmlSchemaHasElemContent:
16959 * @node: the node
16960 *
16961 * Scours the content of the given node for element
16962 * nodes.
16963 *
16964 * Returns 1 if an element node is found,
16965 * 0 otherwise.
16966 */
16967static int
16968xmlSchemaHasElemContent(xmlNodePtr node)
16969{
16970 if (node == NULL)
16971 return (0);
16972 node = node->children;
16973 while (node != NULL) {
16974 if (node->type == XML_ELEMENT_NODE)
16975 return (1);
16976 node = node->next;
16977 }
16978 return (0);
16979}
16980/**
16981 * xmlSchemaHasElemOrCharContent:
16982 * @node: the node
16983 *
16984 * Scours the content of the given node for element
16985 * and character nodes.
16986 *
16987 * Returns 1 if an element or character node is found,
16988 * 0 otherwise.
16989 */
16990static int
16991xmlSchemaHasElemOrCharContent(xmlNodePtr node)
16992{
16993 if (node == NULL)
16994 return (0);
16995 node = node->children;
16996 while (node != NULL) {
16997 switch (node->type) {
16998 case XML_ELEMENT_NODE:
16999 /*
17000 * TODO: Ask Daniel if these are all character nodes.
17001 */
17002 case XML_TEXT_NODE:
17003 case XML_CDATA_SECTION_NODE:
17004 /*
17005 * TODO: How XML_ENTITY_NODEs evaluated?
17006 */
17007 case XML_ENTITY_REF_NODE:
17008 case XML_ENTITY_NODE:
17009 return (1);
17010 break;
17011 default:
17012 break;
17013 }
17014 node = node->next;
17015 }
17016 return (0);
17017}
17018
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017019/************************************************************************
17020 * *
17021 * Identity-constraints (IDC) *
17022 * *
17023 ************************************************************************/
17024
17025#ifdef IDC_ENABLED
17026
17027/**
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017028 * xmlSchemaAugmentIDC:
17029 * @idcDef: the IDC definition
17030 *
17031 * Creates an augmented IDC definition item.
17032 *
17033 * Returns the item, or NULL on internal errors.
17034 */
17035static void
17036xmlSchemaAugmentIDC(xmlSchemaIDCPtr idcDef,
17037 xmlSchemaValidCtxtPtr vctxt)
17038{
17039 xmlSchemaIDCAugPtr aidc;
17040
17041 aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
17042 if (aidc == NULL) {
17043 xmlSchemaVErrMemory(vctxt,
17044 "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
17045 NULL);
17046 return;
17047 }
17048 aidc->bubbleDepth = -1;
17049 aidc->def = idcDef;
17050 aidc->next = NULL;
17051 if (vctxt->aidcs == NULL)
17052 vctxt->aidcs = aidc;
17053 else {
17054 aidc->next = vctxt->aidcs;
17055 vctxt->aidcs = aidc;
17056 }
17057}
17058
17059/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017060 * xmlSchemaIDCNewBinding:
17061 * @idcDef: the IDC definition of this binding
17062 *
17063 * Creates a new IDC binding.
17064 *
17065 * Returns the new binding in case of succeeded, NULL on internal errors.
17066 */
17067static xmlSchemaPSVIIDCBindingPtr
17068xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
17069{
17070 xmlSchemaPSVIIDCBindingPtr ret;
17071
17072 ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
17073 sizeof(xmlSchemaPSVIIDCBinding));
17074 if (ret == NULL) {
17075 xmlSchemaVErrMemory(NULL,
17076 "allocating a PSVI IDC binding item", NULL);
17077 return (NULL);
17078 }
17079 memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
17080 ret->definition = idcDef;
17081 return (ret);
17082}
17083
17084/**
17085 * xmlSchemaIDCStoreNodeTableItem:
17086 * @vctxt: the WXS validation context
17087 * @item: the IDC node table item
17088 *
17089 * The validation context is used to store an IDC node table items.
17090 * They are stored to avoid copying them if IDC node-tables are merged
17091 * with corresponding parent IDC node-tables (bubbling).
17092 *
17093 * Returns 0 if succeeded, -1 on internal errors.
17094 */
17095static int
17096xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
17097 xmlSchemaPSVIIDCNodePtr item)
17098{
17099 /*
17100 * Add to gobal list.
17101 */
17102 if (vctxt->idcNodes == NULL) {
17103 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
17104 xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
17105 if (vctxt->idcNodes == NULL) {
17106 xmlSchemaVErrMemory(vctxt,
17107 "allocating the IDC node table item list", NULL);
17108 return (-1);
17109 }
17110 vctxt->sizeIdcNodes = 20;
17111 } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
17112 vctxt->sizeIdcNodes *= 2;
17113 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
17114 xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
17115 sizeof(xmlSchemaPSVIIDCNodePtr));
17116 if (vctxt->idcNodes == NULL) {
17117 xmlSchemaVErrMemory(vctxt,
17118 "re-allocating the IDC node table item list", NULL);
17119 return (-1);
17120 }
17121 }
17122 vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
17123
17124 return (0);
17125}
17126
17127/**
17128 * xmlSchemaIDCStoreKey:
17129 * @vctxt: the WXS validation context
17130 * @item: the IDC key
17131 *
17132 * The validation context is used to store an IDC key.
17133 *
17134 * Returns 0 if succeeded, -1 on internal errors.
17135 */
17136static int
17137xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
17138 xmlSchemaPSVIIDCKeyPtr key)
17139{
17140 /*
17141 * Add to gobal list.
17142 */
17143 if (vctxt->idcKeys == NULL) {
17144 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
17145 xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
17146 if (vctxt->idcKeys == NULL) {
17147 xmlSchemaVErrMemory(vctxt,
17148 "allocating the IDC key storage list", NULL);
17149 return (-1);
17150 }
17151 vctxt->sizeIdcKeys = 40;
17152 } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
17153 vctxt->sizeIdcKeys *= 2;
17154 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
17155 xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
17156 sizeof(xmlSchemaPSVIIDCKeyPtr));
17157 if (vctxt->idcKeys == NULL) {
17158 xmlSchemaVErrMemory(vctxt,
17159 "re-allocating the IDC key storage list", NULL);
17160 return (-1);
17161 }
17162 }
17163 vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
17164
17165 return (0);
17166}
17167
17168/**
17169 * xmlSchemaIDCAppendNodeTableItem:
17170 * @bind: the IDC binding
17171 * @ntItem: the node-table item
17172 *
17173 * Appends the IDC node-table item to the binding.
17174 *
17175 * Returns 0 on success and -1 on internal errors.
17176 */
17177static int
17178xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
17179 xmlSchemaPSVIIDCNodePtr ntItem)
17180{
17181 if (bind->nodeTable == NULL) {
17182 bind->sizeNodes = 10;
17183 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
17184 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
17185 if (bind->nodeTable == NULL) {
17186 xmlSchemaVErrMemory(NULL,
17187 "allocating an array of IDC node-table items", NULL);
17188 return(-1);
17189 }
17190 } else if (bind->sizeNodes <= bind->nbNodes) {
17191 bind->sizeNodes *= 2;
17192 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
17193 xmlRealloc(bind->nodeTable, bind->sizeNodes *
17194 sizeof(xmlSchemaPSVIIDCNodePtr));
17195 if (bind->nodeTable == NULL) {
17196 xmlSchemaVErrMemory(NULL,
17197 "re-allocating an array of IDC node-table items", NULL);
17198 return(-1);
17199 }
17200 }
17201 bind->nodeTable[bind->nbNodes++] = ntItem;
17202 return(0);
17203}
17204
17205/**
17206 * xmlSchemaIDCAquireBinding:
17207 * @vctxt: the WXS validation context
17208 * @matcher: the IDC matcher
17209 *
17210 * Looks up an PSVI IDC binding, for the IDC definition and
17211 * of the given matcher. If none found, a new one is created
17212 * and added to the IDC table.
17213 *
17214 * Returns an IDC binding or NULL on internal errors.
17215 */
17216static xmlSchemaPSVIIDCBindingPtr
17217xmlSchemaIDCAquireBinding(xmlSchemaValidCtxtPtr vctxt,
17218 xmlSchemaIDCMatcherPtr matcher)
17219{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017220 xmlSchemaNodeInfoPtr info;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017221
17222 info = vctxt->elemInfos[matcher->depth];
17223
17224 if (info->idcTable == NULL) {
17225 info->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
17226 if (info->idcTable == NULL)
17227 return (NULL);
17228 return(info->idcTable);
17229 } else {
17230 xmlSchemaPSVIIDCBindingPtr bind = NULL;
17231
17232 bind = info->idcTable;
17233 do {
17234 if (bind->definition == matcher->aidc->def)
17235 return(bind);
17236 if (bind->next == NULL) {
17237 bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
17238 if (bind->next == NULL)
17239 return (NULL);
17240 return(bind->next);
17241 }
17242 bind = bind->next;
17243 } while (bind != NULL);
17244 }
17245 return (NULL);
17246}
17247
17248/**
17249 * xmlSchemaIDCFreeKey:
17250 * @key: the IDC key
17251 *
17252 * Frees an IDC key together with its compiled value.
17253 */
17254static void
17255xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
17256{
17257 if (key->compValue != NULL)
17258 xmlSchemaFreeValue(key->compValue);
17259 xmlFree(key);
17260}
17261
17262/**
17263 * xmlSchemaIDCFreeBinding:
17264 *
17265 * Frees an IDC binding. Note that the node table-items
17266 * are not freed.
17267 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017268static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017269xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
17270{
17271 if (bind->nodeTable != NULL) {
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017272 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
17273 int i;
17274 /*
17275 * Node-table items for keyrefs are not stored globally
17276 * to the validation context, since they are not bubbled.
17277 * We need to free them here.
17278 */
17279 for (i = 0; i < bind->nbNodes; i++) {
17280 xmlFree(bind->nodeTable[i]->keys);
17281 xmlFree(bind->nodeTable[i]);
17282 }
17283 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017284 xmlFree(bind->nodeTable);
17285 }
17286 xmlFree(bind);
17287}
17288
17289/**
17290 * xmlSchemaIDCFreeIDCTable:
17291 * @bind: the first IDC binding in the list
17292 *
17293 * Frees an IDC table, i.e. all the IDC bindings in the list.
17294 */
17295static void
17296xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
17297{
17298 xmlSchemaPSVIIDCBindingPtr prev;
17299
17300 while (bind != NULL) {
17301 prev = bind;
17302 bind = bind->next;
17303 xmlSchemaIDCFreeBinding(prev);
17304 }
17305}
17306
17307/**
17308 * xmlSchemaIDCFreeMatcherList:
17309 * @matcher: the first IDC matcher in the list
17310 *
17311 * Frees a list of IDC matchers.
17312 */
17313static void
17314xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
17315{
17316 xmlSchemaIDCMatcherPtr next;
17317
17318 while (matcher != NULL) {
17319 next = matcher->next;
17320 if (matcher->keySeqs != NULL) {
17321 int i;
17322 for (i = 0; i < matcher->sizeKeySeqs; i++)
17323 if (matcher->keySeqs[i] != NULL)
17324 xmlFree(matcher->keySeqs[i]);
17325 xmlFree(matcher->keySeqs);
17326 }
17327 xmlFree(matcher);
17328 matcher = next;
17329 }
17330}
17331
17332/**
17333 * xmlSchemaAreValuesEqual:
17334 * @ta: the first type
17335 * @a: the first value
17336 * @tb: the second type
17337 * @b: the second value
17338 *
17339 * Compares two values.
17340 *
17341 * Returns 1 if they are equal, 0 if not and -1 on internal errors.
17342 */
17343static int
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017344xmlSchemaAreValuesEqual(xmlSchemaValidCtxtPtr vctxt,
17345 xmlSchemaTypePtr ta,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017346 xmlSchemaValPtr a,
17347 xmlSchemaTypePtr tb,
17348 xmlSchemaValPtr b)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017349{
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017350 /* Same user derived/built-in derived/built-in primitive types. */
17351 if (ta == tb)
17352 goto compareValue;
17353
17354 /*
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017355 * Note that comparison with anySimpleTypes with be supported for
17356 * string based types as well.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017357 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017358#if 0
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017359 if ((ta->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
17360 (tb->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
17361 return(0);
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017362#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017363
17364 /*
17365 * 4.2.1 equal (data-types)
17366 *
17367 * the ·value space·s of all ·primitive· datatypes are disjoint
17368 * (they do not share any values)
17369 */
17370 if ((ta->builtInType != 0) && (tb->builtInType != 0) &&
17371 (ta->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE) &&
17372 (tb->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
17373 return(0);
17374
17375 if ((ta->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
17376 (ta->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) ||
17377 (tb->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
17378 (tb->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)) {
17379 TODO
17380 return(0);
17381 }
17382 /*
17383 * (1) if a datatype T' is ·derived· by ·restriction· from an atomic datatype
17384 * T then the ·value space· of T' is a subset of the ·value space· of T.
17385 */
17386 /*
17387 * (2) if datatypes T' and T'' are ·derived· by ·restriction· from a common
17388 * atomic ancestor T then the ·value space·s of T' and T'' may overlap.
17389 */
17390
17391 {
17392 xmlSchemaTypePtr pta = ta, ptb = tb;
17393
17394 /* Note that we will compare the primitives here. */
17395 while ((pta->builtInType == 0) ||
17396 ((pta->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE) == 0))
17397 pta = pta->baseType;
17398 while ((ptb->builtInType == 0) ||
17399 ((ptb->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE) == 0))
17400 ptb = ptb->baseType;
17401 if (pta == ptb)
17402 goto compareValue;
17403 return(0);
17404 }
17405compareValue:
17406 {
17407#ifdef IDC_VALUE_SUPPORT
17408 int ret;
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000017409 int aws, bws;
17410
17411 aws = xmlSchemaGetWhiteSpaceFacetValue(ta);
17412 bws = xmlSchemaGetWhiteSpaceFacetValue(tb);
17413
17414 ret = xmlSchemaCompareValuesWhtsp(
17415 a, (xmlSchemaWhitespaceValueType) aws,
17416 b, (xmlSchemaWhitespaceValueType) bws);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017417 if (ret == 0)
17418 return(1);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017419 else if (ret == -2) {
17420 xmlSchemaVErr(vctxt, vctxt->node,
17421 XML_SCHEMAV_INTERNAL,
17422 "Internal error: xmlSchemaAreValuesEqual, "
17423 "failed to compare the values.\n",
17424 NULL, NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017425 return(-1);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017426 } else
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017427 return(0);
17428#else
17429 return (1);
17430#endif
17431 }
17432}
17433
17434/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017435 * xmlSchemaIDCAddStateObject:
17436 * @vctxt: the WXS validation context
17437 * @matcher: the IDC matcher
17438 * @sel: the XPath information
17439 * @parent: the parent "selector" state object if any
17440 * @type: "selector" or "field"
17441 *
17442 * Creates/reuses and activates state objects for the given
17443 * XPath information; if the XPath expression consists of unions,
17444 * multiple state objects are created for every unioned expression.
17445 *
17446 * Returns 0 on success and -1 on internal errors.
17447 */
17448static int
17449xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
17450 xmlSchemaIDCMatcherPtr matcher,
17451 xmlSchemaIDCSelectPtr sel,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017452 int type)
17453{
17454 xmlSchemaIDCStateObjPtr sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017455
17456 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017457 * Reuse the state objects from the pool.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017458 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017459 if (vctxt->xpathStatePool != NULL) {
17460 sto = vctxt->xpathStatePool;
17461 vctxt->xpathStatePool = sto->next;
17462 sto->next = NULL;
17463 } else {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017464 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017465 * Create a new state object.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017466 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017467 sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
17468 if (sto == NULL) {
17469 xmlSchemaVErrMemory(NULL,
17470 "allocating an IDC state object", NULL);
17471 return (-1);
17472 }
17473 memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
17474 }
17475 /*
17476 * Add to global list.
17477 */
17478 if (vctxt->xpathStates != NULL)
17479 sto->next = vctxt->xpathStates;
17480 vctxt->xpathStates = sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017481
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017482 /*
17483 * Free the old xpath validation context.
17484 */
17485 if (sto->xpathCtxt != NULL)
17486 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
17487
17488 /*
17489 * Create a new XPath (pattern) validation context.
17490 */
17491 sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
17492 (xmlPatternPtr) sel->xpathComp);
17493 if (sto->xpathCtxt == NULL) {
17494 xmlSchemaVErr(vctxt, vctxt->node,
17495 XML_SCHEMAV_INTERNAL,
17496 "Internal error: xmlSchemaIDCAddStateObject, "
17497 "failed to create the XPath validation context.\n",
17498 NULL, NULL);
17499 return (-1);
17500 }
17501 sto->type = type;
17502 sto->depth = vctxt->depth;
17503 sto->matcher = matcher;
17504 sto->sel = sel;
17505 sto->nbHistory = 0;
17506
17507#if DEBUG_IDC
17508 xmlGenericError(xmlGenericErrorContext, "IDC: STO push '%s'\n",
17509 sto->sel->xpath);
17510#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017511 return (0);
17512}
17513
17514/**
17515 * xmlSchemaXPathEvaluate:
17516 * @vctxt: the WXS validation context
17517 * @nodeType: the nodeType of the current node
17518 *
17519 * Evaluates all active XPath state objects.
17520 *
17521 * Returns the number of IC "field" state objects which resolved to
17522 * this node, 0 if none resolved and -1 on internal errors.
17523 */
17524static int
17525xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017526 xmlElementType nodeType)
17527{
17528 xmlSchemaIDCStateObjPtr sto, head = NULL, first;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017529 int res, resolved = 0, depth = vctxt->depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017530
17531 if (vctxt->xpathStates == NULL)
17532 return (0);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017533
17534 if (nodeType == XML_ATTRIBUTE_NODE)
17535 depth++;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017536#if DEBUG_IDC
17537 {
17538 xmlChar *str = NULL;
17539 xmlGenericError(xmlGenericErrorContext,
17540 "IDC: EVAL on %s, depth %d, type %d\n",
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017541 xmlSchemaFormatNsUriLocal(&str, vctxt->nodeInfo->namespaceName,
17542 vctxt->nodeInfo->localName), depth, nodeType);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017543 FREE_AND_NULL(str)
17544 }
17545#endif
17546 /*
17547 * Process all active XPath state objects.
17548 */
17549 first = vctxt->xpathStates;
17550 sto = first;
17551 while (sto != head) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017552#if DEBUG_IDC
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017553 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017554 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] selector '%s'\n",
17555 sto->matcher->aidc->def->name, sto->sel->xpath);
17556 else
17557 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] field '%s'\n",
17558 sto->matcher->aidc->def->name, sto->sel->xpath);
17559#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017560
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017561#ifdef IDC_XPATH_SUPPORT
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017562 if (nodeType == XML_ELEMENT_NODE)
17563 res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
17564 vctxt->nodeInfo->localName, vctxt->nodeInfo->namespaceName);
17565 else
17566 res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
17567 vctxt->nodeInfo->localName, vctxt->nodeInfo->namespaceName);
17568
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017569#else
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017570 res = 0;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017571#endif
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017572 if (res == -1) {
17573 xmlSchemaVErr(vctxt, vctxt->node,
17574 XML_SCHEMAV_INTERNAL,
17575 "Internal error: xmlSchemaXPathEvaluate, "
17576 "failed to evaluate a node.\n",
17577 NULL, NULL);
17578 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017579 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017580 if (res == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017581 goto next_sto;
17582 /*
17583 * Full match.
17584 */
17585#if DEBUG_IDC
17586 xmlGenericError(xmlGenericErrorContext, "IDC: "
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017587 "MATCH\n");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017588#endif
17589 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017590 * Register a match in the state object history.
17591 */
17592 if (sto->history == NULL) {
17593 sto->history = (int *) xmlMalloc(5 * sizeof(int));
17594 if (sto->history == NULL) {
17595 xmlSchemaVErrMemory(NULL,
17596 "allocating the state object history", NULL);
17597 return(-1);
17598 }
17599 sto->sizeHistory = 10;
17600 } else if (sto->sizeHistory <= sto->nbHistory) {
17601 sto->sizeHistory *= 2;
17602 sto->history = (int *) xmlRealloc(sto->history,
17603 sto->sizeHistory * sizeof(int));
17604 if (sto->history == NULL) {
17605 xmlSchemaVErrMemory(NULL,
17606 "re-allocating the state object history", NULL);
17607 return(-1);
17608 }
17609 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017610 sto->history[sto->nbHistory++] = depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017611
17612#ifdef DEBUG_IDC
17613 xmlGenericError(xmlGenericErrorContext, "IDC: push match '%d'\n",
17614 vctxt->depth);
17615#endif
17616
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017617 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
17618 xmlSchemaIDCSelectPtr sel;
17619 /*
17620 * Activate state objects for the IDC fields of
17621 * the IDC selector.
17622 */
17623#if DEBUG_IDC
17624 xmlGenericError(xmlGenericErrorContext, "IDC: "
17625 "activating field states\n");
17626#endif
17627 sel = sto->matcher->aidc->def->fields;
17628 while (sel != NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017629 if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
17630 sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
17631 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017632 sel = sel->next;
17633 }
17634 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
17635 /*
17636 * An IDC key node was found.
17637 */
17638#if DEBUG_IDC
17639 xmlGenericError(xmlGenericErrorContext,
17640 "IDC: key found\n");
17641#endif
17642 /*
17643 * Notify that the character value of this node is
17644 * needed.
17645 */
17646 if (resolved == 0)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017647 vctxt->nodeInfo->flags |= XML_SCHEMA_ELEM_INFO_VALUE_NEEDED;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017648 resolved++;
17649 }
17650next_sto:
17651 if (sto->next == NULL) {
17652 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017653 * Evaluate field state objects created on this node as well.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017654 */
17655 head = first;
17656 sto = vctxt->xpathStates;
17657 } else
17658 sto = sto->next;
17659 }
17660 return (resolved);
17661}
17662
17663/**
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017664 * xmlSchemaXPathProcessHistory:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017665 * @vctxt: the WXS validation context
17666 * @type: the simple/complex type of the current node if any at all
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017667 * @compValue: the precompiled value
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017668 *
17669 * Processes and pops the history items of the IDC state objects.
17670 * IDC key-sequences are validated/created on IDC bindings.
17671 *
17672 * Returns 0 on success and -1 on internal errors.
17673 */
17674static int
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017675xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017676 int depth)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017677{
17678 xmlSchemaIDCStateObjPtr sto, nextsto;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017679 int res, matchDepth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017680 xmlSchemaPSVIIDCKeyPtr key = NULL;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017681 xmlSchemaTypePtr type = vctxt->nodeInfo->typeDef;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017682
17683 if (vctxt->xpathStates == NULL)
17684 return (0);
17685 sto = vctxt->xpathStates;
17686
17687#if DEBUG_IDC
17688 {
17689 xmlChar *str = NULL;
17690 xmlGenericError(xmlGenericErrorContext,
17691 "IDC: BACK on %s, depth %d\n",
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017692 xmlSchemaFormatNsUriLocal(&str, vctxt->nodeInfo->namespaceName,
17693 vctxt->nodeInfo->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017694 FREE_AND_NULL(str)
17695 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017696#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017697 /*
17698 * Evaluate the state objects.
17699 */
17700 while (sto != NULL) {
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017701#ifdef IDC_XPATH_SUPPORT
17702 xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
17703 #if DEBUG_IDC
17704 xmlGenericError(xmlGenericErrorContext, "IDC: stream pop '%s'\n",
17705 sto->sel->xpath);
17706 #endif
17707#endif
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017708 if (sto->nbHistory == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017709 goto deregister_check;
17710
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017711 matchDepth = sto->history[sto->nbHistory -1];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017712
17713 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017714 * Only matches at the current depth are of interest.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017715 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017716 if (matchDepth != depth) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017717 sto = sto->next;
17718 continue;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017719 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017720 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
17721 if (! IS_SIMPLE_TYPE(type)) {
17722 /*
17723 * Not qualified if the field resolves to a node of non
17724 * simple type.
17725 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017726 xmlSchemaStreamVCustomErr(vctxt,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017727 XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017728 vctxt->nodeInfo,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017729 (xmlSchemaTypePtr) sto->matcher->aidc->def,
17730 "The field '%s' does evaluate to a node of "
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017731 "non-simple type", sto->sel->xpath, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017732
17733 sto->nbHistory--;
17734 goto deregister_check;
17735 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017736 if ((key == NULL) && (vctxt->nodeInfo->value == NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017737 /*
17738 * Failed to provide the normalized value; maby
17739 * the value was invalid.
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017740 */
17741 xmlSchemaStreamVCustomErr(vctxt,
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000017742 XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017743 vctxt->nodeInfo,
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000017744 (xmlSchemaTypePtr) sto->matcher->aidc->def,
17745 "Warning: No precomputed value available, the value "
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017746 "was either invalid or something strange happend",
17747 NULL, NULL);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000017748 /*
17749 xmlSchemaVErr(vctxt, vctxt->nodeInfo->node,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017750 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017751 "Internal error: xmlSchemaXPathProcessHistory, "
17752 "computed value not available.\n",
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017753 NULL, NULL);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000017754 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017755 sto->nbHistory--;
17756 goto deregister_check;
17757 } else {
17758 xmlSchemaIDCMatcherPtr matcher = sto->matcher;
17759 xmlSchemaPSVIIDCKeyPtr *keySeq;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017760 int pos, idx;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017761
17762 /*
17763 * The key will be anchored on the matcher's list of
17764 * key-sequences. The position in this list is determined
17765 * by the target node's depth relative to the matcher's
17766 * depth of creation (i.e. the depth of the scope element).
17767 */
17768 pos = sto->depth - matcher->depth;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017769 idx = sto->sel->index;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017770
17771 /*
17772 * Create/grow the array of key-sequences.
17773 */
17774 if (matcher->keySeqs == NULL) {
17775 if (pos > 9)
17776 matcher->sizeKeySeqs = pos * 2;
17777 else
17778 matcher->sizeKeySeqs = 10;
17779 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
17780 xmlMalloc(matcher->sizeKeySeqs *
17781 sizeof(xmlSchemaPSVIIDCKeyPtr *));
17782 if (matcher->keySeqs == NULL) {
17783 xmlSchemaVErrMemory(NULL,
17784 "allocating an array of key-sequences",
17785 NULL);
17786 return(-1);
17787 }
17788 memset(matcher->keySeqs, 0,
17789 matcher->sizeKeySeqs *
17790 sizeof(xmlSchemaPSVIIDCKeyPtr *));
17791 } else if (pos >= matcher->sizeKeySeqs) {
17792 int i = matcher->sizeKeySeqs;
17793
17794 matcher->sizeKeySeqs *= 2;
17795 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
17796 xmlRealloc(matcher->keySeqs,
17797 matcher->sizeKeySeqs *
17798 sizeof(xmlSchemaPSVIIDCKeyPtr *));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017799 if (matcher->keySeqs == NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017800 xmlSchemaVErrMemory(NULL,
17801 "reallocating an array of key-sequences",
17802 NULL);
17803 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017804 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017805 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017806 * The array needs to be NULLed.
17807 * TODO: Use memset?
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017808 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017809 for (; i < matcher->sizeKeySeqs; i++)
17810 matcher->keySeqs[i] = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017811 }
17812
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017813 /*
17814 * Get/create the key-sequence.
17815 */
17816 keySeq = matcher->keySeqs[pos];
17817 if (keySeq == NULL) {
17818 goto create_sequence;
17819 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017820 if (keySeq[idx] != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017821 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017822 * cvc-identity-constraint:
17823 * 3 For each node in the ·target node set· all
17824 * of the {fields}, with that node as the context
17825 * node, evaluate to either an empty node-set or
17826 * a node-set with exactly one member, which must
17827 * have a simple type.
17828 *
17829 * The key was already set; report an error.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017830 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017831 xmlSchemaStreamVCustomErr(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017832 XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017833 vctxt->nodeInfo,
17834 (xmlSchemaTypePtr) matcher->aidc->def,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017835 "The field '%s' evaluates to a node-set "
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017836 "with more than one member",
17837 sto->sel->xpath, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017838 sto->nbHistory--;
17839 goto deregister_check;
17840 } else {
17841 goto create_key;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017842 }
17843 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017844
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017845create_sequence:
17846 /*
17847 * Create a key-sequence.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017848 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017849 keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
17850 matcher->aidc->def->nbFields *
17851 sizeof(xmlSchemaPSVIIDCKeyPtr));
17852 if (keySeq == NULL) {
17853 xmlSchemaVErrMemory(NULL,
17854 "allocating an IDC key-sequence", NULL);
17855 return(-1);
17856 }
17857 memset(keySeq, 0, matcher->aidc->def->nbFields *
17858 sizeof(xmlSchemaPSVIIDCKeyPtr));
17859 matcher->keySeqs[pos] = keySeq;
17860create_key:
17861 /*
17862 * Created a key once per node only.
17863 */
17864 if (key == NULL) {
17865 key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
17866 sizeof(xmlSchemaPSVIIDCKey));
17867 if (key == NULL) {
17868 xmlSchemaVErrMemory(NULL,
17869 "allocating a IDC key", NULL);
17870 xmlFree(keySeq);
17871 matcher->keySeqs[pos] = NULL;
17872 return(-1);
17873 }
17874 /*
17875 * Consume the compiled value.
17876 */
17877 key->type = type;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017878 key->compValue = vctxt->nodeInfo->value;
17879 vctxt->nodeInfo->value = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017880 /*
17881 * Store the key in a global list.
17882 */
17883 if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
17884 xmlSchemaIDCFreeKey(key);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017885 return (-1);
17886 }
17887 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017888 keySeq[idx] = key;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017889 }
17890 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017891
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017892 xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
17893 xmlSchemaPSVIIDCBindingPtr bind;
17894 xmlSchemaPSVIIDCNodePtr ntItem;
17895 xmlSchemaIDCMatcherPtr matcher;
17896 xmlSchemaIDCPtr idc;
17897 int pos, i, j, nbKeys;
17898 /*
17899 * Here we have the following scenario:
17900 * An IDC 'selector' state object resolved to a target node,
17901 * during the time this target node was in the
17902 * ancestor-or-self axis, the 'field' state object(s) looked
17903 * out for matching nodes to create a key-sequence for this
17904 * target node. Now we are back to this target node and need
17905 * to put the key-sequence, together with the target node
17906 * itself, into the node-table of the corresponding IDC
17907 * binding.
17908 */
17909 matcher = sto->matcher;
17910 idc = matcher->aidc->def;
17911 nbKeys = idc->nbFields;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017912 pos = depth - matcher->depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017913 /*
17914 * Check if the matcher has any key-sequences at all, plus
17915 * if it has a key-sequence for the current target node.
17916 */
17917 if ((matcher->keySeqs == NULL) ||
17918 (matcher->sizeKeySeqs <= pos)) {
17919 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
17920 goto selector_key_error;
17921 else
17922 goto selector_leave;
17923 }
17924
17925 keySeq = &(matcher->keySeqs[pos]);
17926 if (*keySeq == NULL) {
17927 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
17928 goto selector_key_error;
17929 else
17930 goto selector_leave;
17931 }
17932
17933 for (i = 0; i < nbKeys; i++) {
17934 if ((*keySeq)[i] == NULL) {
17935 /*
17936 * Not qualified, if not all fields did resolve.
17937 */
17938 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
17939 /*
17940 * All fields of a "key" IDC must resolve.
17941 */
17942 goto selector_key_error;
17943 }
17944 goto selector_leave;
17945 }
17946 }
17947 /*
17948 * All fields did resolve.
17949 */
17950
17951 /*
17952 * 4.1 If the {identity-constraint category} is unique(/key),
17953 * then no two members of the ·qualified node set· have
17954 * ·key-sequences· whose members are pairwise equal, as
17955 * defined by Equal in [XML Schemas: Datatypes].
17956 *
17957 * Get the IDC binding from the matcher and check for
17958 * duplicate key-sequences.
17959 */
17960 bind = xmlSchemaIDCAquireBinding(vctxt, matcher);
17961 if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
17962 (bind->nbNodes != 0)) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017963 xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017964
17965 i = 0;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017966 res = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017967 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017968 * Compare the key-sequences, key by key.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017969 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017970 do {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017971 bkeySeq = bind->nodeTable[i]->keys;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017972 for (j = 0; j < nbKeys; j++) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017973 ckey = (*keySeq)[j];
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017974 bkey = bkeySeq[j];
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017975 res = xmlSchemaAreValuesEqual(vctxt, ckey->type,
17976 ckey->compValue, bkey->type, bkey->compValue);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017977 if (res == -1) {
17978 return (-1);
17979 } else if (res == 0)
17980 break;
17981 }
17982 if (res == 1) {
17983 /*
17984 * Duplicate found.
17985 */
17986 break;
17987 }
17988 i++;
17989 } while (i < bind->nbNodes);
17990 if (i != bind->nbNodes) {
17991 /*
17992 * TODO: Try to report the key-sequence.
17993 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017994 xmlSchemaStreamVCustomErr(vctxt,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017995 XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017996 vctxt->nodeInfo,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017997 (xmlSchemaTypePtr) idc,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000017998 "Duplicate key-sequence found", NULL, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017999
18000 goto selector_leave;
18001 }
18002 }
18003 /*
18004 * Add a node-table item to the IDC binding.
18005 */
18006 ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
18007 sizeof(xmlSchemaPSVIIDCNode));
18008 if (ntItem == NULL) {
18009 xmlSchemaVErrMemory(NULL,
18010 "allocating an IDC node-table item", NULL);
18011 xmlFree(*keySeq);
18012 *keySeq = NULL;
18013 return(-1);
18014 }
18015 memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
18016
18017 /*
18018 * Store the node-table item on global list.
18019 */
18020 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
18021 if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
18022 xmlFree(ntItem);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018023 xmlFree(*keySeq);
18024 *keySeq = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018025 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018026 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018027 }
18028 /*
18029 * Init the node-table item. Consume the key-sequence.
18030 */
18031 ntItem->node = vctxt->node;
18032 ntItem->keys = *keySeq;
18033 *keySeq = NULL;
18034 if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1) {
18035 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
18036 /*
18037 * Free the item, since keyref items won't be
18038 * put on a global list.
18039 */
18040 xmlFree(ntItem->keys);
18041 xmlFree(ntItem);
18042 }
18043 return (-1);
18044 }
18045
18046 goto selector_leave;
18047selector_key_error:
18048 /*
18049 * 4.2.1 (KEY) The ·target node set· and the
18050 * ·qualified node set· are equal, that is, every
18051 * member of the ·target node set· is also a member
18052 * of the ·qualified node set· and vice versa.
18053 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000018054 xmlSchemaStreamVCustomErr(vctxt,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018055 XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000018056 vctxt->nodeInfo,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018057 (xmlSchemaTypePtr) idc,
18058 "All 'key' fields must evaluate to a node",
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000018059 NULL, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018060selector_leave:
18061 /*
18062 * Free the key-sequence if not added to the IDC table.
18063 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018064 if ((keySeq != NULL) && (*keySeq != NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018065 xmlFree(*keySeq);
18066 *keySeq = NULL;
18067 }
18068 } /* if selector */
18069
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018070 sto->nbHistory--;
18071
18072deregister_check:
18073 /*
18074 * Deregister state objects if they reach the depth of creation.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018075 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018076 if ((sto->nbHistory == 0) && (sto->depth == depth)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018077#if DEBUG_IDC
18078 xmlGenericError(xmlGenericErrorContext, "IDC: STO pop '%s'\n",
18079 sto->sel->xpath);
18080#endif
18081 if (vctxt->xpathStates != sto) {
18082 xmlSchemaVErr(vctxt, vctxt->node,
18083 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018084 "Internal error: xmlSchemaXPathProcessHistory, "
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018085 "The state object to be removed is not the first "
18086 "in the list.\n",
18087 NULL, NULL);
18088 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018089 nextsto = sto->next;
18090 /*
18091 * Unlink from the list of active XPath state objects.
18092 */
18093 vctxt->xpathStates = sto->next;
18094 sto->next = vctxt->xpathStatePool;
18095 /*
18096 * Link it to the pool of reusable state objects.
18097 */
18098 vctxt->xpathStatePool = sto;
18099 sto = nextsto;
18100 } else
18101 sto = sto->next;
18102 } /* while (sto != NULL) */
18103 return (0);
18104}
18105
18106/**
18107 * xmlSchemaIDCRegisterMatchers:
18108 * @vctxt: the WXS validation context
18109 * @elemDecl: the element declaration
18110 *
18111 * Creates helper objects to evaluate IDC selectors/fields
18112 * successively.
18113 *
18114 * Returns 0 if OK and -1 on internal errors.
18115 */
18116static int
18117xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
18118 xmlSchemaElementPtr elemDecl)
18119{
18120 xmlSchemaIDCMatcherPtr matcher, last = NULL;
18121 xmlSchemaIDCPtr idc, refIdc;
18122 xmlSchemaIDCAugPtr aidc;
18123
18124 idc = (xmlSchemaIDCPtr) elemDecl->idcs;
18125 if (idc == NULL)
18126 return (0);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018127
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018128#if DEBUG_IDC
18129 {
18130 xmlChar *str = NULL;
18131 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018132 "IDC: REGISTER on %s, depth %d\n",
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018133 (char *) xmlSchemaFormatNsUriLocal(&str, vctxt->nodeInfo->namespaceName,
18134 vctxt->nodeInfo->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018135 FREE_AND_NULL(str)
18136 }
18137#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018138 if (vctxt->nodeInfo->idcMatchers != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018139 xmlSchemaVErr(vctxt, vctxt->node,
18140 XML_SCHEMAV_INTERNAL,
18141 "Internal error: xmlSchemaIDCRegisterMatchers: "
18142 "The chain of IDC matchers is expected to be empty.\n",
18143 NULL, NULL);
18144 return (-1);
18145 }
18146 do {
18147 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
18148 /*
18149 * Since IDCs bubbles are expensive we need to know the
18150 * depth at which the bubbles should stop; this will be
18151 * the depth of the top-most keyref IDC. If no keyref
18152 * references a key/unique IDC, the bubbleDepth will
18153 * be -1, indicating that no bubbles are needed.
18154 */
18155 refIdc = (xmlSchemaIDCPtr) idc->ref->item;
18156 if (refIdc != NULL) {
18157 /*
18158 * Lookup the augmented IDC.
18159 */
18160 aidc = vctxt->aidcs;
18161 while (aidc != NULL) {
18162 if (aidc->def == refIdc)
18163 break;
18164 aidc = aidc->next;
18165 }
18166 if (aidc == NULL) {
18167 xmlSchemaVErr(vctxt, vctxt->node,
18168 XML_SCHEMAV_INTERNAL,
18169 "Internal error: xmlSchemaIDCRegisterMatchers: "
18170 "Could not find an augmented IDC item for an IDC "
18171 "definition.\n",
18172 NULL, NULL);
18173 return (-1);
18174 }
18175 if ((aidc->bubbleDepth == -1) ||
18176 (vctxt->depth < aidc->bubbleDepth))
18177 aidc->bubbleDepth = vctxt->depth;
18178 }
18179 }
18180 /*
18181 * Lookup the augmented IDC item for the IDC definition.
18182 */
18183 aidc = vctxt->aidcs;
18184 while (aidc != NULL) {
18185 if (aidc->def == idc)
18186 break;
18187 aidc = aidc->next;
18188 }
18189 if (aidc == NULL) {
18190 xmlSchemaVErr(vctxt, vctxt->node,
18191 XML_SCHEMAV_INTERNAL,
18192 "Internal error: xmlSchemaIDCRegisterMatchers: "
18193 "Could not find an augmented IDC item for an IDC definition.\n",
18194 NULL, NULL);
18195 return (-1);
18196 }
18197 /*
18198 * Create an IDC matcher for every IDC definition.
18199 */
18200 matcher = (xmlSchemaIDCMatcherPtr)
18201 xmlMalloc(sizeof(xmlSchemaIDCMatcher));
18202 if (matcher == NULL) {
18203 xmlSchemaVErrMemory(vctxt,
18204 "allocating an IDC matcher", NULL);
18205 return (-1);
18206 }
18207 memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
18208 if (last == NULL)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018209 vctxt->nodeInfo->idcMatchers = matcher;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018210 else
18211 last->next = matcher;
18212 last = matcher;
18213
18214 matcher->type = IDC_MATCHER;
18215 matcher->depth = vctxt->depth;
18216 matcher->aidc = aidc;
18217#if DEBUG_IDC
18218 xmlGenericError(xmlGenericErrorContext, "IDC: register matcher\n");
18219#endif
18220 /*
18221 * Init the automaton state object.
18222 */
18223 if (xmlSchemaIDCAddStateObject(vctxt, matcher,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018224 idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018225 return (-1);
18226
18227 idc = idc->next;
18228 } while (idc != NULL);
18229 return (0);
18230}
18231
18232/**
18233 * xmlSchemaBubbleIDCNodeTables:
18234 * @depth: the current tree depth
18235 *
18236 * Merges IDC bindings of an element at @depth into the corresponding IDC
18237 * bindings of its parent element. If a duplicate note-table entry is found,
18238 * both, the parent node-table entry and child entry are discarded from the
18239 * node-table of the parent.
18240 *
18241 * Returns 0 if OK and -1 on internal errors.
18242 */
18243static int
18244xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
18245{
18246 xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018247 xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL, lastParBind = NULL; /* parent IDC bindings. */
18248 xmlSchemaPSVIIDCNodePtr node, parNode = NULL; /* node-table entries. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018249 xmlSchemaPSVIIDCKeyPtr key, parKey; /* keys of in a key-sequence. */
18250 xmlSchemaIDCAugPtr aidc;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018251 int i, j, k, ret = 0, oldNum, newDupls = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018252 int duplTop;
18253
18254 /*
18255 * The node table has the following sections:
18256 *
18257 * O --> old node-table entries (first)
18258 * O
18259 * + --> new node-table entries
18260 * +
18261 * % --> new duplicate node-table entries
18262 * %
18263 * # --> old duplicate node-table entries
18264 * # (last)
18265 *
18266 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018267 bind = vctxt->nodeInfo->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018268 if (bind == NULL) {
18269 /* Fine, no table, no bubbles. */
18270 return (0);
18271 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018272
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018273 parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
18274 /*
18275 * Walk all bindings; create new or add to existing bindings.
18276 * Remove duplicate key-sequences.
18277 */
18278start_binding:
18279 while (bind != NULL) {
18280 /*
18281 * Skip keyref IDCs.
18282 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018283 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
18284 bind = bind->next;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018285 continue;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018286 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018287 /*
18288 * Check if the key/unique IDC table needs to be bubbled.
18289 */
18290 aidc = vctxt->aidcs;
18291 do {
18292 if (aidc->def == bind->definition) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018293 if (aidc->bubbleDepth >= vctxt->depth) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018294 bind = bind->next;
18295 goto start_binding;
18296 }
18297 break;
18298 }
18299 aidc = aidc->next;
18300 } while (aidc != NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018301
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018302 if (parTable != NULL)
18303 parBind = *parTable;
18304 while (parBind != NULL) {
18305 /*
18306 * Search a matching parent binding for the
18307 * IDC definition.
18308 */
18309 if (parBind->definition == bind->definition) {
18310
18311 /*
18312 * Compare every node-table entry of the child node,
18313 * i.e. the key-sequence within, ...
18314 */
18315 oldNum = parBind->nbNodes; /* Skip newly added items. */
18316 duplTop = oldNum + parBind->nbDupls;
18317
18318 for (i = 0; i < bind->nbNodes; i++) {
18319 node = bind->nodeTable[i];
18320 if (node == NULL)
18321 continue;
18322 /*
18323 * ...with every key-sequence of the parent node, already
18324 * evaluated to be a duplicate key-sequence.
18325 */
18326 if (parBind->nbDupls != 0) {
18327 j = bind->nbNodes + newDupls;
18328 while (j < duplTop) {
18329 parNode = parBind->nodeTable[j];
18330 for (k = 0; k < bind->definition->nbFields; k++) {
18331 key = node->keys[k];
18332 parKey = parNode->keys[k];
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018333 ret = xmlSchemaAreValuesEqual(vctxt, key->type,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018334 key->compValue,
18335 parKey->type, parKey->compValue);
18336 if (ret == -1) {
18337 /* TODO: Internal error */
18338 return(-1);
18339 } else if (ret == 0)
18340 break;
18341
18342 }
18343 if (ret == 1)
18344 /* Duplicate found. */
18345 break;
18346 j++;
18347 }
18348 if (j != duplTop) {
18349 /* Duplicate found. */
18350 continue;
18351 }
18352 }
18353 /*
18354 * ... and with every key-sequence of the parent node.
18355 */
18356 j = 0;
18357 while (j < oldNum) {
18358 parNode = parBind->nodeTable[j];
18359 /*
18360 * Compare key by key.
18361 */
18362 for (k = 0; k < parBind->definition->nbFields; k++) {
18363 key = node->keys[k];
18364 parKey = parNode->keys[k];
18365
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018366 ret = xmlSchemaAreValuesEqual(vctxt, key->type,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018367 key->compValue,
18368 parKey->type, parKey->compValue);
18369 if (ret == -1) {
18370 /* TODO: Internal error */
18371 } else if (ret == 0)
18372 break;
18373
18374 }
18375 if (ret == 1)
18376 /*
18377 * The key-sequences are equal.
18378 */
18379 break;
18380 j++;
18381 }
18382 if (j != oldNum) {
18383 /*
18384 * Handle duplicates.
18385 */
18386 newDupls++;
18387 oldNum--;
18388 parBind->nbNodes--;
18389 /*
18390 * Move last old item to pos of duplicate.
18391 */
18392 parBind->nodeTable[j] =
18393 parBind->nodeTable[oldNum];
18394
18395 if (parBind->nbNodes != oldNum) {
18396 /*
18397 * If new items exist, move last new item to
18398 * last of old items.
18399 */
18400 parBind->nodeTable[oldNum] =
18401 parBind->nodeTable[parBind->nbNodes];
18402 }
18403 /*
18404 * Move duplicate to last pos of new/old items.
18405 */
18406 parBind->nodeTable[parBind->nbNodes] = parNode;
18407
18408 } else {
18409 /*
18410 * Add the node-table entry (node and key-sequence) of
18411 * the child node to the node table of the parent node.
18412 */
18413 if (parBind->nodeTable == NULL) {
18414 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
18415 xmlMalloc(1 * sizeof(xmlSchemaPSVIIDCNodePtr));
18416 if (parBind->nodeTable == NULL) {
18417 xmlSchemaVErrMemory(NULL,
18418 "allocating IDC list of node-table items", NULL);
18419 return(-1);
18420 }
18421 parBind->sizeNodes = 1;
18422 } else if (duplTop >= parBind->sizeNodes) {
18423 parBind->sizeNodes++;
18424 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
18425 xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
18426 sizeof(xmlSchemaPSVIIDCNodePtr));
18427 if (parBind->nodeTable == NULL) {
18428 xmlSchemaVErrMemory(NULL,
18429 "re-allocating IDC list of node-table items", NULL);
18430 return(-1);
18431 }
18432 }
18433
18434 /*
18435 * Move first old duplicate to last position
18436 * of old duplicates +1.
18437 */
18438 if (parBind->nbDupls != 0) {
18439 parBind->nodeTable[duplTop] =
18440 parBind->nodeTable[parBind->nbNodes + newDupls];
18441 }
18442 /*
18443 * Move first new duplicate to last position of
18444 * new duplicates +1.
18445 */
18446 if (newDupls != 0) {
18447 parBind->nodeTable[parBind->nbNodes + newDupls] =
18448 parBind->nodeTable[parBind->nbNodes];
18449 }
18450 /*
18451 * Append the new node-table entry to the 'new node-table
18452 * entries' section.
18453 */
18454 parBind->nodeTable[parBind->nbNodes] = node;
18455 parBind->nbNodes++;
18456 duplTop++;
18457 }
18458 }
18459 parBind->nbDupls += newDupls;
18460 break;
18461 }
18462 if (parBind->next == NULL)
18463 lastParBind = parBind;
18464 parBind = parBind->next;
18465 }
18466 if (parBind == NULL) {
18467 /*
18468 * No binding for the IDC was found: create a new one and
18469 * copy all node-tables.
18470 */
18471 parBind = xmlSchemaIDCNewBinding(bind->definition);
18472 if (parBind == NULL)
18473 return(-1);
18474
18475 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
18476 xmlMalloc(bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
18477 if (parBind->nodeTable == NULL) {
18478 xmlSchemaVErrMemory(NULL,
18479 "allocating an array of IDC node-table items", NULL);
18480 xmlSchemaIDCFreeBinding(parBind);
18481 return(-1);
18482 }
18483 parBind->sizeNodes = bind->nbNodes;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018484 parBind->nbNodes = bind->nbNodes;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018485 memcpy(parBind->nodeTable, bind->nodeTable,
18486 bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018487 if (*parTable == NULL)
18488 *parTable = parBind;
18489 else
18490 lastParBind->next = parBind;
18491 }
18492 bind = bind->next;
18493 }
18494 return (0);
18495}
18496
18497/**
18498 * xmlSchemaCheckCVCIDCKeyRef:
18499 * @vctxt: the WXS validation context
18500 * @elemDecl: the element declaration
18501 *
18502 * Check the cvc-idc-keyref constraints.
18503 */
18504static int
18505xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
18506{
18507 xmlSchemaPSVIIDCBindingPtr refbind, bind;
18508
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018509 refbind = vctxt->nodeInfo->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018510 /*
18511 * Find a keyref.
18512 */
18513 while (refbind != NULL) {
18514 if (refbind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
18515 int i, j, k, res;
18516 xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
18517 xmlSchemaPSVIIDCKeyPtr refKey, key;
18518
18519 /*
18520 * Find the referred key/unique.
18521 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018522 bind = vctxt->nodeInfo->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018523 do {
18524 if ((xmlSchemaIDCPtr) refbind->definition->ref->item ==
18525 bind->definition)
18526 break;
18527 bind = bind->next;
18528 } while (bind != NULL);
18529
18530 /*
18531 * Search for a matching key-sequences.
18532 */
18533 for (i = 0; i < refbind->nbNodes; i++) {
18534 res = 0;
18535 if (bind != NULL) {
18536 refKeys = refbind->nodeTable[i]->keys;
18537 for (j = 0; j < bind->nbNodes; j++) {
18538 keys = bind->nodeTable[j]->keys;
18539 for (k = 0; k < bind->definition->nbFields; k++) {
18540 refKey = refKeys[k];
18541 key = keys[k];
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018542 res = xmlSchemaAreValuesEqual(vctxt,
18543 key->type, key->compValue,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018544 refKey->type, refKey->compValue);
18545 if (res == 0)
18546 break;
18547 else if (res == -1) {
18548 return (-1);
18549 }
18550 }
18551 if (res == 1) {
18552 /*
18553 * Match found.
18554 */
18555 break;
18556 }
18557 }
18558 }
18559 if (res == 0) {
18560 /* TODO: Report the key-sequence. */
18561 xmlSchemaVCustomErr(vctxt,
18562 XML_SCHEMAV_CVC_IDC,
18563 refbind->nodeTable[i]->node,
18564 (xmlSchemaTypePtr) refbind->definition,
18565 "No matching key-sequence found", NULL);
18566 }
18567 }
18568 }
18569 refbind = refbind->next;
18570 }
18571 return (0);
18572}
18573#endif /* IDC_ENABLED */
18574
18575#ifdef ELEM_INFO_ENABLED
18576/**
18577 * xmlSchemaBeginElement:
18578 * @vctxt: the WXS validation context
18579 *
18580 * Just a temporary workaround to simulate streaming validation
18581 * a bit.
18582 */
18583static void
18584xmlSchemaBeginElement(xmlSchemaValidCtxtPtr vctxt)
18585{
18586 vctxt->depth++;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018587 vctxt->nodeInfo = xmlSchemaGetFreshElemInfo(vctxt, vctxt->depth);
18588 vctxt->nodeInfo->node = vctxt->node;
18589 vctxt->nodeInfo->localName = vctxt->node->name;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018590 if (vctxt->node->ns != NULL)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018591 vctxt->nodeInfo->namespaceName = vctxt->node->ns->href;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018592 else
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018593 vctxt->nodeInfo->namespaceName = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018594}
18595
18596/**
18597 * xmlSchemaEndElement:
18598 * @vctxt: the WXS validation context
18599 *
18600 * Just a temporary workaround to simulate streaming validation
18601 * a bit.
18602 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018603static int
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018604xmlSchemaEndElement(xmlSchemaValidCtxtPtr vctxt)
18605{
18606 if (vctxt->depth < 0) {
18607 /* TODO: raise error? */
18608 vctxt->depth--;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018609 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018610 }
18611#ifdef IDC_ENABLED
18612 /*
18613 * Evaluate the history of changes of active state objects.
18614 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018615 if (xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1)
18616 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018617
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018618 if (vctxt->nodeInfo->value != NULL) {
18619 xmlSchemaFreeValue(vctxt->nodeInfo->value);
18620 vctxt->nodeInfo->value = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018621 }
18622 /*
18623 * TODO: 6 The element information item must be ·valid· with respect to each of
18624 * the {identity-constraint definitions} as per Identity-constraint
18625 * Satisfied (§3.11.4).
18626 */
18627 /*
18628 * Validate IDC keyrefs.
18629 */
18630 xmlSchemaCheckCVCIDCKeyRef(vctxt);
18631#endif
18632
18633 /*
18634 * Merge/free the IDC table.
18635 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018636 if (vctxt->nodeInfo->idcTable != NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018637#ifdef IDC_ENABLED
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018638#ifdef DEBUG_IDC
18639 xmlSchemaDebugDumpIDCTable(stdout,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018640 vctxt->nodeInfo->namespaceName,
18641 vctxt->nodeInfo->localName,
18642 vctxt->nodeInfo->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018643#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018644 if (vctxt->depth > 0) {
18645 /*
18646 * Merge the IDC node table with the table of the parent node.
18647 */
18648 xmlSchemaBubbleIDCNodeTables(vctxt);
18649 }
18650 /*
18651 * TODO: Don't free the PSVI IDC tables if they are
18652 * requested for the PSVI.
18653 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018654 xmlSchemaIDCFreeIDCTable(vctxt->nodeInfo->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018655#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018656 vctxt->nodeInfo->idcTable = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018657 }
18658
18659 /*
18660 * Cleanup IDC matchers.
18661 */
18662#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018663 if (vctxt->nodeInfo->idcMatchers != NULL) {
18664 xmlSchemaIDCFreeMatcherList(vctxt->nodeInfo->idcMatchers);
18665 vctxt->nodeInfo->idcMatchers = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018666 }
18667#endif
18668
18669 /*
18670 * Skip further processing if we are on the validation root.
18671 */
18672 if (vctxt->depth == 0) {
18673 vctxt->depth--;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018674 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018675 }
18676
18677 /*
18678 * Reset the bubbleDepth if needed.
18679 */
18680#ifdef IDC_ENABLED
18681 if (vctxt->aidcs != NULL) {
18682 xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
18683 do {
18684 if (aidc->bubbleDepth == vctxt->depth) {
18685 /*
18686 * A bubbleDepth of a key/unique IDC matches the current
18687 * depth, this means that we are leaving the scope of the
18688 * top-most keyref IDC.
18689 */
18690 aidc->bubbleDepth = -1;
18691 }
18692 aidc = aidc->next;
18693 } while (aidc != NULL);
18694 }
18695#endif
18696 vctxt->depth--;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018697 /*
18698 * Clear the current elemInfo.
18699 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018700 if (vctxt->nodeInfo->value != NULL) {
18701 xmlSchemaFreeValue(vctxt->nodeInfo->value);
18702 vctxt->nodeInfo->value = NULL;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018703 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018704 vctxt->nodeInfo = vctxt->elemInfos[vctxt->depth];
18705 vctxt->node = vctxt->nodeInfo->node;
18706
18707 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018708}
18709
18710#endif /* ELEM_INFO_ENABLED */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018711
18712/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018713 * xmlSchemaValidateElementByDeclaration:
Daniel Veillard4255d502002-04-16 15:50:10 +000018714 * @ctxt: a schema validation context
18715 * @node: the top node.
18716 *
18717 * Validate the content of an element type.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018718 * Validation Rule: Element Locally Valid (Element)
Daniel Veillard4255d502002-04-16 15:50:10 +000018719 *
18720 * Returns 0 if the element is schemas valid, a positive error code
18721 * number otherwise and -1 in case of internal or API error.
18722 */
18723static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018724xmlSchemaValidateElementByDeclaration(xmlSchemaValidCtxtPtr ctxt,
18725 xmlSchemaElementPtr elemDecl)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018726{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018727 xmlNodePtr elem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018728 int ret = 0;
18729 xmlSchemaTypePtr actualType = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018730 xmlAttrPtr attr;
18731 xmlChar *attrValue;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018732 int nilled = 0, elemHasContent = -1;
Daniel Veillard3646d642004-06-02 19:19:14 +000018733
18734 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018735 * This one is called by xmlSchemaValidateElementByWildcardInternal,
18736 * xmlSchemaValidateElementByAnyType and xmlSchemaValidateElement.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018737 * Note that @elemDecl will be the declaration and never the
18738 * reference to a declaration.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018739 */
Daniel Veillard3646d642004-06-02 19:19:14 +000018740
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018741 if (ctxt == NULL) {
18742 xmlSchemaVErr(ctxt, NULL, XML_SCHEMAV_INTERNAL,
18743 "Internal error: xmlSchemaValidateElementByDeclaration, "
18744 "bad arguments.\n",
18745 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018746 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000018747 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018748
18749 elem = ctxt->node;
18750
18751 /*
18752 * cvc-elt (3.3.4) : 1
18753 */
18754 if (elemDecl == NULL) {
18755 xmlSchemaVCustomErr(ctxt,
18756 XML_SCHEMAV_CVC_ELT_1,
18757 elem, NULL,
18758 "No matching declaration available", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018759 /*
18760 * Evaluate IDCs even if an error occured.
18761 */
18762#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018763 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018764 return (-1);
18765#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018766 return (ctxt->err);
18767 }
18768 /*
18769 * cvc-elt (3.3.4) : 2
18770 */
18771 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
18772 xmlSchemaVCustomErr(ctxt,
18773 XML_SCHEMAV_CVC_ELT_2,
18774 elem, NULL,
18775 "The element declaration is abstract", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018776 /*
18777 * Evaluate IDCs even if an error occured.
18778 */
18779#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018780 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018781 return (-1);
18782#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018783 return (ctxt->err);
18784 }
18785
18786 /*
18787 * cvc-elt (3.3.4) : 3
18788 * Handle 'xsi:nil'.
18789 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018790
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018791 attr = xmlHasNsProp(elem, BAD_CAST "nil", xmlSchemaInstanceNs);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018792 if (attr != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018793 attrValue = xmlNodeGetContent((xmlNodePtr) attr);
18794 ctxt->node = (xmlNodePtr) attr;
18795 ctxt->cur = attr->children;
18796 ret = xmlSchemaValidateSimpleTypeValue(ctxt,
18797 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
18798 BAD_CAST attrValue, 1, 1, 1, 1);
18799 ctxt->node = elem;
18800 ctxt->type = (xmlSchemaTypePtr) elemDecl;
18801 if (ret < 0) {
18802 xmlSchemaVCustomErr(ctxt,
18803 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018804 (xmlNodePtr) attr, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018805 "Internal error: xmlSchemaValidateElementByDeclaration, "
18806 "validating the attribute 'xsi:nil'", NULL);
18807 if (attrValue != NULL)
18808 xmlFree(attrValue);
18809 return (-1);
18810 }
18811 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018812 /*
18813 * cvc-elt (3.3.4) : 3.1
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018814 */
18815 xmlSchemaVCustomErr(ctxt,
18816 XML_SCHEMAV_CVC_ELT_3_1,
18817 elem, NULL,
18818 "The element is not 'nillable'", NULL);
18819 } else {
18820 if (xmlStrEqual(BAD_CAST attrValue, BAD_CAST "true") ||
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018821 xmlStrEqual(BAD_CAST attrValue, BAD_CAST "1")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018822 ret = 0;
18823 /*
18824 * cvc-elt (3.3.4) : 3.2.1
18825 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018826 elemHasContent = xmlSchemaHasElemOrCharContent(elem);
18827 if (elemHasContent == 1) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018828 xmlSchemaVCustomErr(ctxt,
18829 XML_SCHEMAV_CVC_ELT_3_2_1,
18830 /* XML_SCHEMAS_ERR_NOTEMPTY, */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018831 elem, (xmlSchemaTypePtr) elemDecl,
18832 "The 'nilled' element must have no character or "
18833 "element content", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018834 ret = XML_SCHEMAV_CVC_ELT_3_2_1;
18835 }
18836 /*
18837 * cvc-elt (3.3.4) : 3.2.2
18838 */
18839 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
18840 (elemDecl->value != NULL)) {
18841 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_CVC_ELT_3_2_2,
18842 /* XML_SCHEMAS_ERR_HAVEDEFAULT, */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018843 elem, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018844 "There is a fixed value constraint defined for "
18845 "the 'nilled' element", NULL);
18846 ret = XML_SCHEMAV_CVC_ELT_3_2_2;
18847 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018848 if (ret == 0)
18849 nilled = 1;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018850 }
18851 }
18852 if (attrValue != NULL)
18853 xmlFree(attrValue);
18854 }
18855
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018856
18857 actualType = elemDecl->subtypes;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018858 /*
18859 * cvc-elt (3.3.4) : 4
18860 * Handle 'xsi:type'.
18861 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018862
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018863 attr = xmlHasNsProp(elem, BAD_CAST "type", xmlSchemaInstanceNs);
18864 if (attr != NULL) {
18865 xmlChar *nsName = NULL, *local = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018866
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018867 /*
18868 * TODO: We should report a *warning* that the type was overriden
18869 * by the instance.
18870 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018871
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018872 /*
18873 * cvc-elt (3.3.4) : 4.1
18874 */
18875 attrValue = xmlNodeGetContent((xmlNodePtr) attr);
18876 ret = xmlSchemaValQNameAcquire(attrValue, attr->parent,
18877 &nsName, &local);
18878 if (ret < 0) {
18879 xmlSchemaVCustomErr(ctxt,
18880 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018881 (xmlNodePtr) attr, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018882 "Internal error: xmlSchemaValidateElementByDeclaration, "
18883 "validating the attribute 'xsi:type'", NULL);;
18884 FREE_AND_NULL(attrValue)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018885 FREE_AND_NULL(nsName)
18886 FREE_AND_NULL(local)
18887 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018888 } else if (ret == 1) {
18889 xmlSchemaVSimpleTypeErr(ctxt,
18890 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
18891 (xmlNodePtr) attr, attrValue,
18892 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME));
18893 } else if (ret == 2) {
18894 xmlSchemaVCustomErr(ctxt,
18895 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
18896 (xmlNodePtr) attr,
18897 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
18898 "The QName value '%s' has no "
18899 "corresponding namespace declaration in scope",
18900 attrValue);
18901 } else {
18902 /*
18903 * cvc-elt (3.3.4) : 4.2
18904 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018905 actualType = xmlSchemaGetType(ctxt->schema, local, nsName);
18906 if (actualType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018907 xmlChar *strA = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018908
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018909 xmlSchemaVCustomErr(ctxt,
18910 XML_SCHEMAV_CVC_ELT_4_2,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018911 (xmlNodePtr) attr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018912 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
18913 "The value %s does not resolve to a type "
18914 "definition",
18915 xmlSchemaFormatNsUriLocal(&strA, nsName, local));
18916 FREE_AND_NULL(strA);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018917 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018918 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018919 * URGENT TODO: cvc-elt (3.3.4) : 4.3 (Type Derivation OK)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018920 */
18921 }
18922 }
18923 FREE_AND_NULL(attrValue)
18924 FREE_AND_NULL(nsName)
18925 FREE_AND_NULL(local)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018926 }
18927 /* TODO: Change the handling of missing types according to
18928 * the spec.
18929 */
18930 if (actualType == NULL) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018931 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018932 XML_SCHEMAV_CVC_TYPE_1,
18933 elem, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018934 "The type definition is absent", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018935 /*
18936 * Evaluate IDCs even if an error occured.
18937 */
18938#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018939 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018940 return (-1);
18941#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018942 return (XML_SCHEMAV_CVC_TYPE_1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018943 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018944
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018945 /*
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018946 * Remember the actual-type definition.
18947 */
18948#ifdef ELEM_INFO_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018949 ctxt->nodeInfo->typeDef = actualType;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018950#endif
18951
18952 /*
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018953 * TODO: Since this should be already checked by the content model automaton,
18954 * and we want to get rid of the XML_SCHEMAS_ERR... types, the error code
18955 * has been changed to XML_SCHEMAV_INTERNAL.
18956 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018957 /*
Daniel Veillard4255d502002-04-16 15:50:10 +000018958 if (child == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000018959 if (decl->minOccurs > 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018960 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018961 XML_SCHEMAS_ERR_MISSING,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018962 "Element %s: missing child %s\n",
18963 node->name, decl->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018964 }
18965 return (ctxt->err);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018966 }
18967 */
Daniel Veillard4255d502002-04-16 15:50:10 +000018968 /*
18969 * Verify the element matches
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018970 * TODO, FIXME: Can this still happen here? Isn't this already checked
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018971 * by the content model automaton?
Daniel Veillardc0826a72004-08-10 14:17:33 +000018972 if (!xmlStrEqual(child->name, decl->name)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018973 xmlSchemaVErr3(ctxt, node, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018974 XML_SCHEMAS_ERR_WRONGELEM,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018975 "Element %s: missing child %s found %s\n",
18976 node->name, decl->name, child->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018977 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000018978 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018979 */
18980 if (elemHasContent == -1)
18981 elemHasContent = xmlSchemaHasElemOrCharContent(elem);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018982
18983 /*
18984 * IDC: Register identity-constraint XPath matchers.
18985 */
18986#ifdef IDC_ENABLED
18987 if (elemDecl->idcs != NULL)
18988 xmlSchemaIDCRegisterMatchers(ctxt, elemDecl);
18989 /*
18990 * Evaluate IDCs.
18991 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018992 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018993 return (-1);
18994#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018995 /*
18996 * cvc-elt (3.3.4) : 5
18997 * The appropriate case among the following must be true:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018998 */
Daniel Veillard4255d502002-04-16 15:50:10 +000018999 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019000 * cvc-elt (3.3.4) : 5.1
19001 * If the declaration has a {value constraint},
19002 * the item has neither element nor character [children] and
19003 * clause 3.2 has not applied, then all of the following must be true:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019004 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019005 if ((elemHasContent == 0) && (nilled == 0) && (elemDecl->value != NULL)) {
19006 /*
19007 * cvc-elt (3.3.4) : 5.1.1
19008 * If the ·actual type definition· is a ·local type definition·
19009 * then the canonical lexical representation of the {value constraint}
19010 * value must be a valid default for the ·actual type definition· as
19011 * defined in Element Default Valid (Immediate) (§3.3.6).
19012 */
19013 /*
19014 * NOTE: 'local' above means types aquired by xsi:type.
19015 */
19016 ret = 0;
19017 if (actualType != elemDecl->subtypes) {
19018 xmlSchemaCreatePCtxtOnVCtxt(ctxt);
19019 ret = xmlSchemaCheckCOSValidDefault(ctxt->pctxt, ctxt, actualType,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019020 elemDecl->value, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019021 if (ret < 0) {
19022 xmlSchemaVCustomErr(ctxt,
19023 XML_SCHEMAV_INTERNAL,
19024 elem, actualType,
19025 "Internal error: xmlSchemaValidateElementByDeclaration, "
19026 "validating a default value", NULL);
19027 return (-1);
19028 }
19029 }
19030 /*
19031 * cvc-elt (3.3.4) : 5.1.2
19032 * The element information item with the canonical lexical
19033 * representation of the {value constraint} value used as its
19034 * ·normalized value· must be ·valid· with respect to the
19035 * ·actual type definition· as defined by Element Locally Valid (Type)
19036 * (§3.3.4).
19037 */
19038 /*
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019039 * Disable validation of the simple content, if it was already
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019040 * done above.
19041 */
19042 if (ret == 0) {
19043 if (actualType != elemDecl->subtypes)
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019044 ret = xmlSchemaValidateElementByType(ctxt, actualType, 0, 0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019045 else
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019046 ret = xmlSchemaValidateElementByType(ctxt, actualType, 0, 1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019047 ctxt->node = elem;
19048 if (ret < 0) {
19049 xmlSchemaVCustomErr(ctxt,
19050 XML_SCHEMAV_INTERNAL,
19051 elem, actualType,
19052 "Internal error: xmlSchemaValidateElementByDeclaration, "
19053 "validating against the type", NULL);
19054 return (-1);
19055 }
19056 /*
19057 * PSVI: Create a text node on the instance element.
19058 */
19059 if (ctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
19060 xmlNodePtr textChild;
19061
19062 textChild = xmlNewText(elemDecl->value);
19063 if (textChild == NULL) {
19064 xmlSchemaVCustomErr(ctxt,
19065 XML_SCHEMAV_INTERNAL,
19066 elem, actualType,
19067 "Internal error: xmlSchemaValidateElementByDeclaration, "
19068 "could not create a default text node for the instance",
19069 NULL);
19070 } else
19071 xmlAddChild(elem, textChild);
19072 }
19073 }
19074
19075 } else {
19076 /*
19077 * 5.2.1 The element information item must be ·valid· with respect
19078 * to the ·actual type definition· as defined by Element Locally
19079 * Valid (Type) (§3.3.4).
19080 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019081 ret = xmlSchemaValidateElementByType(ctxt, actualType, nilled, 1);
19082 /*
19083 * Consume the computed value for IDCs, ect. Note that default
19084 * values are not supported yet.
19085 */
19086#ifdef ELEM_INFO_ENABLED
19087 if (ctxt->value != NULL) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019088 ctxt->nodeInfo->value = ctxt->value;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019089 ctxt->value = NULL;
19090 }
19091#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019092 ctxt->node = elem;
19093 if (ret < 0) {
19094 xmlSchemaVCustomErr(ctxt,
19095 XML_SCHEMAV_INTERNAL,
19096 elem, actualType,
19097 "Internal error: xmlSchemaValidateElementByDeclaration, "
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000019098 "calling validation by type", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019099 return (-1);
19100 }
19101 /*
19102 * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
19103 * not applied, all of the following must be true:
19104 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019105 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) && (nilled == 0)) {
19106 /*
19107 * 5.2.2.1 The element information item must have no element
19108 * information item [children].
19109 *
19110 * TODO REDUNDANT: If the actual type exists, the above call to
19111 * xmlSchemaValidateElementByType will already check for element
19112 * nodes.
19113 */
19114 if (xmlSchemaHasElemContent(elem)) {
19115 xmlSchemaVCustomErr(ctxt,
19116 XML_SCHEMAV_CVC_ELT_5_2_2_1,
19117 elem, (xmlSchemaTypePtr) elemDecl,
19118 "Elements in the content are not allowed if it is "
19119 "constrained by a fixed value", NULL);
19120 } else {
19121 /*
19122 * 5.2.2.2 The appropriate case among the following must
19123 * be true:
19124 */
19125
19126 if (actualType->contentType == XML_SCHEMA_CONTENT_MIXED) {
19127 xmlChar *value;
19128 /*
19129 * 5.2.2.2.1 If the {content type} of the ·actual type
19130 * definition· is mixed, then the *initial value* of the
19131 * item must match the canonical lexical representation
19132 * of the {value constraint} value.
19133 *
19134 * ... the *initial value* of an element information
19135 * item is the string composed of, in order, the
19136 * [character code] of each character information item in
19137 * the [children] of that element information item.
19138 */
19139 value = xmlNodeListGetString(elem->doc, elem->children, 1);
19140 if (! xmlStrEqual(BAD_CAST value, elemDecl->value)) {
19141 /*
19142 * TODO: Report invalid & expected values as well.
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019143 * TODO: Implement the canonical stuff.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019144 */
19145 xmlSchemaVCustomErr(ctxt,
19146 XML_SCHEMAV_CVC_ELT_5_2_2_2_1,
19147 elem, (xmlSchemaTypePtr) elemDecl,
19148 "The value does not match the cononical "
19149 "lexical representation of the fixed constraint",
19150 NULL);
19151 }
19152 if (value != NULL)
19153 xmlFree(value);
19154 } else if ((actualType->contentType ==
19155 XML_SCHEMA_CONTENT_SIMPLE) ||
19156 (actualType->contentType == XML_SCHEMA_CONTENT_BASIC)) {
19157 xmlChar *value;
19158
19159 /*
19160 * 5.2.2.2.2 If the {content type} of the ·actual type
19161 * definition· is a simple type definition, then the
19162 * *actual value* of the item must match the canonical
19163 * lexical representation of the {value constraint} value.
19164 */
19165 /*
19166 * TODO: *actual value* is the normalized value, impl. this.
19167 * TODO: Report invalid & expected values as well.
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019168 * TODO: Implement the canonical stuff.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019169 *
19170 */
19171 value = xmlNodeListGetString(elem->doc, elem->children, 1);
19172 if (! xmlStrEqual(BAD_CAST value, elemDecl->value)) {
19173 xmlSchemaVCustomErr(ctxt,
19174 XML_SCHEMAV_CVC_ELT_5_2_2_2_2,
19175 elem, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019176 "The normalized value does not match the canonical "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019177 "lexical representation of the fixed constraint",
19178 NULL);
19179 }
19180 if (value != NULL)
19181 xmlFree(value);
19182
19183 }
19184 /*
19185 * TODO: What if the content type is not 'mixed' or simple?
19186 */
19187
19188 }
19189
19190 }
19191 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019192 /*
19193 * TODO: 7 If the element information item is the ·validation root·, it must be
19194 * ·valid· per Validation Root Valid (ID/IDREF) (§3.3.4).
19195 */
19196
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019197 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000019198}
19199
Daniel Veillard4255d502002-04-16 15:50:10 +000019200/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019201 * xmlSchemaValidateElementByWildcardInternal:
Daniel Veillardc0826a72004-08-10 14:17:33 +000019202 * @ctxt: a schema validation context
19203 * @node: the top node.
19204 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019205 * Represents the recursive portion of xmlSchemaValidateElementByWildcard.
19206 * Not intended to be used by other functions.
Daniel Veillardc0826a72004-08-10 14:17:33 +000019207 *
19208 * Returns 0 if the element is valid, a positive error code
19209 * number otherwise and -1 in case of an internal error.
19210 */
19211static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019212xmlSchemaValidateElementByWildcardInternal(xmlSchemaValidCtxtPtr ctxt,
19213 xmlSchemaWildcardPtr wild,
19214 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +000019215{
19216 const xmlChar *uri;
19217 int ret = 0;
19218 xmlNodePtr child;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019219
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019220 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019221 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
19222 if (ret == -1) {
19223 xmlSchemaVCustomErr(ctxt,
19224 XML_SCHEMAV_INTERNAL,
19225 ctxt->node, NULL,
19226 "Internal error: xmlSchemaValidateElement, "
19227 "assembling schema by xsi", NULL);
19228 return (-1);
19229 }
19230 /*
19231 * NOTE: We won't react on schema parser errors here.
19232 * TODO: But a warning would be nice.
19233 */
19234 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000019235 if (wild->processContents != XML_SCHEMAS_ANY_SKIP) {
19236 xmlSchemaElementPtr decl = NULL;
19237
19238 if (node->ns != NULL)
19239 decl = xmlHashLookup3(ctxt->schema->elemDecl,
19240 node->name, node->ns->href, NULL);
19241 else
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019242 decl = xmlHashLookup3(ctxt->schema->elemDecl, node->name,
19243 NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000019244 if (decl != NULL) {
19245 ctxt->node = node;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019246 ret = xmlSchemaValidateElementByDeclaration(ctxt, decl);
Daniel Veillardc0826a72004-08-10 14:17:33 +000019247 if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000019248 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000019249 "Internal error: xmlSchemaValidateAnyInternal, "
19250 "validating an element in the context of a wildcard.",
19251 NULL, NULL);
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +000019252 }
19253 return (ret);
Daniel Veillardc0826a72004-08-10 14:17:33 +000019254 } else if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
19255 /* TODO: Change to proper error code. */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000019256 xmlSchemaVWildcardErr(ctxt, XML_SCHEMAV_CVC_ELT_1,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019257 node, wild, "No matching global declaration available");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019258 /*
19259 * Evaluate IDCs even if a validation error occured.
19260 */
19261#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019262 if (xmlSchemaXPathEvaluate(ctxt,XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019263 return(-1);
19264#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +000019265 return (ctxt->err);
19266 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019267 /*
19268 * Evaluate IDCs; we need to know if an IDC field resolves to
19269 * such a node. This node has no type definition and will
19270 * definitely result in an IDC validation error if an IDC field
19271 * resolves.
19272 */
19273#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019274 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019275 return(-1);
19276#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +000019277 }
19278 if (node->children != NULL) {
19279 child = node->children;
19280 do {
19281 if (child->type == XML_ELEMENT_NODE) {
19282 if (child->ns != NULL)
19283 uri = child->ns->href;
19284 else
19285 uri = NULL;
19286 if (xmlSchemaMatchesWildcardNs(wild, uri) == 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000019287 /* TODO: error code. */
19288 xmlSchemaVWildcardErr(ctxt, XML_SCHEMAV_ELEMENT_CONTENT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000019289 child, wild,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019290 "The namespace of the element is not allowed");
Daniel Veillardc0826a72004-08-10 14:17:33 +000019291 return (ctxt->err);
19292 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019293#ifdef ELEM_INFO_ENABLED
19294 ctxt->node = child;
19295 xmlSchemaBeginElement(ctxt);
19296#endif
19297 /*
19298 * Recurse over the children.
19299 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019300 ret = xmlSchemaValidateElementByWildcardInternal(ctxt,
19301 wild, child);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019302 if (ret == -1)
19303 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019304#ifdef ELEM_INFO_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019305 if (xmlSchemaEndElement(ctxt) == -1)
19306 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019307#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +000019308 if (ret != 0)
19309 return (ret);
19310 }
19311 child = child->next;
19312 } while (child != NULL);
19313 }
19314 return (0);
19315}
19316
19317/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019318 * xmlSchemaValidateElementContByWildcard:
Daniel Veillardc0826a72004-08-10 14:17:33 +000019319 * @ctxt: a schema validation context
19320 *
19321 * Returns 0 if the element is valid, a positive error code
19322 * number otherwise and -1 in case of an internal or API error.
19323 */
19324static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019325xmlSchemaValidateElementByWildcard(xmlSchemaValidCtxtPtr ctxt,
19326 xmlSchemaTypePtr type)
Daniel Veillardc0826a72004-08-10 14:17:33 +000019327{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019328 if ((type == NULL) || (type->type != XML_SCHEMA_TYPE_ANY) ||
19329 (ctxt->node == NULL)) {
19330 xmlSchemaVCustomErr(ctxt,
19331 XML_SCHEMAV_INTERNAL, ctxt->node, NULL,
19332 "Internal error: xmlSchemaValidateElementByWildcard, "
19333 "bad arguments", NULL);
19334 return (-1);
19335 }
19336 return(xmlSchemaValidateElementByWildcardInternal(ctxt,
19337 type->attributeWildcard, ctxt->node));
Daniel Veillardc0826a72004-08-10 14:17:33 +000019338}
19339
19340/**
William M. Brack2f2a6632004-08-20 23:09:47 +000019341 * xmlSchemaValidateAnyTypeContent:
19342 * @ctxt: a schema validation context
19343 * @node: the current element
19344 *
19345 * This one validates the content of an element of the type
19346 * 'anyType'. The process contents of the wildcard of 'anyType' is "lax",
19347 * thus elements in the subtree will be validated, if a corresponding
19348 * declaration in the schema exists.
19349 *
19350 * Returns 0 if the element and its subtree is valid, a positive error code
19351 * otherwise and -1 in case of an internal or API error.
19352 */
19353static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019354xmlSchemaValidateElementByAnyType(xmlSchemaValidCtxtPtr ctxt,
19355 xmlSchemaTypePtr type)
William M. Brack2f2a6632004-08-20 23:09:47 +000019356{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019357 xmlSchemaTypePtr oldtype;
19358 xmlNodePtr top, cur;
19359 xmlSchemaElementPtr decl;
William M. Brack2f2a6632004-08-20 23:09:47 +000019360 int skipContent, ret;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019361
19362 if ((type == NULL) || (ctxt->node == NULL))
19363 return (-1);
19364
19365 if (ctxt->node->children == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +000019366 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019367
19368 oldtype = ctxt->type;
19369 top = ctxt->node;
19370 /*
19371 * STREAM: Child nodes are processed.
19372 */
19373 cur = ctxt->node->children;
19374 while (cur != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +000019375 skipContent = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019376 if (cur->type == XML_ELEMENT_NODE) {
William M. Brack2f2a6632004-08-20 23:09:47 +000019377 /*
19378 * The process contents of the wildcard is "lax", thus
19379 * we need to validate the element if a declaration
19380 * exists.
19381 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019382 if (cur->ns != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +000019383 decl = xmlHashLookup3(ctxt->schema->elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019384 cur->name, cur->ns->href, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000019385 else
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019386 decl = xmlHashLookup3(ctxt->schema->elemDecl, cur->name, NULL, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000019387 if (decl != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019388 ctxt->node = cur;
19389 ret = xmlSchemaValidateElementByDeclaration(ctxt, decl);
19390 ctxt->node = top;
William M. Brack2f2a6632004-08-20 23:09:47 +000019391 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019392 xmlSchemaVErr(ctxt, cur, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000019393 "Internal error: xmlSchemaValidateAnyTypeContent, "
19394 "validating an element in the context of a wildcard.",
19395 NULL, NULL);
19396 return (ret);
19397 } else if (ret > 0)
19398 return (ret);
19399 skipContent = 1;
19400 }
19401 }
19402 /*
19403 * Browse the full subtree, deep first.
19404 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019405 if ((skipContent == 0) && (cur->children != NULL)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000019406 /* deep first */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019407 cur = cur->children;
19408 } else if ((cur != top) && (cur->next != NULL)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000019409 /* then siblings */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019410 cur = cur->next;
19411 } else if (cur != top) {
William M. Brack2f2a6632004-08-20 23:09:47 +000019412 /* go up to parents->next if needed */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019413 while (cur != top) {
19414 if (cur->parent != NULL)
19415 cur = cur->parent;
19416 if ((cur != top) && (cur->next != NULL)) {
19417 cur = cur->next;
William M. Brack2f2a6632004-08-20 23:09:47 +000019418 break;
19419 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019420 if (cur->parent == NULL) {
19421 cur = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000019422 break;
19423 }
19424 }
19425 /* exit condition */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019426 if (cur == top)
19427 cur = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000019428 } else
19429 break;
19430 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019431 ctxt->type = oldtype;
William M. Brack2f2a6632004-08-20 23:09:47 +000019432 return (0);
19433}
19434
19435/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019436 * xmlSchemaValidateElementByComplexType:
Daniel Veillard4255d502002-04-16 15:50:10 +000019437 * @ctxt: a schema validation context
19438 * @node: the top node.
19439 *
19440 * Validate the content of an element expected to be a complex type type
19441 * xmlschema-1.html#cvc-complex-type
19442 * Validation Rule: Element Locally Valid (Complex Type)
19443 *
19444 * Returns 0 if the element is schemas valid, a positive error code
Daniel Veillard01fa6152004-06-29 17:04:39 +000019445 * number otherwise and -1 in case of internal or API error.
19446 * Note on reported errors: Although it might be nice to report
19447 * the name of the simple/complex type, used to validate the content
19448 * of a node, it is quite unnecessary: for global defined types
19449 * the local name of the element is equal to the NCName of the type,
19450 * for local defined types it makes no sense to output the internal
19451 * computed name of the type. TODO: Instead, one should attach the
19452 * struct of the type involved to the error handler - this allows
19453 * the report of any additional information by the user.
Daniel Veillard4255d502002-04-16 15:50:10 +000019454 */
19455static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019456xmlSchemaValidateElementByComplexType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019457 xmlSchemaTypePtr type,
19458 int valSimpleContent)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019459{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019460 xmlSchemaTypePtr oldtype;
19461 xmlNodePtr elem, child;
Daniel Veillard01fa6152004-06-29 17:04:39 +000019462 int ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +000019463 const xmlChar *nsUri;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019464 xmlSchemaAttrStatePtr attrs = NULL, attrTop = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000019465
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019466 if ((ctxt == NULL) || (type->type != XML_SCHEMA_TYPE_COMPLEX))
19467 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000019468
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019469 oldtype = ctxt->type;
19470 ctxt->type = type;
19471 elem = ctxt->node;
19472
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019473 /*
19474 * Verify the attributes
19475 */
19476 /*
19477 * TODO: This "attrTop" thing is not needed any more.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019478 */
19479 /* NOTE: removed, since a check for abstract is
19480 * done in the cvc-type constraint.
19481 *
19482 *
19483 * if (type->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
19484 * xmlSchemaVComplexTypeErr(ctxt,
19485 * XML_SCHEMAV_CVC_COMPLEX_TYPE_1,
19486 * elem, type,
19487 * "The type definition is abstract");
19488 * return (XML_SCHEMAV_CVC_COMPLEX_TYPE_1);
19489 *}
19490 */
19491
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019492 attrs = ctxt->attr;
19493 attrTop = ctxt->attrTop;
19494 /*
19495 * STREAM: Attribute nodes are processed.
19496 */
19497 xmlSchemaRegisterAttributes(ctxt, elem->properties);
19498 xmlSchemaValidateAttributes(ctxt, elem, type);
19499 if (ctxt->attr != NULL)
19500 xmlSchemaFreeAttributeStates(ctxt->attr);
19501 ctxt->attr = attrs;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019502 ctxt->attrTop = attrTop;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019503
19504 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019505 * TODO: This one creates a regexp even if no content
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019506 * model was defined. Somehow ->contModel is always not NULL
19507 * for complex types, even if they are empty.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019508 * TODO: Check if the obove still occurs.
19509 */
Daniel Veillard4255d502002-04-16 15:50:10 +000019510 switch (type->contentType) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000019511 case XML_SCHEMA_CONTENT_EMPTY: {
19512 /*
19513 * 1 If the {content type} is empty, then the element information
19514 * item has no character or element information item [children].
Daniel Veillard3646d642004-06-02 19:19:14 +000019515 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000019516 /*
19517 * TODO: Is the entity stuff correct?
19518 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019519 if (xmlSchemaHasElemOrCharContent(elem) == 1) {
William M. Brack2f2a6632004-08-20 23:09:47 +000019520 xmlSchemaVComplexTypeErr(ctxt,
19521 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019522 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000019523 "Character or element content is not allowed, "
19524 "because the content type is empty");
Daniel Veillard01fa6152004-06-29 17:04:39 +000019525 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019526 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000019527 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019528 case XML_SCHEMA_CONTENT_MIXED:
19529 if ((type->subtypes == NULL) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019530 (type->baseType->builtInType == XML_SCHEMAS_ANYTYPE)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019531 /*
19532 * The type has 'anyType' as its base and no content model
19533 * is defined -> use 'anyType' as the type to validate
19534 * against.
19535 */
19536 ret = xmlSchemaValidateElementByAnyType(ctxt, type->baseType);
19537 /* TODO: Handle -1. */
19538 break;
19539 }
19540 /* No break on purpose. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000019541 case XML_SCHEMA_CONTENT_ELEMENTS:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019542 {
19543 xmlRegExecCtxtPtr oldregexp = NULL;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019544 xmlChar *values[10];
19545 int terminal, nbval = 10, nbneg;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019546
19547 /*
19548 * Content model check initialization.
19549 */
19550 if (type->contModel != NULL) {
19551 oldregexp = ctxt->regexp;
19552 ctxt->regexp = xmlRegNewExecCtxt(type->contModel,
19553 (xmlRegExecCallbacks)
19554 xmlSchemaValidateCallback, ctxt);
19555#ifdef DEBUG_AUTOMATA
19556 xmlGenericError(xmlGenericErrorContext, "====> %s\n", elem->name);
19557#endif
19558 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019559 /*
19560 * STREAM: Children are processed.
19561 */
19562 child = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000019563 while (child != NULL) {
19564 if (child->type == XML_ELEMENT_NODE) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000019565 if (child->ns != NULL)
19566 nsUri = child->ns->href;
19567 else
19568 nsUri = NULL;
19569 ret = xmlRegExecPushString2(ctxt->regexp,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019570 child->name, nsUri, child);
19571 if (ctxt->err == XML_SCHEMAV_INTERNAL)
19572 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019573 /*
19574 * URGENT TODO: Could we anchor an error report
19575 * here to notify of invalid elements?
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019576 * TODO: Perhaps it would be better to report
19577 * only the first erroneous element and then break.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019578 */
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019579#ifdef DEBUG_AUTOMATA
Daniel Veillard01fa6152004-06-29 17:04:39 +000019580 if (ret < 0)
19581 xmlGenericError(xmlGenericErrorContext,
19582 " --> %s Error\n", child->name);
William M. Bracke7091952004-05-11 15:09:58 +000019583 else
19584 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard01fa6152004-06-29 17:04:39 +000019585 " --> %s\n", child->name);
19586#endif
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019587 if (ret < 0) {
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019588 xmlRegExecErrInfo(ctxt->regexp, NULL, &nbval, &nbneg,
19589 &values[0], &terminal);
19590 xmlSchemaVComplexTypeElemErr(ctxt,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019591 XML_SCHEMAV_ELEMENT_CONTENT,
19592 child, NULL/* type */,
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019593 "This element is not expected",
19594 nbval, nbneg, values);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019595 ret = 1;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019596 /*
19597 * Note that this will skip further validation of the
19598 * content.
19599 */
19600 break;
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019601 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000019602 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) &&
19603 /*
19604 * TODO: Ask Daniel if this are all character nodes.
19605 */
19606 (((child->type == XML_TEXT_NODE) && (!IS_BLANK_NODE(child))) ||
19607 (child->type == XML_ENTITY_NODE) ||
19608 (child->type == XML_ENTITY_REF_NODE) ||
19609 (child->type == XML_CDATA_SECTION_NODE))) {
19610 /*
19611 * 2.3 If the {content type} is element-only, then the
19612 * element information item has no character information
19613 * item [children] other than those whose [character
19614 * code] is defined as a white space in [XML 1.0 (Second
19615 * Edition)].
19616 */
William M. Brack2f2a6632004-08-20 23:09:47 +000019617 xmlSchemaVComplexTypeErr(ctxt,
19618 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019619 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000019620 "Character content is not allowed, "
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019621 "because the content type is element-only");
19622 ret = 1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000019623 break;
19624 }
19625 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019626 }
19627 /*
19628 * Content model check finalization.
19629 */
19630 if (type->contModel != NULL) {
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019631 if (ret == 0) {
19632 xmlRegExecNextValues(ctxt->regexp, &nbval, &nbneg,
19633 &values[0], &terminal);
19634 if (nbval + nbneg != 0) {
19635 /*
19636 * If a next value still exists, I does not have to
19637 * mean that there's an element missing, since it
19638 * might be an optional element. So double check it.
19639 */
19640 ret = xmlRegExecPushString(ctxt->regexp,
19641 NULL, NULL);
19642 if (ret <= 0) {
19643 ret = 1;
19644 xmlSchemaVComplexTypeElemErr(ctxt,
19645 XML_SCHEMAV_ELEMENT_CONTENT,
19646 elem, type, "Missing child element(s)",
19647 nbval, nbneg, values);
19648 } else
19649 ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019650#ifdef DEBUG_AUTOMATA
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019651 xmlGenericError(xmlGenericErrorContext,
19652 "====> %s : %d\n", elem->name, ret);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019653#endif
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019654 }
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019655#ifdef DEBUG_CONTENT
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019656 if (ret == 0)
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019657 xmlGenericError(xmlGenericErrorContext,
19658 "Element %s content check succeeded\n",
19659 elem->name);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019660#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019661 }
19662 xmlRegFreeExecCtxt(ctxt->regexp);
19663 ctxt->regexp = oldregexp;
19664 }
19665 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000019666 break;
19667 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019668 case XML_SCHEMA_CONTENT_BASIC:
19669 /*
19670 * If the simple content was already validated
19671 * (e.g. a default value), the content need not
19672 * to be validated again.
19673 */
19674 if (valSimpleContent == 1) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000019675 xmlChar *value = NULL;
19676 /*
19677 * We hit a complexType with a simpleContent resolving
19678 * to a user derived or built-in simple type.
William M. Brack2f2a6632004-08-20 23:09:47 +000019679 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000019680 /*
19681 * 2.2 If the {content type} is a simple type definition,
19682 * then the element information item has no element
19683 * information item [children], and the ·normalized value·
19684 * of the element information item is ·valid· with respect
19685 * to that simple type definition as defined by String
19686 * Valid (§3.14.4).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019687 */
19688 /*
19689 * STREAM: Children are processed.
19690 */
19691 child = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000019692 while (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019693 /*
19694 * TODO: Could the entity stuff produce elements
19695 * as well?
19696 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000019697 if (child->type == XML_ELEMENT_NODE) {
William M. Brack2f2a6632004-08-20 23:09:47 +000019698 xmlSchemaVComplexTypeErr(ctxt,
19699 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019700 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000019701 "Element content is not allowed, because "
19702 "the content type is a simple type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000019703 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
19704 break;
19705 }
19706 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019707 }
19708 ctxt->node = elem;
19709 ctxt->cur = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000019710 if (ret == 0) {
19711 /*
19712 * Validate the character content against a simple type.
Daniel Veillard3646d642004-06-02 19:19:14 +000019713 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019714 /*
19715 * STREAM: Children are processed.
19716 */
19717 if (elem->children == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000019718 value = NULL;
19719 else
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019720 value = xmlNodeGetContent(elem);
19721 /*
19722 * URGENT TODO: Should facets for the simple type validation be
19723 * disabled, if the derivation of facets for complex types
19724 * is implemented?
19725 */
19726 /*
19727 * NOTE: This call won't check the correct types of the
19728 * content nodes, since this should be done here.
19729 */
19730 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type, value, 1, 1, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000019731 if (ret > 0) {
19732 /*
19733 * NOTE: Although an error will be reported by
19734 * xmlSchemaValidateSimpleTypeValue, the spec wants
19735 * a specific complex type error to be reported
19736 * additionally.
19737 */
19738 xmlSchemaVComplexTypeErr(ctxt,
19739 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019740 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000019741 "The character content is not valid");
Daniel Veillard01fa6152004-06-29 17:04:39 +000019742 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
19743 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019744 xmlSchemaVErr(ctxt, elem, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000019745 "Internal error: xmlSchemaValidateComplexType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000019746 "Element '%s': Error while validating character "
19747 "content against complex type '%s'.\n",
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019748 elem->name, type->name);
19749 if (value != NULL)
19750 xmlFree(value);
19751 ctxt->type = oldtype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000019752 return (-1);
19753 }
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000019754 }
19755#if 0
19756 /*
19757 * REMOVED since handled by xmlSchemaValidateSimpleTypeValue
19758 * already.
19759 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000019760 if (ret == 0) {
19761 /*
19762 * Apply facets of the complexType. Be sure to pass the
19763 * built-in type to xmlSchemaValidateFacetsInternal.
19764 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019765 /* URGENT TODO: I don't know yet if the facets of the simple type
Daniel Veillard01fa6152004-06-29 17:04:39 +000019766 * are used, or if the facets, defined by this complex type,
19767 * are to be used only. This here applies both facet sets.
19768 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000019769
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019770 ret = xmlSchemaValidateFacetsInternal(ctxt,
19771 type, value, 0, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000019772 if (ret > 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +000019773 xmlSchemaVComplexTypeErr(ctxt,
19774 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019775 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000019776 "The character content is not valid");
Daniel Veillard01fa6152004-06-29 17:04:39 +000019777 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
19778 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019779 xmlSchemaVErr(ctxt, elem, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000019780 "Internal error: xmlSchemaValidateComplexType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000019781 "Element '%s': Error while validating character "
19782 "content against complex type '%s'; failed to "
Daniel Veillard01fa6152004-06-29 17:04:39 +000019783 "apply facets.\n",
19784 type->name, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019785 if (value != NULL)
19786 xmlFree(value);
19787 ctxt->type = oldtype;
19788 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000019789 }
19790 }
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000019791#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +000019792 if (value != NULL)
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019793 xmlFree(value);
19794
Daniel Veillard01fa6152004-06-29 17:04:39 +000019795 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019796 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019797 default:
19798 TODO xmlGenericError(xmlGenericErrorContext,
19799 "unimplemented content type %d\n",
19800 type->contentType);
Daniel Veillard4255d502002-04-16 15:50:10 +000019801 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019802 ctxt->type = oldtype;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019803 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000019804}
19805
19806/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019807 * xmlSchemaValidateElementByType:
Daniel Veillard4255d502002-04-16 15:50:10 +000019808 * @ctxt: a schema validation context
19809 * @elem: an element
19810 * @type: the list of type declarations
19811 *
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019812 * Validation Rule: Element Locally Valid (Type).
Daniel Veillard4255d502002-04-16 15:50:10 +000019813 *
19814 * Returns 0 if the element is schemas valid, a positive error code
19815 * number otherwise and -1 in case of internal or API error.
19816 */
19817static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019818xmlSchemaValidateElementByType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019819 xmlSchemaTypePtr type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019820 int isNil,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019821 int valSimpleContent)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019822{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019823 int ret;
Daniel Veillard4255d502002-04-16 15:50:10 +000019824
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019825
19826 if ((ctxt == NULL) || (type == NULL)) {
19827 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_INTERNAL, NULL, NULL,
19828 "Internal error: xmlSchemaValidateElementByType, "
19829 "bad arguments", NULL);
19830 return (-1);
19831 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019832 /*
19833 * This one is called by "xmlSchemaValidateElementByDeclaration".
19834 * It will forward to the proper validation
19835 * procedures for the given type.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019836 */
19837 if (type == NULL) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019838 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019839 XML_SCHEMAV_CVC_TYPE_1,
19840 ctxt->node, NULL,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019841 "The type definition is absent", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019842 return (XML_SCHEMAV_CVC_TYPE_1);
19843 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019844
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019845 if (type->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019846 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019847 XML_SCHEMAV_CVC_TYPE_2,
19848 ctxt->node, type,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019849 "The type definition is abstract", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019850 return (XML_SCHEMAV_CVC_TYPE_2);
19851 }
19852
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019853 switch (type->type) {
19854 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019855 ret = xmlSchemaValidateElementByComplexType(ctxt, type,
19856 valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019857 break;
19858 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019859 ret = xmlSchemaValidateElementBySimpleType(ctxt, type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019860 isNil, valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019861 break;
19862 case XML_SCHEMA_TYPE_BASIC:
19863 if (type->builtInType == XML_SCHEMAS_ANYTYPE)
19864 ret = xmlSchemaValidateElementByAnyType(ctxt, type);
19865 else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019866 ret = xmlSchemaValidateElementBySimpleType(ctxt, type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019867 isNil, valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019868 break;
19869 default:
19870 ret = -1;
19871 break;
19872 }
19873 if (ret == -1)
19874 return (-1);
19875 else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019876 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000019877}
19878
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019879static int
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019880xmlSchemaPostCreateVal(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000019881 xmlSchemaTypePtr type,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019882 const xmlChar *value,
19883 xmlSchemaValPtr *val)
19884{
19885 xmlSchemaTypePtr prim;
19886
19887 if (val == NULL) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000019888 xmlSchemaVErr(vctxt, NULL,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019889 XML_SCHEMAV_INTERNAL,
19890 "Internal error: xmlSchemaPostCreateVal, "
19891 "bad arguments", NULL, NULL);
19892 return (-1);
19893 }
19894 /*
19895 * Only string or anySimpleType values are expected to be post-created.
19896 */
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000019897 prim = xmlSchemaGetPrimitiveType(type);
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019898 if ((prim->builtInType == XML_SCHEMAS_STRING) ||
19899 (prim->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
19900 {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019901 if (value == NULL)
19902 /* TODO: Can this happen at all? */
19903 *val = xmlSchemaNewStringValue(XML_SCHEMAS_STRING,
19904 xmlStrdup(BAD_CAST ""));
19905 else
19906 *val = xmlSchemaNewStringValue(XML_SCHEMAS_STRING, value);
19907 if ((*val) == NULL) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000019908 xmlSchemaVErr(vctxt, NULL,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019909 XML_SCHEMAV_INTERNAL,
19910 "Internal error: xmlSchemaPostCreateVal, "
19911 "failed to create the value", NULL, NULL);
19912 return (-1);
19913 }
19914 return (0);
19915 }
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000019916 xmlSchemaVErr(vctxt, NULL,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019917 XML_SCHEMAV_INTERNAL,
19918 "Internal error: xmlSchemaPostCreateVal, "
19919 "the given type is not supported", NULL, NULL);
19920 return (-1);
19921}
19922
19923static int
19924xmlSchemaCheckAttrLocallyValid(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019925 xmlSchemaAttrStatePtr state)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019926{
19927 xmlChar *value;
19928 const xmlChar *defValue;
19929 xmlSchemaValPtr defVal;
19930 int fixed;
19931 int ret;
19932
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019933 if (vctxt->attrInfo->typeDef == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019934 state->state = XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED;
19935 return (XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED);
19936 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019937 vctxt->node = vctxt->attrInfo->node;
19938 vctxt->cur = vctxt->node->children;
19939 /* STREAM */
19940 value = xmlNodeListGetString(vctxt->node->doc, vctxt->cur, 1);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019941
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019942 /*
19943 * NOTE: This call also checks the content nodes for correct type.
19944 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019945 ret = xmlSchemaValidateSimpleTypeValue(vctxt, vctxt->attrInfo->typeDef,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019946 value, 1, 1, 1, 1);
19947
19948 /*
19949 * Handle 'fixed' attributes.
19950 */
19951 if (ret > 0) {
19952 state->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
19953 /*
19954 * NOTE: Fixed value constraints will be not
19955 * applied if the value was invalid, because:
19956 * 1. The validation process does not return a precomputed
19957 * value.
19958 * 2. An invalid value implies a violation of a fixed
19959 * value constraint.
19960 */
19961 } else if (ret == 0) {
19962 state->state = XML_SCHEMAS_ATTR_CHECKED;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019963 if (xmlSchemaGetEffectiveValueConstraint(
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019964 (xmlSchemaAttributePtr) vctxt->attrInfo->decl,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019965 &fixed, &defValue, &defVal) && (fixed == 1)) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000019966
19967 int ws = xmlSchemaGetWhiteSpaceFacetValue(
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019968 vctxt->nodeInfo->typeDef);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019969 /*
19970 * cvc-au : Attribute Locally Valid (Use)
19971 * For an attribute information item to be·valid·
19972 * with respect to an attribute use its ·normalized
19973 * value· must match the canonical lexical representation
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019974 * of the attribute use's {value constraint} value, if it
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019975 * is present and fixed.
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019976 *
19977 * TODO: Use somehow the *normalized* value and the *canonical*
19978 * fixed value. This here compares the canonical values of both.
19979 * The normalized value of, for example, a float type can differ
19980 * from its canonical representation. This all means that a fixed
19981 * value can only be OK, if it's present in the canonical form in
19982 * the instance.
19983 * NOTE: Since the value for string and anySimpleType is not always
19984 * precomputed during validation, we need to do it now.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019985 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019986 if (vctxt->value == NULL) {
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000019987 /*
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019988 * Post-create the value.
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000019989 */
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000019990 if (xmlSchemaPostCreateVal(vctxt, vctxt->attrInfo->typeDef,
19991 value, &(vctxt->value)) == -1) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019992 ret = -1;
19993 goto exit;
19994 }
19995 value = NULL;
19996 }
19997 if (defVal == NULL) {
19998 xmlChar *str;
19999
20000 /*
20001 * Post-create the default/fixed value.
20002 */
20003 if (defValue == NULL)
20004 str = xmlStrdup(BAD_CAST "");
20005 else
20006 str = xmlStrdup(defValue);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000020007 if (xmlSchemaPostCreateVal(vctxt, vctxt->attrInfo->typeDef,
20008 str, &defVal) == -1) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020009 ret = -1;
20010 FREE_AND_NULL(str)
20011 goto exit;
20012 }
20013 ((xmlSchemaAttributePtr) vctxt->attrInfo->decl)->defVal = defVal;
20014 }
20015 if (xmlSchemaCompareValuesWhtsp(vctxt->value,
20016 (xmlSchemaWhitespaceValueType) ws,
20017 defVal,
20018 (xmlSchemaWhitespaceValueType) ws) != 0)
20019 {
20020 state->state = XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020021 }
20022 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020023 }
20024exit:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020025 if (value != NULL) {
20026 xmlFree(value);
20027 }
20028 return (ret);
20029}
20030
Daniel Veillard4255d502002-04-16 15:50:10 +000020031/**
20032 * xmlSchemaValidateAttributes:
20033 * @ctxt: a schema validation context
20034 * @elem: an element
Daniel Veillard3646d642004-06-02 19:19:14 +000020035 * @type: the complexType holding the attribute uses
Daniel Veillard4255d502002-04-16 15:50:10 +000020036 *
20037 * Validate the attributes of an element.
20038 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000020039 * 1. Existent, invalid attributes are reported in the form
20040 * "prefix:localName".
20041 * Reason: readability - it is easier to find the actual XML
20042 * representation of the attributes QName.
20043 * 2. Missing attributes are reported in the form
20044 * {"URI", "localName"}.
20045 * This is necessary, since the the prefix need not to be declared
20046 * at all, and thus is not computable.
20047 *
Daniel Veillard4255d502002-04-16 15:50:10 +000020048 * Returns 0 if the element is schemas valid, a positive error code
20049 * number otherwise and -1 in case of internal or API error.
20050 */
20051static int
Daniel Veillard3646d642004-06-02 19:19:14 +000020052xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem, xmlSchemaTypePtr type)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020053{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020054 const xmlChar *nsURI;
Daniel Veillard3646d642004-06-02 19:19:14 +000020055 int ret;
20056 xmlAttrPtr attr; /* An attribute on the element. */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020057 const xmlChar *defValue;
20058 xmlSchemaValPtr defVal;
20059 int fixed;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020060 xmlSchemaAttributeLinkPtr attrUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000020061 xmlSchemaAttributePtr attrDecl;
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000020062 int found;
William M. Brack803812b2004-06-03 02:11:24 +000020063 xmlSchemaAttrStatePtr curState, reqAttrStates = NULL, reqAttrStatesTop = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020064 xmlSchemaAttrStatePtr defAttrStates = NULL, defAttrStatesTop = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020065 xmlNodePtr oldnode;
Daniel Veillard3646d642004-06-02 19:19:14 +000020066#ifdef DEBUG_ATTR_VALIDATION
20067 int redundant = 0;
20068#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000020069
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020070
Daniel Veillardc0826a72004-08-10 14:17:33 +000020071 /*
20072 * Allow all attributes if the type is anyType.
20073 */
20074 if (type == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE))
20075 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020076
20077 oldnode = ctxt->node;
20078 if (type != NULL)
20079 attrUse = type->attributeUses;
Daniel Veillard3646d642004-06-02 19:19:14 +000020080 while (attrUse != NULL) {
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000020081 found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000020082 attrDecl = attrUse->attr;
20083#ifdef DEBUG_ATTR_VALIDATION
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020084 printf("attr use - name: %s\n", xmlSchemaGetAttrName(attrDecl));
Daniel Veillard3646d642004-06-02 19:19:14 +000020085 printf("attr use - use: %d\n", attrDecl->occurs);
20086#endif
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020087 for (curState = ctxt->attr; curState != NULL; curState = curState->next) {
Daniel Veillard3646d642004-06-02 19:19:14 +000020088
20089 if (curState->decl == attrUse->attr) {
20090#ifdef DEBUG_ATTR_VALIDATION
20091 redundant = 1;
20092#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020093 }
Daniel Veillard3646d642004-06-02 19:19:14 +000020094 attr = curState->attr;
20095#ifdef DEBUG_ATTR_VALIDATION
20096 printf("attr - name: %s\n", attr->name);
20097 if (attr->ns != NULL)
20098 printf("attr - ns: %s\n", attr->ns->href);
20099 else
20100 printf("attr - ns: none\n");
20101#endif
20102 /* TODO: Can this ever happen? */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020103 if (attr == NULL)
20104 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000020105 if (attrDecl->ref != NULL) {
20106 if (!xmlStrEqual(attr->name, attrDecl->ref))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020107 continue;
20108 if (attr->ns != NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000020109 if ((attrDecl->refNs == NULL) ||
20110 (!xmlStrEqual(attr->ns->href, attrDecl->refNs)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020111 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000020112 } else if (attrDecl->refNs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020113 continue;
20114 }
20115 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000020116 if (!xmlStrEqual(attr->name, attrDecl->name))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020117 continue;
20118 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +000020119 * handle the namespaces checks here
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020120 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000020121 if (attr->ns == NULL) {
20122 /*
William M. Bracke7091952004-05-11 15:09:58 +000020123 * accept an unqualified attribute only if the target
20124 * namespace of the declaration is absent.
Daniel Veillardbe9c6322003-11-22 20:37:51 +000020125 */
Daniel Veillard3646d642004-06-02 19:19:14 +000020126 if (attrDecl->targetNamespace != NULL)
William M. Bracke7091952004-05-11 15:09:58 +000020127 /*
20128 * This check was removed, since the target namespace
20129 * was evaluated during parsing and already took
20130 * "attributeFormDefault" into account.
20131 */
20132 /* ((attributes->flags & XML_SCHEMAS_ATTR_NSDEFAULT) == 0)) */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000020133 continue;
20134 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000020135 if (attrDecl->targetNamespace == NULL)
Daniel Veillardbe9c6322003-11-22 20:37:51 +000020136 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000020137 if (!xmlStrEqual(attrDecl->targetNamespace,
Daniel Veillardbe9c6322003-11-22 20:37:51 +000020138 attr->ns->href))
20139 continue;
20140 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020141 }
Daniel Veillard3646d642004-06-02 19:19:14 +000020142#ifdef DEBUG_ATTR_VALIDATION
20143 printf("found\n");
20144#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020145 found = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +000020146 curState->decl = attrDecl;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020147 curState->state = XML_SCHEMAS_ATTR_VALIDATE_VALUE;
20148 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020149 ret = xmlSchemaCheckAttrLocallyValid(ctxt, attrDecl, curState, attr);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020150 */
Daniel Veillard3646d642004-06-02 19:19:14 +000020151 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020152 if (!found) {
20153 if (attrDecl->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
20154 xmlSchemaAttrStatePtr tmp;
20155
Daniel Veillard3646d642004-06-02 19:19:14 +000020156#ifdef DEBUG_ATTR_VALIDATION
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020157 printf("required attr not found\n");
Daniel Veillard3646d642004-06-02 19:19:14 +000020158#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020159 /*
20160 * Add a new dummy attribute state.
20161 */
20162 tmp = (xmlSchemaAttrStatePtr) xmlMalloc(sizeof(xmlSchemaAttrState));
20163 if (tmp == NULL) {
20164 xmlSchemaVErrMemory(ctxt, "registering required attributes", NULL);
20165 ctxt->node = oldnode;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020166 goto fatal_exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020167 }
20168 tmp->attr = NULL;
20169 tmp->state = XML_SCHEMAS_ATTR_MISSING;
20170 tmp->decl = attrDecl;
20171 tmp->next = NULL;
20172
20173 if (reqAttrStates == NULL) {
20174 reqAttrStates = tmp;
20175 reqAttrStatesTop = tmp;
20176 } else {
20177 reqAttrStatesTop->next = tmp;
20178 reqAttrStatesTop = tmp;
20179 }
20180 } else if ((attrDecl->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
20181 (xmlSchemaGetEffectiveValueConstraint(attrDecl,
20182 &fixed, &defValue, &defVal))) {
20183 xmlSchemaAttrStatePtr tmp;
20184 /*
20185 * Handle non existent default/fixed attributes.
20186 */
20187 tmp = (xmlSchemaAttrStatePtr)
20188 xmlMalloc(sizeof(xmlSchemaAttrState));
20189 if (tmp == NULL) {
20190 xmlSchemaVErrMemory(ctxt,
20191 "registering schema specified attributes", NULL);
20192 ctxt->node = oldnode;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020193 goto fatal_exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020194 }
20195 tmp->attr = NULL;
20196 tmp->state = XML_SCHEMAS_ATTR_DEFAULT;
20197 tmp->decl = attrDecl;
20198 tmp->value = defValue;
20199 tmp->next = NULL;
20200
20201 if (defAttrStates == NULL) {
20202 defAttrStates = tmp;
20203 defAttrStates = tmp;
20204 } else {
20205 defAttrStates->next = tmp;
20206 defAttrStatesTop = tmp;
20207 }
20208 }
Daniel Veillard3646d642004-06-02 19:19:14 +000020209 }
20210 attrUse = attrUse->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000020211 }
Daniel Veillard3646d642004-06-02 19:19:14 +000020212 /*
20213 * Add required attributes to the attribute states of the context.
20214 */
20215 if (reqAttrStates != NULL) {
20216 if (ctxt->attr == NULL) {
20217 ctxt->attr = reqAttrStates;
20218 } else {
20219 ctxt->attrTop->next = reqAttrStates;
20220 }
20221 ctxt->attrTop = reqAttrStatesTop;
Daniel Veillardc0826a72004-08-10 14:17:33 +000020222 }
Daniel Veillard3646d642004-06-02 19:19:14 +000020223 /*
20224 * Process wildcards.
20225 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020226
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020227 if ((type != NULL) && (type->attributeWildcard != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000020228#ifdef DEBUG_ATTR_VALIDATION
20229 xmlSchemaWildcardNsPtr ns;
20230 printf("matching wildcard: [%d] of complexType: %s\n", type->attributeWildcard, type->name);
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000020231 if (type->attributeWildcard->processContents ==
20232 XML_SCHEMAS_ANY_LAX)
20233 printf("processContents: lax\n");
20234 else if (type->attributeWildcard->processContents ==
20235 XML_SCHEMAS_ANY_STRICT)
20236 printf("processContents: strict\n");
20237 else
20238 printf("processContents: skip\n");
Daniel Veillard3646d642004-06-02 19:19:14 +000020239 if (type->attributeWildcard->any)
20240 printf("type: any\n");
20241 else if (type->attributeWildcard->negNsSet != NULL) {
20242 printf("type: negated\n");
20243 if (type->attributeWildcard->negNsSet->value == NULL)
20244 printf("ns: (absent)\n");
20245 else
20246 printf("ns: %s\n", type->attributeWildcard->negNsSet->value);
20247 } else if (type->attributeWildcard->nsSet != NULL) {
20248 printf("type: set\n");
20249 ns = type->attributeWildcard->nsSet;
20250 while (ns != NULL) {
20251 if (ns->value == NULL)
20252 printf("ns: (absent)\n");
20253 else
20254 printf("ns: %s\n", ns->value);
20255 ns = ns->next;
20256 }
20257 } else
20258 printf("empty\n");
20259
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000020260
20261#endif
Daniel Veillard3646d642004-06-02 19:19:14 +000020262 curState = ctxt->attr;
20263 while (curState != NULL) {
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000020264 if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
20265 if (curState->attr->ns != NULL)
20266 nsURI = curState->attr->ns->href;
20267 else
20268 nsURI = NULL;
20269 if (xmlSchemaMatchesWildcardNs(type->attributeWildcard,
20270 nsURI)) {
20271 /*
20272 * Handle processContents.
20273 */
20274 if ((type->attributeWildcard->processContents ==
20275 XML_SCHEMAS_ANY_LAX) ||
20276 (type->attributeWildcard->processContents ==
20277 XML_SCHEMAS_ANY_STRICT)) {
20278
20279 attr = curState->attr;
20280 attrDecl = xmlSchemaGetAttribute(ctxt->schema,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020281 attr->name, nsURI);
20282 curState->decl = attrDecl;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000020283 if (attrDecl != NULL) {
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000020284 curState->decl = attrDecl;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020285 curState->state = XML_SCHEMAS_ATTR_VALIDATE_VALUE;
20286 /* TODO
20287 ret = xmlSchemaCheckAttrLocallyValid(ctxt, attrDecl, curState, attr);
20288 */
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000020289 } else if (type->attributeWildcard->processContents ==
20290 XML_SCHEMAS_ANY_LAX) {
20291 curState->state = XML_SCHEMAS_ATTR_CHECKED;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020292 } else
20293 curState->state = XML_SCHEMAS_ATTR_WILD_NO_DECL;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000020294 } else
Daniel Veillard3646d642004-06-02 19:19:14 +000020295 curState->state = XML_SCHEMAS_ATTR_CHECKED;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020296 }
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000020297 }
Daniel Veillard3646d642004-06-02 19:19:14 +000020298 curState = curState->next;
20299 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020300 }
20301
Daniel Veillardc0826a72004-08-10 14:17:33 +000020302 if (ctxt->attr != NULL) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020303 int valueNeeded;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020304
20305 /*
20306 * Validate the value of the attribute.
20307 */
20308 if (ctxt->value != NULL) {
20309 xmlSchemaFreeValue(ctxt->value);
20310 ctxt->value = NULL;
20311 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000020312 curState = ctxt->attr;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020313 while ((curState != NULL) && (curState != ctxt->attrTop->next)) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020314 valueNeeded = 0;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020315 switch (curState->state) {
20316 case XML_SCHEMAS_ATTR_VALIDATE_VALUE:
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020317
20318 /*
20319 * Create an attribute info if needed.
20320 */
20321 if (ctxt->attrInfo == NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020322 ctxt->attrInfo = (xmlSchemaNodeInfoPtr)
20323 xmlMalloc(sizeof(xmlSchemaNodeInfo));
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020324 if (ctxt->attrInfo == NULL) {
20325 xmlSchemaVErrMemory(ctxt,
20326 "allocating an attribute info", NULL);
20327 goto fatal_exit;
20328 }
20329 }
20330 /*
20331 * Init the attribute info.
20332 */
20333 ctxt->attrInfo->flags = 0;
20334 ctxt->attrInfo->node = (xmlNodePtr) curState->attr;
20335 ctxt->attrInfo->decl = (xmlSchemaTypePtr) curState->decl;
20336 ctxt->attrInfo->value = NULL;
20337 if (curState->decl != NULL)
20338 ctxt->attrInfo->typeDef = curState->decl->subtypes;
20339 else
20340 ctxt->attrInfo->typeDef = NULL;
20341 if (curState->attr->ns != NULL)
20342 ctxt->attrInfo->namespaceName =
20343 curState->attr->ns->href;
20344 else
20345 ctxt->attrInfo->namespaceName = NULL;
20346 ctxt->attrInfo->localName = curState->attr->name;
20347
20348 ctxt->nodeInfo = ctxt->attrInfo;
20349
20350#ifdef IDC_ENABLED
20351 /*
20352 * Evaluate IDCs.
20353 */
20354 if (ctxt->xpathStates != NULL) {
20355 ret = xmlSchemaXPathEvaluate(ctxt,
20356 XML_ATTRIBUTE_NODE);
20357 if (ret == -1)
20358 goto fatal_exit;
20359 }
20360
20361#endif
20362 ret = xmlSchemaCheckAttrLocallyValid(ctxt, curState);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020363 if (ret == -1)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020364 goto fatal_exit;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020365 if ((ret != 0) && (ctxt->value != NULL)) {
20366 xmlSchemaFreeValue(ctxt->value);
20367 ctxt->value = NULL;
20368 }
20369 /* No break on purpose. */
20370 case XML_SCHEMAS_ATTR_CHECKED:
20371#ifdef IDC_ENABLED
20372 if (ctxt->xpathStates != NULL) {
20373 /*
20374 * Evaluate IDCs.
20375 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020376 if (ctxt->value != NULL) {
20377 ctxt->attrInfo->value = ctxt->value;
20378 ctxt->value = NULL;
20379 }
20380 if (xmlSchemaXPathProcessHistory(ctxt, ctxt->depth +1) == -1)
20381 goto fatal_exit;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020382 }
20383 break;
20384#endif
20385 default:
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020386 break;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020387 }
20388 curState = curState->next;
20389 }
20390
20391 /*
20392 * Report missing and illegal attributes.
20393 */
20394 curState = ctxt->attr;
20395 while ((curState != NULL) && (curState != ctxt->attrTop->next)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000020396 if (curState->state != XML_SCHEMAS_ATTR_CHECKED) {
20397 attr = curState->attr;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020398 if (curState->decl != NULL) {
20399 if (curState->decl->ref != NULL)
20400 attrDecl = curState->decl->refDecl;
20401 else
20402 attrDecl = curState->decl;
20403 } else
20404 attrDecl = NULL;
20405 if (curState->state == XML_SCHEMAS_ATTR_MISSING) {
20406 xmlSchemaVMissingAttrErr(ctxt, elem, attrDecl);
20407 } else if (curState->state ==
20408 XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED) {
20409 xmlSchemaVCustomErr(ctxt,
20410 XML_SCHEMAV_CVC_ATTRIBUTE_2,
20411 (xmlNodePtr) attr,
20412 (xmlSchemaTypePtr) attrDecl,
20413 "The type definition is absent",
20414 NULL);
20415 } else if (curState->state ==
20416 XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE) {
20417 xmlSchemaVCustomErr(ctxt,
20418 XML_SCHEMAV_CVC_AU,
20419 (xmlNodePtr) attr, (xmlSchemaTypePtr) attrDecl,
20420 "The value does not match the fixed value "
20421 "constraint", NULL);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020422 } else if (curState->state == XML_SCHEMAS_ATTR_WILD_NO_DECL) {
20423 xmlSchemaVWildcardErr(ctxt,
20424 XML_SCHEMAV_CVC_WILDCARD,
20425 (xmlNodePtr) attr,
20426 type->attributeWildcard,
20427 "No global attribute declaration found, but "
20428 "stipulated by the strict processContents of "
20429 "the wildcard");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020430 } else if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000020431 /* TODO: "prohibited" won't ever be touched here!.
20432 (curState->state == XML_SCHEMAS_ATTR_PROHIBITED))
20433 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020434 /*
20435 * TODO: One might report different error messages
20436 * for the following errors.
20437 */
20438 if ((type == NULL) || (type->attributeWildcard == NULL)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000020439 xmlSchemaVIllegalAttrErr(ctxt,
20440 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, attr);
20441 } else {
20442 xmlSchemaVIllegalAttrErr(ctxt,
20443 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, attr);
20444 }
20445 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000020446 }
20447 curState = curState->next;
20448 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020449 }
20450
20451 /*
20452 * Add missing default/fixed attributes.
20453 */
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000020454 if (defAttrStates != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020455 curState = defAttrStates;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000020456
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020457 while (curState != NULL) {
20458 attrDecl = curState->decl;
20459 if (attrDecl->ref != NULL)
20460 attrDecl = attrDecl->refDecl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020461
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000020462#ifdef IDC_ENABLED
20463 /*
20464 * Evaluate IDCs on default attributes.
20465 */
20466 if (ctxt->xpathStates != NULL) {
20467 /*
20468 * Create an attribute info if needed.
20469 */
20470 if (ctxt->attrInfo == NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020471 ctxt->attrInfo = (xmlSchemaNodeInfoPtr)
20472 xmlMalloc(sizeof(xmlSchemaNodeInfo));
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000020473 if (ctxt->attrInfo == NULL) {
20474 xmlSchemaVErrMemory(ctxt,
20475 "allocating an attribute info", NULL);
20476 goto fatal_exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020477 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020478 ctxt->attrInfo->value = NULL;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000020479 }
20480 /*
20481 * Init the attribute info.
Kasimier T. Buchcik285ebab2005-03-04 18:04:59 +000020482 * TODO: Hmm, maby a bit oversized this all.
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000020483 */
20484 ctxt->attrInfo->flags = 0;
20485 ctxt->attrInfo->decl = (xmlSchemaTypePtr) attrDecl;
20486 ctxt->attrInfo->node = NULL;
20487 ctxt->attrInfo->typeDef = attrDecl->subtypes;
20488 ctxt->attrInfo->namespaceName = attrDecl->targetNamespace;
20489 ctxt->attrInfo->localName = attrDecl->name;
20490
20491 ctxt->nodeInfo = ctxt->attrInfo;
20492
20493 ret = xmlSchemaXPathEvaluate(ctxt,
20494 XML_ATTRIBUTE_NODE);
20495 if (ret == -1)
20496 goto fatal_exit;
20497 if (ctxt->attrInfo->value != NULL) {
20498 xmlSchemaFreeValue(ctxt->attrInfo->value);
20499 ctxt->attrInfo->value = NULL;
20500 }
20501 if (ret > 0) {
Kasimier T. Buchcik285ebab2005-03-04 18:04:59 +000020502 /*
20503 * IDCs will consume the precomputed default value,
20504 * so we need to clone it somehow.
20505 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020506 /*
20507 * string or anySimpleType does not create a precomputed value
20508 * by default, so it will be created here on demand.
20509 * TODO: default/fixed attributes are a bit unoptimized:
20510 * the string value will be hold by ->defValue and inside
20511 * the precomputed value.
20512 */
20513 if (attrDecl->defVal == NULL) {
20514 xmlChar *str = xmlStrdup(attrDecl->defValue);
20515
20516 if (xmlSchemaPostCreateVal(ctxt,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000020517 ctxt->attrInfo->typeDef,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020518 str,
20519 &(attrDecl->defVal)) == -1) {
20520 FREE_AND_NULL(str)
20521 goto fatal_exit;
20522 }
20523 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000020524 ctxt->attrInfo->value = xmlSchemaCopyValue(attrDecl->defVal);
20525 /* TODO: error on NULL return. */
20526 }
Kasimier T. Buchcik285ebab2005-03-04 18:04:59 +000020527
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000020528 if (xmlSchemaXPathProcessHistory(ctxt, ctxt->depth +1) == -1)
20529 goto fatal_exit;
20530 }
20531#endif
20532
20533 if (ctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
20534 /*
20535 * PSVI: Add a new attribute node to the current element.
20536 */
20537 if (attrDecl->targetNamespace == NULL) {
20538 xmlNewProp(elem, attrDecl->name, curState->value);
20539 } else {
20540 xmlNsPtr ns;
20541
20542 ns = xmlSearchNsByHref(elem->doc, elem,
20543 attrDecl->targetNamespace);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020544 if (ns == NULL) {
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000020545 xmlChar prefix[12];
20546 int counter = 1;
20547
20548 attr = curState->attr;
20549 /*
20550 * Create a namespace declaration on the validation
20551 * root node if no namespace declaration is in scope.
20552 */
20553 snprintf((char *) prefix, sizeof(prefix), "p");
20554 /*
20555 * This is somehow not performant, since the ancestor
20556 * axis beyond @elem will be searched as well.
20557 */
20558 ns = xmlSearchNs(elem->doc, elem, BAD_CAST prefix);
20559 while (ns != NULL) {
20560 if (counter > 1000) {
20561 xmlSchemaVErr(ctxt, (xmlNodePtr) attr,
20562 XML_SCHEMAV_INTERNAL,
20563 "Internal error: xmlSchemaValidateAttributes, "
20564 "could not compute a ns prefix for "
20565 "default/fixed attribute '%s'.\n",
20566 attrDecl->name, NULL);
20567
20568 break;
20569 }
20570 snprintf((char *) prefix,
20571 sizeof(prefix), "p%d", counter++);
20572 ns = xmlSearchNs(elem->doc, elem,
20573 BAD_CAST prefix);
20574 }
20575 if (ns == NULL) {
20576 ns = xmlNewNs(ctxt->validationRoot,
20577 attrDecl->targetNamespace, BAD_CAST prefix);
20578 xmlNewNsProp(elem, ns, attrDecl->name,
20579 curState->value);
20580 }
20581 } else {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020582 xmlNewNsProp(elem, ns, attrDecl->name,
20583 curState->value);
20584 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020585 }
20586 }
20587 curState = curState->next;
20588 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000020589 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020590 ret = ctxt->err;
20591 goto exit;
20592
20593fatal_exit:
20594 ret = -1;
20595
20596exit:
20597
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020598 if (defAttrStates != NULL)
20599 xmlSchemaFreeAttributeStates(defAttrStates);
20600
Daniel Veillard3646d642004-06-02 19:19:14 +000020601#ifdef DEBUG_ATTR_VALIDATION
20602 if (redundant)
20603 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020604 "xmlSchemaValidateAttributes: redundant call by "
20605 "type: %s\n", type->name);
Daniel Veillard3646d642004-06-02 19:19:14 +000020606#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020607 ctxt->nodeInfo = ctxt->elemInfos[ctxt->depth];
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020608 ctxt->node = oldnode;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020609 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000020610}
20611
20612/**
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020613 * xmlSchemaStartValidation:
Daniel Veillard4255d502002-04-16 15:50:10 +000020614 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000020615 *
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020616 * The starting point of the validation, called by
20617 * xmlSchemaValidateDocument and xmlSchemaValidateOneElement.
Daniel Veillard4255d502002-04-16 15:50:10 +000020618 *
20619 * Returns 0 if the element is schemas valid, a positive error code
20620 * number otherwise and -1 in case of internal or API error.
20621 */
20622static int
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020623xmlSchemaStartValidation(xmlSchemaValidCtxtPtr ctxt)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020624{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020625 xmlSchemaElementPtr elemDecl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020626 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000020627
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020628 ctxt->err = 0;
20629 ctxt->nberrors = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020630 if (ctxt->schema == NULL) {
20631 /*
20632 * No schema was specified at time of creation of the validation
20633 * context. Use xsi:schemaLocation and xsi:noNamespaceSchemaLocation
20634 * of the instance to build a schema.
20635 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020636 if (ctxt->pctxt == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020637 if (xmlSchemaCreatePCtxtOnVCtxt(ctxt) == -1)
20638 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020639 ctxt->schema = xmlSchemaNewSchema(ctxt->pctxt);
20640 if (ctxt->schema == NULL)
20641 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020642 ctxt->xsiAssemble = 1;
20643 } else
20644 ctxt->xsiAssemble = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020645 /*
20646 * Assemble new schemata using xsi.
Daniel Veillardc0826a72004-08-10 14:17:33 +000020647 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020648 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020649 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
20650 if (ret == -1) {
20651 xmlSchemaVCustomErr(ctxt,
20652 XML_SCHEMAV_INTERNAL,
20653 ctxt->node, NULL,
20654 "Internal error: xmlSchemaValidateElement, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020655 "assembling schema by xsi", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020656 }
20657 /*
20658 * NOTE: We won't react on schema parser errors here.
20659 * TODO: But a warning would be nice.
20660 */
20661 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020662 if (ret != -1) {
20663 if (ctxt->node->ns != NULL)
20664 elemDecl = xmlSchemaGetElem(ctxt->schema, ctxt->node->name,
20665 ctxt->node->ns->href);
20666 else
20667 elemDecl = xmlSchemaGetElem(ctxt->schema, ctxt->node->name, NULL);
20668
20669 if (elemDecl == NULL) {
20670 xmlSchemaVCustomErr(ctxt,
20671 XML_SCHEMAV_CVC_ELT_1,
20672 ctxt->node, NULL,
20673 "No matching global declaration available", NULL);
20674 ret = XML_SCHEMAV_CVC_ELT_1;
20675 } else {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020676 /*
20677 * Augment the IDC definitions.
20678 */
20679 if (ctxt->schema->idcDef != NULL) {
20680 xmlHashScan(ctxt->schema->idcDef,
20681 (xmlHashScanner) xmlSchemaAugmentIDC, ctxt);
20682 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020683 ctxt->depth = -1;
20684 xmlSchemaBeginElement(ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020685 ret = xmlSchemaValidateElementByDeclaration(ctxt, elemDecl);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020686 xmlSchemaEndElement(ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020687 if (ret < 0) {
20688 xmlSchemaVCustomErr(ctxt,
20689 XML_SCHEMAV_INTERNAL, ctxt->node, NULL,
20690 "Internal error: xmlSchemaValidateElement, "
20691 "calling validation by declaration", NULL);
20692 }
20693 }
20694 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020695
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020696 if (ctxt->xsiAssemble) {
20697 if (ctxt->schema != NULL) {
20698 xmlSchemaFree(ctxt->schema);
20699 ctxt->schema = NULL;
20700 }
Daniel Veillard4255d502002-04-16 15:50:10 +000020701 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020702 xmlSchemaClearValidCtxt(ctxt);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020703 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000020704}
20705
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020706
Daniel Veillard4255d502002-04-16 15:50:10 +000020707/**
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000020708 * xmlSchemaValidateOneElement:
20709 * @ctxt: a schema validation context
20710 * @elem: an element node
20711 *
20712 * Validate a branch of a tree, starting with the given @elem.
20713 *
20714 * Returns 0 if the element and its subtree is valid, a positive error
20715 * code number otherwise and -1 in case of an internal or API error.
20716 */
20717int
20718xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
20719{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020720 if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000020721 return (-1);
20722
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020723 if (ctxt->schema == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020724 xmlSchemaVErr(ctxt, NULL,
20725 XML_SCHEMAV_INTERNAL,
20726 "API error: xmlSchemaValidateOneElement, "
20727 "no schema specified.\n", NULL, NULL);
20728 return (-1);
20729 }
20730
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000020731 ctxt->doc = elem->doc;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020732 ctxt->node = elem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020733 ctxt->validationRoot = elem;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020734 return (xmlSchemaStartValidation(ctxt));
Daniel Veillard4255d502002-04-16 15:50:10 +000020735}
20736
20737/************************************************************************
20738 * *
20739 * SAX Validation code *
20740 * *
20741 ************************************************************************/
20742
20743/************************************************************************
20744 * *
20745 * Validation interfaces *
20746 * *
20747 ************************************************************************/
20748
20749/**
20750 * xmlSchemaNewValidCtxt:
20751 * @schema: a precompiled XML Schemas
20752 *
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020753 * Create an XML Schemas validation context based on the given schema.
Daniel Veillard4255d502002-04-16 15:50:10 +000020754 *
20755 * Returns the validation context or NULL in case of error
20756 */
20757xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020758xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
20759{
Daniel Veillard4255d502002-04-16 15:50:10 +000020760 xmlSchemaValidCtxtPtr ret;
20761
20762 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
20763 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020764 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000020765 return (NULL);
20766 }
20767 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
Daniel Veillardc0826a72004-08-10 14:17:33 +000020768 ret->schema = schema;
Daniel Veillard4255d502002-04-16 15:50:10 +000020769 return (ret);
20770}
20771
20772/**
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020773 * xmlSchemaClearValidCtxt:
20774 * @ctxt: the schema validation context
20775 *
20776 * Free the resources associated to the schema validation context;
20777 * leaves some fields alive intended for reuse of the context.
20778 */
20779static void
20780xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
20781{
20782 if (vctxt == NULL)
20783 return;
20784
20785 vctxt->validationRoot = NULL;
20786 if (vctxt->attr != NULL) {
20787 xmlSchemaFreeAttributeStates(vctxt->attr);
20788 vctxt->attr = NULL;
20789 }
20790 if (vctxt->value != NULL) {
20791 xmlSchemaFreeValue(vctxt->value);
20792 vctxt->value = NULL;
20793 }
20794 /*
20795 * Augmented IDC information.
20796 */
20797 if (vctxt->aidcs != NULL) {
20798 xmlSchemaIDCAugPtr cur = vctxt->aidcs, next;
20799 do {
20800 next = cur->next;
20801 xmlFree(cur);
20802 cur = next;
20803 } while (cur != NULL);
20804 vctxt->aidcs = NULL;
20805 }
20806 if (vctxt->idcNodes != NULL) {
20807 int i;
20808 xmlSchemaPSVIIDCNodePtr item;
20809
20810 for (i = 0; i < vctxt->nbIdcNodes; i++) {
20811 item = vctxt->idcNodes[i];
20812 xmlFree(item->keys);
20813 xmlFree(item);
20814 }
20815 xmlFree(vctxt->idcNodes);
20816 vctxt->idcNodes = NULL;
20817 }
20818 /*
20819 * Note that we won't delete the XPath state pool here.
20820 */
20821 if (vctxt->xpathStates != NULL) {
20822 xmlSchemaFreeIDCStateObjList(vctxt->xpathStates);
20823 vctxt->xpathStates = NULL;
20824 }
20825 if (vctxt->attrInfo != NULL) {
20826 if (vctxt->attrInfo->value != NULL) {
20827 xmlSchemaFreeValue(vctxt->attrInfo->value);
20828 }
20829 memset(vctxt->attrInfo, 0, sizeof(xmlSchemaNodeInfo));
20830 }
20831 if (vctxt->elemInfos != NULL) {
20832 int i;
20833 xmlSchemaNodeInfoPtr info;
20834
20835 for (i = 0; i < vctxt->sizeElemInfos; i++) {
20836 info = vctxt->elemInfos[i];
20837 if (info == NULL)
20838 break;
20839 if (info->value != NULL) {
20840 xmlSchemaFreeValue(info->value);
20841 info->value = NULL;
20842 }
20843 if (info->idcMatchers != NULL) {
20844 xmlSchemaIDCFreeMatcherList(info->idcMatchers);
20845 info->idcMatchers = NULL;
20846 }
20847 if (info->idcTable != NULL) {
20848 xmlSchemaIDCFreeIDCTable(info->idcTable);
20849 info->idcTable = NULL;
20850 }
20851 }
20852 }
20853}
20854
20855/**
Daniel Veillard4255d502002-04-16 15:50:10 +000020856 * xmlSchemaFreeValidCtxt:
20857 * @ctxt: the schema validation context
20858 *
20859 * Free the resources associated to the schema validation context
20860 */
20861void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020862xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
20863{
Daniel Veillard4255d502002-04-16 15:50:10 +000020864 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020865 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000020866 if (ctxt->attr != NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000020867 xmlSchemaFreeAttributeStates(ctxt->attr);
Daniel Veillard88c58912002-04-23 07:12:20 +000020868 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020869 xmlSchemaFreeValue(ctxt->value);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020870 if (ctxt->pctxt != NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020871 xmlSchemaFreeParserCtxt(ctxt->pctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020872 if (ctxt->idcNodes != NULL) {
20873 int i;
20874 xmlSchemaPSVIIDCNodePtr item;
20875
20876 for (i = 0; i < ctxt->nbIdcNodes; i++) {
20877 item = ctxt->idcNodes[i];
20878 xmlFree(item->keys);
20879 xmlFree(item);
20880 }
20881 xmlFree(ctxt->idcNodes);
20882 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020883 if (ctxt->idcKeys != NULL) {
20884 int i;
20885 for (i = 0; i < ctxt->nbIdcKeys; i++)
20886 xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
20887 xmlFree(ctxt->idcKeys);
20888 }
20889
20890 if (ctxt->xpathStates != NULL)
20891 xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
20892 if (ctxt->xpathStatePool != NULL)
20893 xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
20894
20895 /*
20896 * Augmented IDC information.
20897 */
20898 if (ctxt->aidcs != NULL) {
20899 xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
20900 do {
20901 next = cur->next;
20902 xmlFree(cur);
20903 cur = next;
20904 } while (cur != NULL);
20905 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020906 if (ctxt->attrInfo != NULL) {
20907 if (ctxt->attrInfo->value != NULL)
20908 xmlSchemaFreeValue(ctxt->attrInfo->value);
20909 xmlFree(ctxt->attrInfo);
20910 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020911 if (ctxt->elemInfos != NULL) {
20912 int i;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000020913 xmlSchemaNodeInfoPtr info;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020914
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020915 for (i = 0; i < ctxt->sizeElemInfos; i++) {
20916 info = ctxt->elemInfos[i];
20917 if (info == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020918 break;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020919 if (info->value != NULL)
20920 xmlSchemaFreeValue(info->value);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020921 if (info->idcMatchers != NULL)
20922 xmlSchemaIDCFreeMatcherList(info->idcMatchers);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020923 if (info->idcTable != NULL)
20924 xmlSchemaIDCFreeIDCTable(info->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020925 /*
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000020926 * TODO: Don't know if those will have to be freed if in streaming
20927 * mode.
20928 *
20929 * xmlFree(info->localName);
20930 * if (info->namespaceName != NULL)
20931 * xmlFree(info->namespaceName);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020932 */
20933 xmlFree(info);
20934 }
20935 xmlFree(ctxt->elemInfos);
20936 }
Daniel Veillard4255d502002-04-16 15:50:10 +000020937 xmlFree(ctxt);
20938}
20939
20940/**
20941 * xmlSchemaSetValidErrors:
20942 * @ctxt: a schema validation context
20943 * @err: the error function
20944 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +000020945 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +000020946 *
William M. Brack2f2a6632004-08-20 23:09:47 +000020947 * Set the error and warning callback informations
Daniel Veillard4255d502002-04-16 15:50:10 +000020948 */
20949void
20950xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020951 xmlSchemaValidityErrorFunc err,
20952 xmlSchemaValidityWarningFunc warn, void *ctx)
20953{
Daniel Veillard4255d502002-04-16 15:50:10 +000020954 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020955 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000020956 ctxt->error = err;
20957 ctxt->warning = warn;
20958 ctxt->userData = ctx;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020959 if (ctxt->pctxt != NULL)
20960 xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
Daniel Veillard4255d502002-04-16 15:50:10 +000020961}
20962
20963/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000020964 * xmlSchemaGetValidErrors:
20965 * @ctxt: a XML-Schema validation context
20966 * @err: the error function result
20967 * @warn: the warning function result
20968 * @ctx: the functions context result
20969 *
20970 * Get the error and warning callback informations
20971 *
20972 * Returns -1 in case of error and 0 otherwise
20973 */
20974int
20975xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
20976 xmlSchemaValidityErrorFunc * err,
20977 xmlSchemaValidityWarningFunc * warn, void **ctx)
20978{
20979 if (ctxt == NULL)
20980 return (-1);
20981 if (err != NULL)
20982 *err = ctxt->error;
20983 if (warn != NULL)
20984 *warn = ctxt->warning;
20985 if (ctx != NULL)
20986 *ctx = ctxt->userData;
20987 return (0);
20988}
20989
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020990
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020991/**
Daniel Veillard6927b102004-10-27 17:29:04 +000020992 * xmlSchemaSetValidOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020993 * @ctxt: a schema validation context
20994 * @options: a combination of xmlSchemaValidOption
20995 *
20996 * Sets the options to be used during the validation.
20997 *
20998 * Returns 0 in case of success, -1 in case of an
20999 * API error.
21000 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021001int
21002xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
21003 int options)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021004
21005{
21006 int i;
21007
21008 if (ctxt == NULL)
21009 return (-1);
21010 /*
21011 * WARNING: Change the start value if adding to the
21012 * xmlSchemaValidOption.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021013 * TODO: Is there an other, more easy to maintain,
21014 * way?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021015 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021016 for (i = 1; i < (int) sizeof(int) * 8; i++) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021017 if (options & 1<<i) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021018 xmlSchemaVErr(ctxt, NULL,
21019 XML_SCHEMAV_INTERNAL,
21020 "Internal error: xmlSchemaSetValidOptions, "
21021 "invalid option argument.\n", NULL, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021022 return (-1);
21023 }
21024 }
21025 ctxt->options = options;
21026 return (0);
21027}
21028
21029/**
Daniel Veillard6927b102004-10-27 17:29:04 +000021030 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021031 * @ctxt: a schema validation context
21032 *
William M. Brack21e4ef22005-01-02 09:53:13 +000021033 * Get the validation context options.
21034 *
21035 * Returns the option combination or -1 on error.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021036 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021037int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021038xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
21039
21040{
21041 if (ctxt == NULL)
21042 return (-1);
21043 else
21044 return (ctxt->options);
21045}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000021046
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000021047
Daniel Veillard259f0df2004-08-18 09:13:18 +000021048/**
Daniel Veillard4255d502002-04-16 15:50:10 +000021049 * xmlSchemaValidateDoc:
21050 * @ctxt: a schema validation context
21051 * @doc: a parsed document tree
21052 *
21053 * Validate a document tree in memory.
21054 *
21055 * Returns 0 if the document is schemas valid, a positive error code
21056 * number otherwise and -1 in case of internal or API error.
21057 */
21058int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021059xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
21060{
Daniel Veillard4255d502002-04-16 15:50:10 +000021061 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021062 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000021063
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000021064 ctxt->doc = doc;
21065 ctxt->node = xmlDocGetRootElement(doc);
21066 if (ctxt->node == NULL) {
21067 xmlSchemaVCustomErr(ctxt,
21068 XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
21069 (xmlNodePtr) doc, NULL,
21070 "The document has no document element", NULL);
21071 return (ctxt->err);
21072 }
21073 ctxt->validationRoot = ctxt->node;
21074 xmlSchemaStartValidation(ctxt);
21075
21076 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000021077}
21078
21079/**
21080 * xmlSchemaValidateStream:
21081 * @ctxt: a schema validation context
21082 * @input: the input to use for reading the data
21083 * @enc: an optional encoding information
21084 * @sax: a SAX handler for the resulting events
21085 * @user_data: the context to provide to the SAX handler.
21086 *
21087 * Validate a document tree in memory.
21088 *
21089 * Returns 0 if the document is schemas valid, a positive error code
21090 * number otherwise and -1 in case of internal or API error.
21091 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021092int
Daniel Veillard4255d502002-04-16 15:50:10 +000021093xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021094 xmlParserInputBufferPtr input, xmlCharEncoding enc,
21095 xmlSAXHandlerPtr sax, void *user_data)
21096{
Daniel Veillard4255d502002-04-16 15:50:10 +000021097 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021098 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000021099 ctxt->input = input;
21100 ctxt->enc = enc;
21101 ctxt->sax = sax;
21102 ctxt->user_data = user_data;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000021103 TODO return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000021104}
21105
21106#endif /* LIBXML_SCHEMAS_ENABLED */