blob: 7aa5cbebce9abb7c6007dd04e4d3b188b71ee666 [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
Daniel Veillardb0f397e2003-12-23 23:30:53 +000010/*
11 * 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
57/* #define IDC_ENABLED 1 */
58
59/* #define IDC_VALUE_SUPPORT 1 */
60
61/* #define IDC_XPATH_SUPPORT 1 */
62
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";
Daniel Veillardc0826a72004-08-10 14:17:33 +000095
Daniel Veillard4255d502002-04-16 15:50:10 +000096#define IS_SCHEMA(node, type) \
97 ((node != NULL) && (node->ns != NULL) && \
98 (xmlStrEqual(node->name, (const xmlChar *) type)) && \
99 (xmlStrEqual(node->ns->href, xmlSchemaNs)))
100
Daniel Veillardc0826a72004-08-10 14:17:33 +0000101#define FREE_AND_NULL(str) \
102 if (str != NULL) { \
103 xmlFree(str); \
104 str = NULL; \
105 }
106
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000107#define IS_ANYTYPE(item) \
108 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
109 (item->builtInType == XML_SCHEMAS_ANYTYPE))
110
111#define IS_COMPLEX_TYPE(item) \
112 ((item->type == XML_SCHEMA_TYPE_COMPLEX) || \
113 (item->builtInType == XML_SCHEMAS_ANYTYPE))
114
115#define IS_SIMPLE_TYPE(item) \
116 ((item->type == XML_SCHEMA_TYPE_SIMPLE) || \
117 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
118 (item->builtInType != XML_SCHEMAS_ANYTYPE)))
119
Daniel Veillardc0826a72004-08-10 14:17:33 +0000120#define XML_SCHEMAS_VAL_WTSP_PRESERVE 0
121#define XML_SCHEMAS_VAL_WTSP_REPLACE 1
122#define XML_SCHEMAS_VAL_WTSP_COLLAPSE 2
123
Daniel Veillard4255d502002-04-16 15:50:10 +0000124#define XML_SCHEMAS_PARSE_ERROR 1
125
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000126#define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT
127
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000128
129/*
130* XML_SCHEMA_VAL_XSI_ASSEMBLE_TNS_COMPOSE
131* allow to assemble schemata with
132* the same target namespace from
133* different sources; otherwise, the first
134* encountered schema with a specific target
135* namespace will be used only *
136
137*
138* XML_SCHEMA_VAL_LOCATE_BY_NSNAME = 1<<2
139* locate schemata to be imported
140* using the namespace name; otherwise
141* the location URI will be used */
142
143/*
144* xmlSchemaParserOption:
145*
146* This is the set of XML Schema parser options.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000147*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000148typedef enum {
149 XML_SCHEMA_PAR_LOCATE_BY_NSNAME = 1<<0
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000150 * locate schemata to be imported
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000151 * using the namespace name; otherwise
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000152 * the location URI will be used *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000153} xmlSchemaParserOption;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000154*/
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000155
156/*
157XMLPUBFUN int XMLCALL
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000158 xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
159 int options);
160XMLPUBFUN int XMLCALL
161 xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt);
162
163*/
164
165typedef struct _xmlSchemaAssemble xmlSchemaAssemble;
166typedef xmlSchemaAssemble *xmlSchemaAssemblePtr;
167struct _xmlSchemaAssemble {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000168 void **items; /* used for dynamic addition of schemata */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000169 int nbItems; /* used for dynamic addition of schemata */
170 int sizeItems; /* used for dynamic addition of schemata */
171};
172
Daniel Veillard4255d502002-04-16 15:50:10 +0000173struct _xmlSchemaParserCtxt {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000174 void *userData; /* user specific data block */
175 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
176 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillarde19fc232002-04-22 16:01:24 +0000177 xmlSchemaValidError err;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000178 int nberrors;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000179 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000180
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000181 xmlSchemaPtr topschema; /* The main schema */
182 xmlHashTablePtr namespaces; /* Hash table of namespaces to schemas */
183
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000184 xmlSchemaPtr schema; /* The schema in use */
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000185 const xmlChar *container; /* the current element, group, ... */
Daniel Veillard4255d502002-04-16 15:50:10 +0000186 int counter;
187
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000188 const xmlChar *URL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000189 xmlDocPtr doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +0000190 int preserve; /* Whether the doc should be freed */
Daniel Veillard4255d502002-04-16 15:50:10 +0000191
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000192 const char *buffer;
193 int size;
Daniel Veillard6045c902002-10-09 21:13:59 +0000194
Daniel Veillard4255d502002-04-16 15:50:10 +0000195 /*
196 * Used to build complex element content models
197 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000198 xmlAutomataPtr am;
Daniel Veillard4255d502002-04-16 15:50:10 +0000199 xmlAutomataStatePtr start;
200 xmlAutomataStatePtr end;
201 xmlAutomataStatePtr state;
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000202
203 xmlDictPtr dict; /* dictionnary for interned string names */
Daniel Veillardb0f397e2003-12-23 23:30:53 +0000204 int includes; /* the inclusion level, 0 for root or imports */
Daniel Veillard01fa6152004-06-29 17:04:39 +0000205 xmlSchemaTypePtr ctxtType; /* The current context simple/complex type */
206 xmlSchemaTypePtr parentItem; /* The current parent schema item */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000207 xmlSchemaAssemblePtr assemble;
208 int options;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000209 xmlSchemaValidCtxtPtr vctxt;
Daniel Veillard4255d502002-04-16 15:50:10 +0000210};
211
212
213#define XML_SCHEMAS_ATTR_UNKNOWN 1
214#define XML_SCHEMAS_ATTR_CHECKED 2
Daniel Veillard3646d642004-06-02 19:19:14 +0000215#define XML_SCHEMAS_ATTR_PROHIBITED 3
216#define XML_SCHEMAS_ATTR_MISSING 4
217#define XML_SCHEMAS_ATTR_INVALID_VALUE 5
218#define XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED 6
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000219#define XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE 7
220#define XML_SCHEMAS_ATTR_DEFAULT 8
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +0000221#define XML_SCHEMAS_ATTR_VALIDATE_VALUE 9
222#define XML_SCHEMAS_ATTR_WILD_NO_DECL 10
Daniel Veillard4255d502002-04-16 15:50:10 +0000223
224typedef struct _xmlSchemaAttrState xmlSchemaAttrState;
225typedef xmlSchemaAttrState *xmlSchemaAttrStatePtr;
226struct _xmlSchemaAttrState {
Daniel Veillard3646d642004-06-02 19:19:14 +0000227 xmlSchemaAttrStatePtr next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000228 xmlAttrPtr attr;
229 int state;
Daniel Veillard3646d642004-06-02 19:19:14 +0000230 xmlSchemaAttributePtr decl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000231 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000232};
233
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000234typedef struct _xmlSchemaBasicItem xmlSchemaBasicItem;
235typedef xmlSchemaBasicItem *xmlSchemaBasicItemPtr;
236struct _xmlSchemaBasicItem {
237 xmlSchemaTypeType type;
238 xmlSchemaAnnotPtr annot;
239};
240
241typedef struct _xmlSchemaItemQNRef xmlSchemaItemQNRef;
242typedef xmlSchemaItemQNRef *xmlSchemaItemQNRefPtr;
243struct _xmlSchemaItemQNRef {
244 xmlSchemaBasicItemPtr item;
245 const xmlChar *name;
246 const xmlChar *targetNamespace;
247};
248
249typedef struct _xmlSchemaIDC xmlSchemaIDC;
250typedef xmlSchemaIDC *xmlSchemaIDCPtr;
251
252/**
253 * xmlSchemaIDCSelect:
254 *
255 * The identity-constraint "field" and "selector" item, holding the
256 * XPath expression.
257 */
258typedef struct _xmlSchemaIDCSelect xmlSchemaIDCSelect;
259typedef xmlSchemaIDCSelect *xmlSchemaIDCSelectPtr;
260struct _xmlSchemaIDCSelect {
261 xmlSchemaIDCSelectPtr next;
262 xmlSchemaIDCPtr idc;
263 int index; /* an index position if significant for IDC key-sequences */
264 const xmlChar *xpath; /* the XPath expression */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000265 void *xpathComp; /* the compiled XPath expression */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000266};
267
268/**
269 * xmlSchemaIDC:
270 *
271 * The identity-constraint definition component.
272 */
273
274struct _xmlSchemaIDC {
275 xmlSchemaTypeType type;
276 xmlSchemaAnnotPtr annot;
277 xmlSchemaIDCPtr next;
278 xmlNodePtr node;
279 const xmlChar *name;
280 const xmlChar *targetNamespace;
281 xmlSchemaIDCSelectPtr selector;
282 xmlSchemaIDCSelectPtr fields;
283 int nbFields;
284 xmlSchemaItemQNRefPtr ref;
285};
286
287/**
288 * xmlSchemaIDCAug:
289 *
290 * The augmented IDC information used for validation.
291 */
292typedef struct _xmlSchemaIDCAug xmlSchemaIDCAug;
293typedef xmlSchemaIDCAug *xmlSchemaIDCAugPtr;
294struct _xmlSchemaIDCAug {
295 xmlSchemaIDCAugPtr next; /* next in a list */
296 xmlSchemaIDCPtr def; /* the IDC definition */
297 int bubbleDepth; /* the lowest level to which IDC
298 tables need to be bubbled upwards */
299};
300
301/**
302 * xmlSchemaPSVIIDCKeySequence:
303 *
304 * The key sequence of a node table item.
305 */
306typedef struct _xmlSchemaPSVIIDCKey xmlSchemaPSVIIDCKey;
307typedef xmlSchemaPSVIIDCKey *xmlSchemaPSVIIDCKeyPtr;
308struct _xmlSchemaPSVIIDCKey {
309 xmlSchemaTypePtr type;
310 xmlSchemaValPtr compValue;
311};
312
313/**
314 * xmlSchemaPSVIIDCNode:
315 *
316 * The node table item of a node table.
317 */
318typedef struct _xmlSchemaPSVIIDCNode xmlSchemaPSVIIDCNode;
319typedef xmlSchemaPSVIIDCNode *xmlSchemaPSVIIDCNodePtr;
320struct _xmlSchemaPSVIIDCNode {
321 xmlNodePtr node;
322 xmlSchemaPSVIIDCKeyPtr *keys;
323};
324
325/**
326 * xmlSchemaPSVIIDCBinding:
327 *
328 * The identity-constraint binding item of the [identity-constraint table].
329 */
330typedef struct _xmlSchemaPSVIIDCBinding xmlSchemaPSVIIDCBinding;
331typedef xmlSchemaPSVIIDCBinding *xmlSchemaPSVIIDCBindingPtr;
332struct _xmlSchemaPSVIIDCBinding {
333 xmlSchemaPSVIIDCBindingPtr next; /* next binding of a specific node */
334 xmlSchemaIDCPtr definition; /* the IDC definition */
335 xmlSchemaPSVIIDCNodePtr *nodeTable; /* array of key-sequences */
336 int nbNodes; /* number of entries in the node table */
337 int sizeNodes; /* size of the node table */
338 int nbDupls; /* number of already identified duplicates in the node
339 table */
340 /* int nbKeys; number of keys in each key-sequence */
341};
342
343#define XPATH_STATE_OBJ_TYPE_IDC_SELECTOR 1
344#define XPATH_STATE_OBJ_TYPE_IDC_FIELD 2
345
346#define XPATH_STATE_OBJ_MATCHES -2
347#define XPATH_STATE_OBJ_BLOCKED -3
348
349typedef struct _xmlSchemaIDCMatcher xmlSchemaIDCMatcher;
350typedef xmlSchemaIDCMatcher *xmlSchemaIDCMatcherPtr;
351
352/**
353 * xmlSchemaIDCStateObj:
354 *
355 * The state object used to evaluate XPath expressions.
356 */
357typedef struct _xmlSchemaIDCStateObj xmlSchemaIDCStateObj;
358typedef xmlSchemaIDCStateObj *xmlSchemaIDCStateObjPtr;
359struct _xmlSchemaIDCStateObj {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000360 int type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000361 xmlSchemaIDCStateObjPtr next; /* next if in a list */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000362 int depth; /* depth of creation */
363 int *history; /* list of (depth, state-id) tuples */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000364 int nbHistory;
365 int sizeHistory;
366 xmlSchemaIDCMatcherPtr matcher; /* the correspondent field/selector
367 matcher */
368 xmlSchemaIDCSelectPtr sel;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000369 void *xpathCtxt;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000370};
371
372#define IDC_MATCHER 0
373
374/**
375 * xmlSchemaIDCMatcher:
376 *
377 * Used to IDC selectors (and fields) successively.
378 */
379struct _xmlSchemaIDCMatcher {
380 int type;
381 int depth; /* the tree depth at creation time */
382 xmlSchemaIDCMatcherPtr next; /* next in the list */
383 xmlSchemaIDCAugPtr aidc; /* the augmented IDC item */
384 xmlSchemaPSVIIDCKeyPtr **keySeqs; /* the key-sequences of the target
385 elements */
386 int sizeKeySeqs;
387 xmlSchemaPSVIIDCKeyPtr **refKeySeqs;
388 int nbRefKeySeqs;
389 int sizeRefKeySeqs;
390 int targetDepth;
391};
392
393/*
394* Element info flags.
395*/
396#define XML_SCHEMA_ELEM_INFO_VALUE_NEEDED 1<<0
397
398/**
399 * xmlSchemaElemInfo:
400 *
401 * Holds information of an element node.
402 */
403typedef struct _xmlSchemaElemInfo xmlSchemaElemInfo;
404typedef xmlSchemaElemInfo *xmlSchemaElemInfoPtr;
405struct _xmlSchemaElemInfo {
406 int depth;
407 int flags; /* combination of element info flags */
408 xmlNodePtr node;
409 const xmlChar *localName;
410 const xmlChar *namespaceName;
411 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +0000412 xmlSchemaTypePtr decl; /* the element/attribute declaration */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000413 xmlSchemaValPtr value; /* the pre-computed value if any */
414 xmlSchemaPSVIIDCBindingPtr idcTable; /* the table of PSVI IDC bindings
415 for the scope element*/
416 xmlSchemaIDCMatcherPtr idcMatchers; /* the IDC matchers for the scope
417 element */
418};
419
Daniel Veillard4255d502002-04-16 15:50:10 +0000420/**
421 * xmlSchemaValidCtxt:
422 *
423 * A Schemas validation context
424 */
425
426struct _xmlSchemaValidCtxt {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000427 void *userData; /* user specific data block */
428 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000429 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000430 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000431
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000432 xmlSchemaPtr schema; /* The schema in use */
433 xmlDocPtr doc;
Daniel Veillard4255d502002-04-16 15:50:10 +0000434 xmlParserInputBufferPtr input;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000435 xmlCharEncoding enc;
436 xmlSAXHandlerPtr sax;
437 void *user_data;
Daniel Veillard4255d502002-04-16 15:50:10 +0000438
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000439 xmlDocPtr myDoc;
440 int err;
441 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +0000442
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000443 xmlNodePtr node;
444 xmlNodePtr cur;
445 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +0000446
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000447 xmlRegExecCtxtPtr regexp;
448 xmlSchemaValPtr value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000449
Daniel Veillard3646d642004-06-02 19:19:14 +0000450 xmlSchemaAttrStatePtr attrTop;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000451 xmlSchemaAttrStatePtr attr;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000452 /* xmlNodePtr scope; not used */
Daniel Veillardc0826a72004-08-10 14:17:33 +0000453 int valueWS;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000454 int options;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000455 xmlNodePtr validationRoot;
456 xmlSchemaParserCtxtPtr pctxt;
457 int xsiAssemble;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000458#ifdef ELEM_INFO_ENABLED
459 int depth;
460 xmlSchemaElemInfoPtr *elemInfos; /* array of element informations */
461 int sizeElemInfos;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +0000462 xmlSchemaElemInfoPtr nodeInfo; /* the current element information */
463 xmlSchemaElemInfoPtr attrInfo; /* node infor for the current attribute */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000464#endif
465#ifdef IDC_ENABLED
466 xmlSchemaIDCAugPtr aidcs; /* a list of augmented IDC informations */
467
468 xmlSchemaIDCStateObjPtr xpathStates; /* first active state object. */
469 xmlSchemaIDCStateObjPtr xpathStatePool; /* first stored state object. */
470
471 xmlSchemaPSVIIDCNodePtr *idcNodes; /* list of all IDC node-table entries*/
472 int nbIdcNodes;
473 int sizeIdcNodes;
474
475 xmlSchemaPSVIIDCKeyPtr *idcKeys; /* list of all IDC node-table entries */
476 int nbIdcKeys;
477 int sizeIdcKeys;
478#endif
Daniel Veillard4255d502002-04-16 15:50:10 +0000479};
480
Daniel Veillard1d913862003-11-21 00:28:39 +0000481/*
482 * These are the entries in the schemas importSchemas hash table
483 */
484typedef struct _xmlSchemaImport xmlSchemaImport;
485typedef xmlSchemaImport *xmlSchemaImportPtr;
486struct _xmlSchemaImport {
487 const xmlChar *schemaLocation;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000488 xmlSchemaPtr schema; /* not used any more */
William M. Brack2f2a6632004-08-20 23:09:47 +0000489 xmlDocPtr doc;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000490 int isMain;
Daniel Veillard1d913862003-11-21 00:28:39 +0000491};
Daniel Veillard4255d502002-04-16 15:50:10 +0000492
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000493/*
494 * These are the entries associated to includes in a schemas
495 */
496typedef struct _xmlSchemaInclude xmlSchemaInclude;
497typedef xmlSchemaInclude *xmlSchemaIncludePtr;
498struct _xmlSchemaInclude {
499 xmlSchemaIncludePtr next;
500
501 const xmlChar *schemaLocation;
502 xmlDocPtr doc;
503};
504
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000505typedef struct _xmlSchemaParticle xmlSchemaParticle;
506typedef xmlSchemaParticle *xmlSchemaParticlePtr;
507struct _xmlSchemaParticle {
508 xmlSchemaTypeType type;
509 xmlSchemaParticlePtr next; /* the next particle if in a list */
510 int minOccurs;
511 int maxOccurs;
512 xmlSchemaTypePtr term;
513};
514
515
516typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup;
517typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr;
518struct _xmlSchemaModelGroup {
519 xmlSchemaTypeType type;
520 int compositor; /* one of all, choice or sequence */
521 xmlSchemaParticlePtr particles; /* list of particles */
522 xmlSchemaAnnotPtr annot;
523};
524
525typedef struct _xmlSchemaModelGroupDef xmlSchemaModelGroupDef;
526typedef xmlSchemaModelGroupDef *xmlSchemaModelGroupDefPtr;
527struct _xmlSchemaModelGroupDef {
528 xmlSchemaTypeType type;
529 const xmlChar *name;
530 const xmlChar *targetNamespace;
531 xmlSchemaModelGroupPtr modelGroup;
532 xmlSchemaAnnotPtr annot;
533};
534
Daniel Veillard4255d502002-04-16 15:50:10 +0000535/************************************************************************
536 * *
537 * Some predeclarations *
538 * *
539 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000540
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000541static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
542 xmlSchemaPtr schema,
543 xmlNodePtr node);
Daniel Veillard01fa6152004-06-29 17:04:39 +0000544static void
545xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
546 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name);
547static const char *
548xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
549static int
550xmlSchemaValidateSimpleTypeValue(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000551 xmlSchemaTypePtr type,
Daniel Veillard01fa6152004-06-29 17:04:39 +0000552 const xmlChar *value,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000553 int fireErrors,
Daniel Veillardc0826a72004-08-10 14:17:33 +0000554 int applyFacets,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000555 int normalize,
556 int checkNodes);
557static int
558xmlSchemaValidateElementByDeclaration(xmlSchemaValidCtxtPtr ctxt,
559 xmlSchemaElementPtr elemDecl);
560static int
561xmlSchemaValidateElementByWildcard(xmlSchemaValidCtxtPtr ctxt,
562 xmlSchemaTypePtr type);
563static int
564xmlSchemaHasElemOrCharContent(xmlNodePtr node);
William M. Brack2f2a6632004-08-20 23:09:47 +0000565static int
566xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
567 xmlNodePtr node);
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +0000568static void
569xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
570 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name);
William M. Brack87640d52004-04-17 14:58:15 +0000571
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000572/************************************************************************
573 * *
574 * Datatype error handlers *
575 * *
576 ************************************************************************/
577
578/**
579 * xmlSchemaPErrMemory:
580 * @node: a context node
581 * @extra: extra informations
582 *
583 * Handle an out of memory condition
584 */
585static void
586xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
587 const char *extra, xmlNodePtr node)
588{
589 if (ctxt != NULL)
590 ctxt->nberrors++;
591 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
592 extra);
593}
594
595/**
596 * xmlSchemaPErr:
597 * @ctxt: the parsing context
598 * @node: the context node
599 * @error: the error code
600 * @msg: the error message
601 * @str1: extra data
602 * @str2: extra data
603 *
604 * Handle a parser error
605 */
606static void
607xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
608 const char *msg, const xmlChar * str1, const xmlChar * str2)
609{
610 xmlGenericErrorFunc channel = NULL;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000611 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000612 void *data = NULL;
613
614 if (ctxt != NULL) {
615 ctxt->nberrors++;
616 channel = ctxt->error;
617 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000618 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000619 }
Daniel Veillard659e71e2003-10-10 14:10:40 +0000620 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000621 error, XML_ERR_ERROR, NULL, 0,
622 (const char *) str1, (const char *) str2, NULL, 0, 0,
623 msg, str1, str2);
624}
625
626/**
627 * xmlSchemaPErr2:
628 * @ctxt: the parsing context
629 * @node: the context node
630 * @node: the current child
631 * @error: the error code
632 * @msg: the error message
633 * @str1: extra data
634 * @str2: extra data
635 *
636 * Handle a parser error
637 */
638static void
639xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
640 xmlNodePtr child, int error,
641 const char *msg, const xmlChar * str1, const xmlChar * str2)
642{
643 if (child != NULL)
644 xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
645 else
646 xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
647}
648
Daniel Veillard01fa6152004-06-29 17:04:39 +0000649
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000650/**
Daniel Veillard3646d642004-06-02 19:19:14 +0000651 * xmlSchemaPErrExt:
652 * @ctxt: the parsing context
653 * @node: the context node
654 * @error: the error code
655 * @strData1: extra data
656 * @strData2: extra data
657 * @strData3: extra data
658 * @msg: the message
659 * @str1: extra parameter for the message display
660 * @str2: extra parameter for the message display
661 * @str3: extra parameter for the message display
662 * @str4: extra parameter for the message display
663 * @str5: extra parameter for the message display
664 *
665 * Handle a parser error
666 */
667static void
668xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
669 const xmlChar * strData1, const xmlChar * strData2,
670 const xmlChar * strData3, const char *msg, const xmlChar * str1,
671 const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
672 const xmlChar * str5)
673{
674
675 xmlGenericErrorFunc channel = NULL;
676 xmlStructuredErrorFunc schannel = NULL;
677 void *data = NULL;
678
679 if (ctxt != NULL) {
680 ctxt->nberrors++;
681 channel = ctxt->error;
682 data = ctxt->userData;
683 schannel = ctxt->serror;
684 }
685 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
686 error, XML_ERR_ERROR, NULL, 0,
687 (const char *) strData1, (const char *) strData2,
William M. Brack803812b2004-06-03 02:11:24 +0000688 (const char *) strData3, 0, 0, msg, str1, str2,
689 str3, str4, str5);
Daniel Veillard3646d642004-06-02 19:19:14 +0000690}
Daniel Veillard01fa6152004-06-29 17:04:39 +0000691
Daniel Veillard3646d642004-06-02 19:19:14 +0000692
693/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000694 * xmlSchemaVTypeErrMemory:
695 * @node: a context node
696 * @extra: extra informations
697 *
698 * Handle an out of memory condition
699 */
700static void
701xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
702 const char *extra, xmlNodePtr node)
703{
704 if (ctxt != NULL) {
705 ctxt->nberrors++;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000706 ctxt->err = XML_SCHEMAV_INTERNAL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000707 }
708 __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
709 extra);
710}
711
712/**
713 * xmlSchemaVErr3:
714 * @ctxt: the validation context
715 * @node: the context node
716 * @error: the error code
717 * @msg: the error message
718 * @str1: extra data
719 * @str2: extra data
720 * @str3: extra data
721 *
722 * Handle a validation error
723 */
724static void
725xmlSchemaVErr3(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
726 const char *msg, const xmlChar *str1, const xmlChar *str2,
727 const xmlChar *str3)
728{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000729 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000730 xmlGenericErrorFunc channel = NULL;
731 void *data = NULL;
732
733 if (ctxt != NULL) {
734 ctxt->nberrors++;
735 ctxt->err = error;
736 channel = ctxt->error;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000737 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000738 data = ctxt->userData;
739 }
740 /* reajust to global error numbers */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000741 /* Removed, since the old schema error codes have been
742 * substituted for the global error codes.
743 *
744 * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
745 */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000746 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000747 error, XML_ERR_ERROR, NULL, 0,
748 (const char *) str1, (const char *) str2,
749 (const char *) str3, 0, 0,
750 msg, str1, str2, str3);
751}
Daniel Veillardc0826a72004-08-10 14:17:33 +0000752
753/**
754 * xmlSchemaVErrExt:
755 * @ctxt: the validation context
756 * @node: the context node
757 * @error: the error code
758 * @msg: the message
759 * @str1: extra parameter for the message display
760 * @str2: extra parameter for the message display
761 * @str3: extra parameter for the message display
762 * @str4: extra parameter for the message display
763 * @str5: extra parameter for the message display
764 *
765 * Handle a validation error
766 */
767static void
768xmlSchemaVErrExt(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
769 const char *msg, const xmlChar * str1,
770 const xmlChar * str2, const xmlChar * str3,
771 const xmlChar * str4, const xmlChar * str5)
772{
773 xmlStructuredErrorFunc schannel = NULL;
774 xmlGenericErrorFunc channel = NULL;
775 void *data = NULL;
776
777 if (ctxt != NULL) {
778 ctxt->nberrors++;
779 ctxt->err = error;
780 channel = ctxt->error;
781 schannel = ctxt->serror;
782 data = ctxt->userData;
783 }
784 /* reajust to global error numbers */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000785 /* Removed, since the old schema error codes have been
786 * substituted for the global error codes.
787 *
788 * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
789 */
Daniel Veillardc0826a72004-08-10 14:17:33 +0000790 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
791 error, XML_ERR_ERROR, NULL, 0, NULL, NULL, NULL, 0, 0,
792 msg, str1, str2, str3, str4, str5);
793}
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000794/**
795 * xmlSchemaVErr:
796 * @ctxt: the validation context
797 * @node: the context node
798 * @error: the error code
799 * @msg: the error message
800 * @str1: extra data
801 * @str2: extra data
802 *
803 * Handle a validation error
804 */
805static void
806xmlSchemaVErr(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
807 const char *msg, const xmlChar * str1, const xmlChar * str2)
808{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000809 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000810 xmlGenericErrorFunc channel = NULL;
811 void *data = NULL;
812
813 if (ctxt != NULL) {
814 ctxt->nberrors++;
815 ctxt->err = error;
816 channel = ctxt->error;
817 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000818 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000819 }
820 /* reajust to global error numbers */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000821 /* Removed, since the old schema error codes have been
822 * substituted for the global error codes.
823 *
824 * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
825 */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000826 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000827 error, XML_ERR_ERROR, NULL, 0,
828 (const char *) str1, (const char *) str2, NULL, 0, 0,
829 msg, str1, str2);
830}
Daniel Veillard4255d502002-04-16 15:50:10 +0000831
Daniel Veillardc0826a72004-08-10 14:17:33 +0000832/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000833 * xmlSchemaGetAttrName:
Daniel Veillardc0826a72004-08-10 14:17:33 +0000834 * @attr: the attribute declaration/use
835 *
836 * Returns the name of the attribute; if the attribute
837 * is a reference, the name of the referenced global type will be returned.
838 */
839static const xmlChar *
840xmlSchemaGetAttrName(xmlSchemaAttributePtr attr)
841{
842 if (attr->ref != NULL)
843 return(attr->ref);
844 else
845 return(attr->name);
846}
847
848/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000849 * xmlSchemaGetAttrTargetNsURI:
Daniel Veillardc0826a72004-08-10 14:17:33 +0000850 * @type: the type (element or attribute)
851 *
852 * Returns the target namespace URI of the type; if the type is a reference,
853 * the target namespace of the referenced type will be returned.
854 */
855static const xmlChar *
856xmlSchemaGetAttrTargetNsURI(xmlSchemaAttributePtr attr)
857{
858 if (attr->ref != NULL)
859 return (attr->refNs);
860 else
861 return(attr->targetNamespace);
862}
863
864/**
865 * xmlSchemaFormatNsUriLocal:
866 * @buf: the string buffer
867 * @uri: the namespace URI
868 * @local: the local name
869 *
870 * Returns a representation of the given URI used
871 * for error reports.
872 *
873 * Returns an empty string, if @ns is NULL, a formatted
874 * string otherwise.
875 */
876static const xmlChar*
877xmlSchemaFormatNsUriLocal(xmlChar **buf,
878 const xmlChar *uri, const xmlChar *local)
879{
880 if (*buf != NULL)
881 xmlFree(*buf);
882 if (uri == NULL) {
883 *buf = xmlStrdup(BAD_CAST "{'");
884 *buf = xmlStrcat(*buf, local);
885 } else {
886 *buf = xmlStrdup(BAD_CAST "{'");
887 *buf = xmlStrcat(*buf, uri);
888 *buf = xmlStrcat(*buf, BAD_CAST "', '");
889 *buf = xmlStrcat(*buf, local);
890 }
891 *buf = xmlStrcat(*buf, BAD_CAST "'}");
892 return ((const xmlChar *) *buf);
893}
894
895/**
896 * xmlSchemaFormatNsPrefixLocal:
897 * @buf: the string buffer
898 * @ns: the namespace
899 * @local: the local name
900 *
901 * Returns a representation of the given URI used
902 * for error reports.
903 *
904 * Returns an empty string, if @ns is NULL, a formatted
905 * string otherwise.
906 */
907static const xmlChar*
908xmlSchemaFormatNsPrefixLocal(xmlChar **buf,
909 xmlNsPtr ns, const xmlChar *local)
910{
911 if (*buf != NULL) {
912 xmlFree(*buf);
913 *buf = NULL;
914 }
915 if ((ns == NULL) || (ns->prefix == NULL))
916 return(local);
917 else {
918 *buf = xmlStrdup(ns->prefix);
919 *buf = xmlStrcat(*buf, BAD_CAST ":");
920 *buf = xmlStrcat(*buf, local);
921 }
922 return ((const xmlChar *) *buf);
923}
924
925/**
926 * xmlSchemaFormatItemForReport:
927 * @buf: the string buffer
928 * @itemDes: the designation of the item
929 * @itemName: the name of the item
930 * @item: the item as an object
931 * @itemNode: the node of the item
932 * @local: the local name
933 * @parsing: if the function is used during the parse
934 *
935 * Returns a representation of the given item used
936 * for error reports.
937 *
938 * The following order is used to build the resulting
939 * designation if the arguments are not NULL:
940 * 1a. If itemDes not NULL -> itemDes
941 * 1b. If (itemDes not NULL) and (itemName not NULL)
942 * -> itemDes + itemName
943 * 2. If the preceding was NULL and (item not NULL) -> item
944 * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
945 *
946 * If the itemNode is an attribute node, the name of the attribute
947 * will be appended to the result.
948 *
949 * Returns the formatted string and sets @buf to the resulting value.
950 */
951static xmlChar*
952xmlSchemaFormatItemForReport(xmlChar **buf,
953 const xmlChar *itemDes,
954 xmlSchemaTypePtr item,
955 xmlNodePtr itemNode,
956 int parsing)
957{
958 xmlChar *str = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +0000959 int named = 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +0000960
961 if (*buf != NULL) {
962 xmlFree(*buf);
963 *buf = NULL;
964 }
965
William M. Brack2f2a6632004-08-20 23:09:47 +0000966 if (itemDes != NULL) {
967 *buf = xmlStrdup(itemDes);
968 } else if (item != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000969 switch (item->type) {
970 case XML_SCHEMA_TYPE_BASIC:
Daniel Veillardc0826a72004-08-10 14:17:33 +0000971 if (item->builtInType == XML_SCHEMAS_ANYTYPE)
972 *buf = xmlStrdup(BAD_CAST "'anyType'");
973 else if (item->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)
974 *buf = xmlStrdup(BAD_CAST "'anySimpleType'");
975 else {
976 /* *buf = xmlStrdup(BAD_CAST "bi "); */
977 /* *buf = xmlStrcat(*buf, xmlSchemaElemDesST); */
978 *buf = xmlStrdup(BAD_CAST "'");
979 *buf = xmlStrcat(*buf, item->name);
980 *buf = xmlStrcat(*buf, BAD_CAST "'");
981 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000982 break;
983 case XML_SCHEMA_TYPE_SIMPLE:
Daniel Veillardc0826a72004-08-10 14:17:33 +0000984 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
985 *buf = xmlStrdup(xmlSchemaElemDesST);
986 *buf = xmlStrcat(*buf, BAD_CAST " '");
987 *buf = xmlStrcat(*buf, item->name);
988 *buf = xmlStrcat(*buf, BAD_CAST "'");
989 } else {
990 *buf = xmlStrdup(xmlSchemaElemDesST);
Daniel Veillardc0826a72004-08-10 14:17:33 +0000991 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000992 break;
993 case XML_SCHEMA_TYPE_COMPLEX:
Daniel Veillardc0826a72004-08-10 14:17:33 +0000994 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
995 *buf = xmlStrdup(xmlSchemaElemDesCT);
996 *buf = xmlStrcat(*buf, BAD_CAST " '");
997 *buf = xmlStrcat(*buf, item->name);
998 *buf = xmlStrcat(*buf, BAD_CAST "'");
999 } else {
1000 *buf = xmlStrdup(xmlSchemaElemDesCT);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001001 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001002 break;
1003 case XML_SCHEMA_TYPE_ATTRIBUTE: {
1004 xmlSchemaAttributePtr attr;
1005
1006 attr = (xmlSchemaAttributePtr) item;
1007 if ((attr->flags & XML_SCHEMAS_TYPE_GLOBAL) ||
1008 (attr->ref == NULL)) {
1009 *buf = xmlStrdup(xmlSchemaElemDesAttrDecl);
1010 *buf = xmlStrcat(*buf, BAD_CAST " '");
1011 *buf = xmlStrcat(*buf, attr->name);
1012 *buf = xmlStrcat(*buf, BAD_CAST "'");
1013 } else {
1014 *buf = xmlStrdup(xmlSchemaElemDesAttrRef);
1015 *buf = xmlStrcat(*buf, BAD_CAST " '");
1016 *buf = xmlStrcat(*buf, attr->refPrefix);
1017 *buf = xmlStrcat(*buf, BAD_CAST ":");
1018 *buf = xmlStrcat(*buf, attr->ref);
1019 *buf = xmlStrcat(*buf, BAD_CAST "'");
1020 }
1021 }
1022 break;
1023 case XML_SCHEMA_TYPE_ELEMENT: {
1024 xmlSchemaElementPtr elem;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001025
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001026 elem = (xmlSchemaElementPtr) item;
1027 if ((elem->flags & XML_SCHEMAS_TYPE_GLOBAL) ||
1028 (elem->ref == NULL)) {
1029 *buf = xmlStrdup(xmlSchemaElemDesElemDecl);
1030 *buf = xmlStrcat(*buf, BAD_CAST " '");
1031 *buf = xmlStrcat(*buf, elem->name);
1032 *buf = xmlStrcat(*buf, BAD_CAST "'");
1033 } else {
1034 *buf = xmlStrdup(xmlSchemaElemDesElemRef);
1035 *buf = xmlStrcat(*buf, BAD_CAST " '");
1036 *buf = xmlStrcat(*buf, elem->refPrefix);
1037 *buf = xmlStrcat(*buf, BAD_CAST ":");
1038 *buf = xmlStrcat(*buf, elem->ref);
1039 *buf = xmlStrcat(*buf, BAD_CAST "'");
1040 }
1041 }
1042 break;
1043 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1044 case XML_SCHEMA_TYPE_IDC_KEY:
1045 case XML_SCHEMA_TYPE_IDC_KEYREF:
1046 if (item->type == XML_SCHEMA_TYPE_IDC_UNIQUE)
1047 *buf = xmlStrdup(BAD_CAST "unique '");
1048 else if (item->type == XML_SCHEMA_TYPE_IDC_KEY)
1049 *buf = xmlStrdup(BAD_CAST "key '");
1050 else
1051 *buf = xmlStrdup(BAD_CAST "keyRef '");
1052 *buf = xmlStrcat(*buf, ((xmlSchemaIDCPtr) item)->name);
1053 *buf = xmlStrcat(*buf, BAD_CAST "'");
1054 break;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00001055 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1056 TODO
1057 break;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001058 default:
William M. Brack2f2a6632004-08-20 23:09:47 +00001059 named = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001060 }
William M. Brack2f2a6632004-08-20 23:09:47 +00001061 } else
1062 named = 0;
1063
1064 if ((named == 0) && (itemNode != NULL)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00001065 xmlNodePtr elem;
1066
1067 if (itemNode->type == XML_ATTRIBUTE_NODE)
1068 elem = itemNode->parent;
1069 else
1070 elem = itemNode;
1071 *buf = xmlStrdup(BAD_CAST "Element '");
1072 if (parsing)
1073 *buf = xmlStrcat(*buf, elem->name);
1074 else
1075 *buf = xmlStrcat(*buf,
1076 xmlSchemaFormatNsPrefixLocal(&str, elem->ns, elem->name));
1077 *buf = xmlStrcat(*buf, BAD_CAST "'");
1078 }
1079 if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
1080 *buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
1081 *buf = xmlStrcat(*buf, xmlSchemaFormatNsPrefixLocal(&str,
1082 itemNode->ns, itemNode->name));
1083 *buf = xmlStrcat(*buf, BAD_CAST "'");
1084 }
1085 FREE_AND_NULL(str);
1086
1087 return (*buf);
1088}
1089
1090/**
1091 * xmlSchemaPFormatItemDes:
1092 * @buf: the string buffer
1093 * @item: the item as a schema object
1094 * @itemNode: the item as a node
1095 *
1096 * If the pointer to @buf is not NULL and @but holds no value,
1097 * the value is set to a item designation using
1098 * xmlSchemaFormatItemForReport. This one avoids adding
1099 * an attribute designation postfix.
1100 *
1101 * Returns a string of all enumeration elements.
1102 */
1103static void
1104xmlSchemaPRequestItemDes(xmlChar **buf,
1105 xmlSchemaTypePtr item,
1106 xmlNodePtr itemNode)
1107{
1108 if ((buf == 0) || (*buf != NULL))
1109 return;
1110 if (itemNode->type == XML_ATTRIBUTE_NODE)
1111 itemNode = itemNode->parent;
1112 xmlSchemaFormatItemForReport(buf, NULL, item, itemNode, 1);
1113}
1114
1115/**
1116 * xmlSchemaFormatFacetEnumSet:
1117 * @buf: the string buffer
1118 * @type: the type holding the enumeration facets
1119 *
1120 * Builds a string consisting of all enumeration elements.
1121 *
1122 * Returns a string of all enumeration elements.
1123 */
1124static const xmlChar *
1125xmlSchemaFormatFacetEnumSet(xmlChar **buf, xmlSchemaTypePtr type)
1126{
1127 xmlSchemaFacetLinkPtr link;
1128
1129 if (*buf != NULL)
1130 xmlFree(*buf);
1131 *buf = NULL;
1132 for (link = type->facetSet; link != NULL; link = link->next) {
1133 if (link->facet->type == XML_SCHEMA_FACET_ENUMERATION) {
1134 if (*buf == NULL) {
1135 *buf = xmlStrdup(BAD_CAST "'");
1136 *buf = xmlStrcat(*buf, link->facet->value);
1137 *buf = xmlStrcat(*buf, BAD_CAST "'");
1138 } else {
1139 *buf = xmlStrcat(*buf, BAD_CAST ", '");
1140 *buf = xmlStrcat(*buf, link->facet->value);
1141 *buf = xmlStrcat(*buf, BAD_CAST "'");
1142 }
1143 }
1144 }
1145 return ((const xmlChar *) *buf);
1146}
1147
1148/**
1149 * xmlSchemaVFacetErr:
1150 * @ctxt: the schema validation context
1151 * @error: the error code
1152 * @node: the node to be validated
1153 * @value: the value of the node
1154 * @type: the type holding the facet
1155 * @facet: the facet
1156 * @message: the error message of NULL
1157 * @str1: extra data
1158 * @str2: extra data
1159 * @str3: extra data
1160 *
1161 * Reports a facet validation error.
1162 * TODO: Should this report the value of an element as well?
1163 */
1164static void
1165xmlSchemaVFacetErr(xmlSchemaValidCtxtPtr ctxt,
1166 xmlParserErrors error,
1167 xmlNodePtr node,
1168 const xmlChar *value,
1169 unsigned long length,
1170 xmlSchemaTypePtr type,
1171 xmlSchemaFacetPtr facet,
1172 const char *message,
1173 const xmlChar *str1,
1174 const xmlChar *str2,
1175 const xmlChar *str3)
1176{
1177 xmlChar *str = NULL, *msg = NULL;
1178 xmlSchemaTypeType facetType;
1179
1180 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
1181 msg = xmlStrcat(msg, BAD_CAST " [");
1182 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1183 msg = xmlStrcat(msg, BAD_CAST ", facet '");
1184 if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
1185 facetType = XML_SCHEMA_FACET_ENUMERATION;
1186 /*
1187 * If enumerations are validated, one must not expect the
1188 * facet to be given.
1189 */
1190 } else
1191 facetType = facet->type;
1192 msg = xmlStrcat(msg, BAD_CAST xmlSchemaFacetTypeToString(facetType));
1193 msg = xmlStrcat(msg, BAD_CAST "']: ");
1194 if (message == NULL) {
1195 /*
1196 * Use a default message.
1197 */
1198 if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
1199 (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
1200 (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
1201
1202 char len[25], actLen[25];
1203
1204 /* FIXME, TODO: What is the max expected string length of the
1205 * this value?
1206 */
1207 if (node->type == XML_ATTRIBUTE_NODE)
1208 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
1209 else
1210 msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
1211
1212 snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
1213 snprintf(actLen, 24, "%lu", length);
1214
1215 if (facetType == XML_SCHEMA_FACET_LENGTH)
1216 msg = xmlStrcat(msg,
1217 BAD_CAST "this differs from the allowed length of '%s'.\n");
1218 else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
1219 msg = xmlStrcat(msg,
1220 BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
1221 else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
1222 msg = xmlStrcat(msg,
1223 BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
1224
1225 if (node->type == XML_ATTRIBUTE_NODE)
1226 xmlSchemaVErrExt(ctxt, node, error,
1227 (const char *) msg,
1228 value, (const xmlChar *) actLen, (const xmlChar *) len,
1229 NULL, NULL);
1230 else
1231 xmlSchemaVErr(ctxt, node, error,
1232 (const char *) msg,
1233 (const xmlChar *) actLen, (const xmlChar *) len);
1234
1235 } else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
1236 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
1237 "of the set {%s}.\n");
1238 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
1239 xmlSchemaFormatFacetEnumSet(&str, type));
1240 } else if (facetType == XML_SCHEMA_FACET_PATTERN) {
1241 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
1242 "by the pattern '%s'.\n");
1243 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
1244 facet->value);
1245 } else if (node->type == XML_ATTRIBUTE_NODE) {
1246 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
1247 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value, NULL);
1248 } else {
1249 msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
1250 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
1251 }
1252 } else {
1253 msg = xmlStrcat(msg, (const xmlChar *) message);
1254 msg = xmlStrcat(msg, BAD_CAST ".\n");
1255 xmlSchemaVErr3(ctxt, node, error, (const char *) msg, str1, str2, str3);
1256 }
1257 FREE_AND_NULL(str)
1258 xmlFree(msg);
1259}
1260
1261/**
1262 * xmlSchemaVSimpleTypeErr:
1263 * @ctxt: the schema validation context
1264 * @error: the error code
1265 * @type: the type used for validation
1266 * @node: the node containing the validated value
1267 * @value: the validated value
1268 *
1269 * Reports a simple type validation error.
1270 * TODO: Should this report the value of an element as well?
1271 */
1272static void
1273xmlSchemaVSimpleTypeErr(xmlSchemaValidCtxtPtr ctxt,
1274 xmlParserErrors error,
1275 xmlNodePtr node,
1276 const xmlChar *value,
1277 xmlSchemaTypePtr type)
1278{
1279 xmlChar *str = NULL, *msg = NULL;
1280
1281 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
1282 msg = xmlStrcat(msg, BAD_CAST " [");
1283 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1284 if (node->type == XML_ATTRIBUTE_NODE) {
1285 msg = xmlStrcat(msg, BAD_CAST "]: The value '%s' is not valid.\n");
1286 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value, NULL);
1287 } else {
1288 msg = xmlStrcat(msg, BAD_CAST "]: The character content is not valid.\n");
1289 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
1290 }
1291 FREE_AND_NULL(str)
1292 xmlFree(msg);
1293}
1294
1295/**
William M. Brack2f2a6632004-08-20 23:09:47 +00001296 * xmlSchemaVComplexTypeErr:
1297 * @ctxt: the schema validation context
1298 * @error: the error code
1299 * @node: the node containing the validated value
1300 * @type: the complex type used for validation
1301 * @message: the error message
1302 *
1303 * Reports a complex type validation error.
1304 */
1305static void
1306xmlSchemaVComplexTypeErr(xmlSchemaValidCtxtPtr ctxt,
1307 xmlParserErrors error,
1308 xmlNodePtr node,
1309 xmlSchemaTypePtr type,
1310 const char *message)
1311{
1312 xmlChar *str = NULL, *msg = NULL;
1313
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00001314 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00001315 /* Specify the complex type only if it is global. */
1316 if ((type != NULL) && (type->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00001317 msg = xmlStrcat(msg, BAD_CAST " [");
1318 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1319 msg = xmlStrcat(msg, BAD_CAST "]");
1320 }
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001321 msg = xmlStrcat(msg, BAD_CAST ": %s.\n");
1322 xmlSchemaVErr(ctxt, node, error, (const char *) msg,
William M. Brack2f2a6632004-08-20 23:09:47 +00001323 (const xmlChar *) message, NULL);
1324 FREE_AND_NULL(str)
1325 xmlFree(msg);
1326}
1327
1328/**
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001329 * xmlSchemaVComplexTypeElemErr:
1330 * @ctxt: the schema validation context
1331 * @error: the error code
1332 * @node: the node containing the validated value
1333 * @type: the complex type used for validation
1334 * @message: the error message
1335 *
1336 * Reports a complex type validation error.
1337 */
1338static void
1339xmlSchemaVComplexTypeElemErr(xmlSchemaValidCtxtPtr ctxt,
1340 xmlParserErrors error,
1341 xmlNodePtr node,
1342 xmlSchemaTypePtr type,
1343 const char *message,
1344 int nbval,
1345 int nbneg,
1346 xmlChar **values)
1347{
1348 xmlChar *str = NULL, *msg = NULL;
1349 xmlChar *localName, *nsName;
1350 const xmlChar *cur, *end;
1351 int i;
1352
1353 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
1354 /* Specify the complex type only if it is global. */
1355 if ((type != NULL) && (type->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
1356 msg = xmlStrcat(msg, BAD_CAST " [");
1357 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1358 msg = xmlStrcat(msg, BAD_CAST "]");
1359 FREE_AND_NULL(str)
1360 }
1361 msg = xmlStrcat(msg, BAD_CAST ": ");
1362 msg = xmlStrcat(msg, (const xmlChar *) message);
1363 /*
1364 * Note that is does not make sense to report that we have a
1365 * wildcard here, since the wildcard might be unfolded into
1366 * multiple transitions.
1367 */
1368 if (nbval + nbneg > 0) {
1369 if (nbval + nbneg > 1) {
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00001370 str = xmlStrdup(BAD_CAST ". Expected is one of ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001371 } else
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00001372 str = xmlStrdup(BAD_CAST ". Expected is ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001373 nsName = NULL;
1374
1375 for (i = 0; i < nbval + nbneg; i++) {
1376 cur = values[i];
1377 /*
1378 * Get the local name.
1379 */
1380 localName = NULL;
1381
1382 end = cur;
1383 if (*end == '*') {
1384 localName = xmlStrdup(BAD_CAST "*");
1385 *end++;
1386 } else {
1387 while ((*end != 0) && (*end != '|'))
1388 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001389 localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001390 }
1391 if (*end != 0) {
1392 *end++;
1393 /*
1394 * Skip "*|*" if they come with negated expressions, since
1395 * they represent the same negated wildcard.
1396 */
1397 if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
1398 /*
1399 * Get the namespace name.
1400 */
1401 cur = end;
1402 if (*end == '*') {
1403 nsName = xmlStrdup(BAD_CAST "{*}");
1404 } else {
1405 while (*end != 0)
1406 end++;
1407
1408 if (i >= nbval)
1409 nsName = xmlStrdup(BAD_CAST "{##other:");
1410 else
1411 nsName = xmlStrdup(BAD_CAST "{");
1412
1413 nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
1414 nsName = xmlStrcat(nsName, BAD_CAST "}");
1415 }
1416 str = xmlStrcat(str, BAD_CAST nsName);
1417 FREE_AND_NULL(nsName)
1418 } else {
1419 FREE_AND_NULL(localName);
1420 continue;
1421 }
1422 }
1423 str = xmlStrcat(str, BAD_CAST localName);
1424 FREE_AND_NULL(localName);
1425
1426 if (i < nbval + nbneg -1)
1427 str = xmlStrcat(str, BAD_CAST ", ");
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00001428 }
1429 str = xmlStrcat(str, BAD_CAST " )");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001430 msg = xmlStrcat(msg, BAD_CAST str);
1431 FREE_AND_NULL(str)
1432 }
1433 msg = xmlStrcat(msg, BAD_CAST ".\n");
1434 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
1435 xmlFree(msg);
1436}
1437
1438/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00001439 * xmlSchemaPMissingAttrErr:
1440 * @ctxt: the schema validation context
1441 * @ownerDes: the designation of the owner
1442 * @ownerName: the name of the owner
1443 * @ownerItem: the owner as a schema object
1444 * @ownerElem: the owner as an element node
1445 * @node: the parent element node of the missing attribute node
1446 * @type: the corresponding type of the attribute node
1447 *
1448 * Reports an illegal attribute.
1449 */
1450static void
1451xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
1452 xmlParserErrors error,
1453 xmlChar **ownerDes,
1454 xmlSchemaTypePtr ownerItem,
1455 xmlNodePtr ownerElem,
1456 const char *name,
1457 const char *message)
1458{
1459 xmlChar *des = NULL;
1460
1461 if (ownerDes == NULL)
1462 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
1463 else if (*ownerDes == NULL) {
1464 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
1465 des = *ownerDes;
1466 } else
1467 des = *ownerDes;
1468 if (message != NULL)
1469 xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
1470 else
1471 xmlSchemaPErr(ctxt, ownerElem, error,
1472 "%s: The attribute '%s' is required but missing.\n",
1473 BAD_CAST des, BAD_CAST name);
1474 if (ownerDes == NULL)
1475 FREE_AND_NULL(des);
1476}
1477
William M. Brack2f2a6632004-08-20 23:09:47 +00001478/**
1479 * xmlSchemaCompTypeToString:
1480 * @type: the type of the schema item
1481 *
1482 * Returns the component name of a schema item.
1483 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001484static const char *
1485xmlSchemaCompTypeToString(xmlSchemaTypeType type)
1486{
1487 switch (type) {
1488 case XML_SCHEMA_TYPE_SIMPLE:
1489 return("simple type definition");
1490 case XML_SCHEMA_TYPE_COMPLEX:
1491 return("complex type definition");
1492 case XML_SCHEMA_TYPE_ELEMENT:
1493 return("element declaration");
1494 case XML_SCHEMA_TYPE_ATTRIBUTE:
1495 return("attribute declaration");
1496 case XML_SCHEMA_TYPE_GROUP:
1497 return("model group definition");
1498 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1499 return("attribute group definition");
1500 case XML_SCHEMA_TYPE_NOTATION:
1501 return("notation declaration");
1502 default:
1503 return("Not a schema component");
1504 }
1505}
1506/**
1507 * xmlSchemaPResCompAttrErr:
1508 * @ctxt: the schema validation context
1509 * @error: the error code
1510 * @ownerDes: the designation of the owner
1511 * @ownerItem: the owner as a schema object
1512 * @ownerElem: the owner as an element node
1513 * @name: the name of the attribute holding the QName
1514 * @refName: the referenced local name
1515 * @refURI: the referenced namespace URI
1516 * @message: optional message
1517 *
1518 * Used to report QName attribute values that failed to resolve
1519 * to schema components.
1520 */
1521static void
1522xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
1523 xmlParserErrors error,
1524 xmlChar **ownerDes,
1525 xmlSchemaTypePtr ownerItem,
1526 xmlNodePtr ownerElem,
1527 const char *name,
1528 const xmlChar *refName,
1529 const xmlChar *refURI,
1530 xmlSchemaTypeType refType,
1531 const char *refTypeStr)
1532{
1533 xmlChar *des = NULL, *strA = NULL;
1534
1535 if (ownerDes == NULL)
1536 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
1537 else if (*ownerDes == NULL) {
1538 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
1539 des = *ownerDes;
1540 } else
1541 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001542 if (refTypeStr == NULL)
1543 refTypeStr = xmlSchemaCompTypeToString(refType);
1544 xmlSchemaPErrExt(ctxt, ownerElem, error,
1545 NULL, NULL, NULL,
1546 "%s, attribute '%s': The QName value %s does not resolve to a(n) "
1547 "%s.\n", BAD_CAST des, BAD_CAST name,
1548 xmlSchemaFormatNsUriLocal(&strA, refURI, refName),
1549 BAD_CAST refTypeStr, NULL);
1550 if (ownerDes == NULL)
1551 FREE_AND_NULL(des)
1552 FREE_AND_NULL(strA)
1553}
1554
William M. Brack2f2a6632004-08-20 23:09:47 +00001555/**
1556 * xmlSchemaPCustomAttrErr:
1557 * @ctxt: the schema parser context
1558 * @error: the error code
1559 * @ownerDes: the designation of the owner
1560 * @ownerItem: the owner as a schema object
1561 * @attr: the illegal attribute node
1562 *
1563 * Reports an illegal attribute during the parse.
1564 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001565static void
1566xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00001567 xmlParserErrors error,
1568 xmlChar **ownerDes,
1569 xmlSchemaTypePtr ownerItem,
1570 xmlAttrPtr attr,
1571 const char *msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001572{
1573 xmlChar *des = NULL;
1574
1575 if (ownerDes == NULL)
1576 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
1577 else if (*ownerDes == NULL) {
1578 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
1579 des = *ownerDes;
1580 } else
1581 des = *ownerDes;
1582 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
1583 "%s, attribute '%s': %s.\n",
1584 BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
1585 if (ownerDes == NULL)
1586 FREE_AND_NULL(des);
1587}
1588
1589/**
1590 * xmlSchemaPIllegalAttrErr:
William M. Brack2f2a6632004-08-20 23:09:47 +00001591 * @ctxt: the schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00001592 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00001593 * @ownerDes: the designation of the attribute's owner
1594 * @ownerItem: the attribute's owner item
Daniel Veillardc0826a72004-08-10 14:17:33 +00001595 * @attr: the illegal attribute node
1596 *
William M. Brack2f2a6632004-08-20 23:09:47 +00001597 * Reports an illegal attribute during the parse.
Daniel Veillardc0826a72004-08-10 14:17:33 +00001598 */
1599static void
1600xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
1601 xmlParserErrors error,
1602 xmlChar **ownerDes,
1603 xmlSchemaTypePtr ownerItem,
1604 xmlAttrPtr attr)
1605{
1606 xmlChar *des = NULL, *strA = NULL;
1607
1608 if (ownerDes == NULL)
1609 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
1610 else if (*ownerDes == NULL) {
1611 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
1612 des = *ownerDes;
1613 } else
1614 des = *ownerDes;
1615 xmlSchemaPErr(ctxt, (xmlNodePtr) attr, error,
1616 "%s: The attribute '%s' is not allowed.\n", BAD_CAST des,
1617 xmlSchemaFormatNsPrefixLocal(&strA, attr->ns, attr->name));
1618 if (ownerDes == NULL)
1619 FREE_AND_NULL(des);
1620 FREE_AND_NULL(strA);
1621}
1622
William M. Brack2f2a6632004-08-20 23:09:47 +00001623/**
1624 * xmlSchemaPAquireDes:
1625 * @des: the first designation
1626 * @itemDes: the second designation
1627 * @item: the schema item
1628 * @itemElem: the node of the schema item
1629 *
1630 * Creates a designation for an item.
1631 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001632static void
1633xmlSchemaPAquireDes(xmlChar **des,
1634 xmlChar **itemDes,
1635 xmlSchemaTypePtr item,
1636 xmlNodePtr itemElem)
1637{
1638 if (itemDes == NULL)
1639 xmlSchemaFormatItemForReport(des, NULL, item, itemElem, 1);
1640 else if (*itemDes == NULL) {
1641 xmlSchemaFormatItemForReport(itemDes, NULL, item, itemElem, 1);
1642 *des = *itemDes;
1643 } else
1644 *des = *itemDes;
1645}
1646
William M. Brack2f2a6632004-08-20 23:09:47 +00001647/**
1648 * xmlSchemaPCustomErr:
1649 * @ctxt: the schema parser context
1650 * @error: the error code
1651 * @itemDes: the designation of the schema item
1652 * @item: the schema item
1653 * @itemElem: the node of the schema item
1654 * @message: the error message
1655 * @str1: an optional param for the error message
1656 * @str2: an optional param for the error message
1657 * @str3: an optional param for the error message
1658 *
1659 * Reports an error during parsing.
1660 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001661static void
1662xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
1663 xmlParserErrors error,
1664 xmlChar **itemDes,
1665 xmlSchemaTypePtr item,
1666 xmlNodePtr itemElem,
1667 const char *message,
1668 const xmlChar *str1,
1669 const xmlChar *str2,
1670 const xmlChar *str3)
1671{
1672 xmlChar *des = NULL, *msg = NULL;
1673
1674 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
1675 msg = xmlStrdup(BAD_CAST "%s: ");
1676 msg = xmlStrcat(msg, (const xmlChar *) message);
1677 msg = xmlStrcat(msg, BAD_CAST ".\n");
1678 if ((itemElem == NULL) && (item != NULL))
1679 itemElem = item->node;
1680 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
1681 (const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
1682 if (itemDes == NULL)
1683 FREE_AND_NULL(des);
1684 FREE_AND_NULL(msg);
1685}
1686
William M. Brack2f2a6632004-08-20 23:09:47 +00001687/**
1688 * xmlSchemaPCustomErr:
1689 * @ctxt: the schema parser context
1690 * @error: the error code
1691 * @itemDes: the designation of the schema item
1692 * @item: the schema item
1693 * @itemElem: the node of the schema item
1694 * @message: the error message
1695 * @str1: the optional param for the error message
1696 *
1697 * Reports an error during parsing.
1698 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001699static void
1700xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
1701 xmlParserErrors error,
1702 xmlChar **itemDes,
1703 xmlSchemaTypePtr item,
1704 xmlNodePtr itemElem,
1705 const char *message,
1706 const xmlChar *str1)
1707{
1708 xmlSchemaPCustomErrExt(ctxt, error, itemDes, item, itemElem, message,
1709 str1, NULL, NULL);
1710}
1711
William M. Brack2f2a6632004-08-20 23:09:47 +00001712/**
1713 * xmlSchemaPAttrUseErr:
1714 * @ctxt: the schema parser context
1715 * @error: the error code
1716 * @itemDes: the designation of the schema type
1717 * @item: the schema type
1718 * @itemElem: the node of the schema type
1719 * @attr: the invalid schema attribute
1720 * @message: the error message
1721 * @str1: the optional param for the error message
1722 *
1723 * Reports an attribute use error during parsing.
1724 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001725static void
1726xmlSchemaPAttrUseErr(xmlSchemaParserCtxtPtr ctxt,
1727 xmlParserErrors error,
1728 xmlChar **itemDes,
1729 xmlSchemaTypePtr item,
1730 xmlNodePtr itemElem,
1731 const xmlSchemaAttributePtr attr,
1732 const char *message,
1733 const xmlChar *str1)
1734{
1735 xmlChar *des = NULL, *strA = NULL, *msg = NULL;
1736
1737 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
1738 xmlSchemaFormatNsUriLocal(&strA, xmlSchemaGetAttrTargetNsURI(attr),
1739 xmlSchemaGetAttrName(attr));
1740 msg = xmlStrdup(BAD_CAST "%s, attr. use %s: ");
1741 msg = xmlStrcat(msg, (const xmlChar *) message);
1742 msg = xmlStrcat(msg, BAD_CAST ".\n");
1743 if ((itemElem == NULL) && (item != NULL))
1744 itemElem = item->node;
1745 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
1746 (const char *) msg, BAD_CAST des, BAD_CAST strA, str1, NULL, NULL);
1747 if (itemDes == NULL)
1748 FREE_AND_NULL(des);
1749 FREE_AND_NULL(strA);
1750 xmlFree(msg);
1751}
1752
William M. Brack2f2a6632004-08-20 23:09:47 +00001753/**
1754 * xmlSchemaPIllegalFacetAtomicErr:
1755 * @ctxt: the schema parser context
1756 * @error: the error code
1757 * @itemDes: the designation of the type
1758 * @item: the schema type
1759 * @baseItem: the base type of type
1760 * @facet: the illegal facet
1761 *
1762 * Reports an illegal facet for atomic simple types.
1763 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001764static void
1765xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
1766 xmlParserErrors error,
1767 xmlChar **itemDes,
1768 xmlSchemaTypePtr item,
1769 xmlSchemaTypePtr baseItem,
1770 xmlSchemaFacetPtr facet)
1771{
1772 xmlChar *des = NULL, *strT = NULL;
1773
1774 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
1775 xmlSchemaPErrExt(ctxt, item->node, error, NULL, NULL, NULL,
1776 "%s: The facet '%s' is not allowed on types derived from the "
1777 "type %s.\n",
1778 BAD_CAST des, BAD_CAST xmlSchemaFacetTypeToString(facet->type),
1779 xmlSchemaFormatItemForReport(&strT, NULL, baseItem, NULL, 1),
1780 NULL, NULL);
1781 if (itemDes == NULL)
1782 FREE_AND_NULL(des);
1783 FREE_AND_NULL(strT);
1784}
1785
William M. Brack2f2a6632004-08-20 23:09:47 +00001786/**
1787 * xmlSchemaPIllegalFacetListUnionErr:
1788 * @ctxt: the schema parser context
1789 * @error: the error code
1790 * @itemDes: the designation of the schema item involved
1791 * @item: the schema item involved
1792 * @facet: the illegal facet
1793 *
1794 * Reports an illegal facet for <list> and <union>.
1795 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001796static void
1797xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
1798 xmlParserErrors error,
1799 xmlChar **itemDes,
1800 xmlSchemaTypePtr item,
1801 xmlSchemaFacetPtr facet)
1802{
1803 xmlChar *des = NULL, *strT = NULL;
1804
1805 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
1806 xmlSchemaPErr(ctxt, item->node, error,
1807 "%s: The facet '%s' is not allowed.\n",
1808 BAD_CAST des, BAD_CAST xmlSchemaFacetTypeToString(facet->type));
1809 if (itemDes == NULL)
1810 FREE_AND_NULL(des);
1811 FREE_AND_NULL(strT);
1812}
1813
1814/**
1815 * xmlSchemaPMutualExclAttrErr:
1816 * @ctxt: the schema validation context
1817 * @error: the error code
1818 * @elemDes: the designation of the parent element node
1819 * @attr: the bad attribute node
1820 * @type: the corresponding type of the attribute node
1821 *
1822 * Reports an illegal attribute.
1823 */
1824static void
1825xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
1826 xmlParserErrors error,
1827 xmlChar **ownerDes,
1828 xmlSchemaTypePtr ownerItem,
1829 xmlAttrPtr attr,
1830 const char *name1,
1831 const char *name2)
1832{
1833 xmlChar *des = NULL;
1834
1835 if (ownerDes == NULL)
1836 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
1837 else if (*ownerDes == NULL) {
1838 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
1839 des = *ownerDes;
1840 } else
1841 des = *ownerDes;
1842 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
1843 "%s: The attributes '%s' and '%s' are mutually exclusive.\n",
1844 BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
1845 if (ownerDes == NULL)
1846 FREE_AND_NULL(des)
1847}
1848
1849/**
1850 * xmlSchemaPSimpleTypeErr:
1851 * @ctxt: the schema validation context
1852 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00001853 * @type: the type specifier
Daniel Veillardc0826a72004-08-10 14:17:33 +00001854 * @ownerDes: the designation of the owner
1855 * @ownerItem: the schema object if existent
1856 * @node: the validated node
1857 * @value: the validated value
1858 *
1859 * Reports a simple type validation error.
1860 * TODO: Should this report the value of an element as well?
1861 */
1862static void
1863xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
1864 xmlParserErrors error,
1865 xmlChar **ownerDes,
1866 xmlSchemaTypePtr ownerItem,
1867 xmlNodePtr node,
William M. Brack2f2a6632004-08-20 23:09:47 +00001868 xmlSchemaTypePtr type,
Daniel Veillardc0826a72004-08-10 14:17:33 +00001869 const char *typeDes,
1870 const xmlChar *value,
1871 const char *message,
1872 const xmlChar *str1,
1873 const xmlChar *str2)
1874{
William M. Brack2f2a6632004-08-20 23:09:47 +00001875 xmlChar *des = NULL, *strA = NULL, *strT = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001876
1877 if (ownerDes == NULL)
1878 xmlSchemaPRequestItemDes(&des, ownerItem, node);
1879 else if (*ownerDes == NULL) {
1880 xmlSchemaPRequestItemDes(ownerDes, ownerItem, node);
1881 des = *ownerDes;
1882 } else
1883 des = *ownerDes;
William M. Brack2f2a6632004-08-20 23:09:47 +00001884 if (type != NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001885 typeDes = (const char *) xmlSchemaFormatItemForReport(&strT, NULL, type, NULL, 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001886 if (message == NULL) {
1887 /*
1888 * Use default messages.
1889 */
1890 if (node->type == XML_ATTRIBUTE_NODE) {
1891 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
1892 "%s, attribute '%s' [%s]: The value '%s' is not "
1893 "valid.\n",
1894 BAD_CAST des, xmlSchemaFormatNsPrefixLocal(&strA, node->ns,
1895 node->name), BAD_CAST typeDes, value, NULL);
1896 } else {
1897 xmlSchemaPErr(ctxt, node, error,
1898 "%s [%s]: The character content is not valid.\n",
1899 BAD_CAST des, BAD_CAST typeDes);
1900 }
1901 } else {
1902 xmlChar *msg;
1903
1904 msg = xmlStrdup(BAD_CAST "%s");
1905 if (node->type == XML_ATTRIBUTE_NODE)
1906 msg = xmlStrcat(msg, BAD_CAST ", attribute '%s'");
1907 msg = xmlStrcat(msg, BAD_CAST " [%s]: ");
1908 msg = xmlStrcat(msg, (const xmlChar *) message);
1909 msg = xmlStrcat(msg, BAD_CAST ".\n");
1910 if (node->type == XML_ATTRIBUTE_NODE) {
1911 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
1912 (const char *) msg,
1913 BAD_CAST des, xmlSchemaFormatNsPrefixLocal(&strA,
1914 node->ns, node->name), BAD_CAST typeDes, str1, str2);
1915 } else {
1916 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
1917 (const char *) msg,
1918 BAD_CAST des, BAD_CAST typeDes, str1, str2, NULL);
1919 }
1920 xmlFree(msg);
1921 }
1922 /* Cleanup. */
1923 FREE_AND_NULL(strA)
1924 FREE_AND_NULL(strT)
1925 if (ownerDes == NULL)
1926 FREE_AND_NULL(des)
1927}
1928
William M. Brack2f2a6632004-08-20 23:09:47 +00001929/**
1930 * xmlSchemaPContentErr:
1931 * @ctxt: the schema parser context
1932 * @error: the error code
1933 * @onwerDes: the designation of the holder of the content
1934 * @ownerItem: the owner item of the holder of the content
1935 * @ownerElem: the node of the holder of the content
1936 * @child: the invalid child node
1937 * @message: the optional error message
1938 * @content: the optional string describing the correct content
1939 *
1940 * Reports an error concerning the content of a schema element.
1941 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001942static void
1943xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
1944 xmlParserErrors error,
1945 xmlChar **ownerDes,
1946 xmlSchemaTypePtr ownerItem,
1947 xmlNodePtr ownerElem,
1948 xmlNodePtr child,
1949 const char *message,
1950 const char *content)
1951{
1952 xmlChar *des = NULL;
1953
1954 if (ownerDes == NULL)
1955 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
1956 else if (*ownerDes == NULL) {
1957 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
1958 des = *ownerDes;
1959 } else
1960 des = *ownerDes;
1961 if (message != NULL)
1962 xmlSchemaPErr2(ctxt, ownerElem, child, error,
1963 "%s: %s.\n",
1964 BAD_CAST des, BAD_CAST message);
1965 else {
1966 if (content != NULL) {
1967 xmlSchemaPErr2(ctxt, ownerElem, child, error,
1968 "%s: The content is not valid. Expected is %s.\n",
1969 BAD_CAST des, BAD_CAST content);
1970 } else {
1971 xmlSchemaPErr2(ctxt, ownerElem, child, error,
1972 "%s: The content is not valid.\n",
1973 BAD_CAST des, NULL);
1974 }
1975 }
1976 if (ownerDes == NULL)
1977 FREE_AND_NULL(des)
1978}
1979
1980/**
1981 * xmlSchemaVIllegalAttrErr:
1982 * @ctxt: the schema validation context
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001983 * @error: the error code
Daniel Veillardc0826a72004-08-10 14:17:33 +00001984 * @attr: the illegal attribute node
1985 *
1986 * Reports an illegal attribute.
1987 */
1988static void
1989xmlSchemaVIllegalAttrErr(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001990 xmlParserErrors error,
William M. Brack2f2a6632004-08-20 23:09:47 +00001991 xmlAttrPtr attr)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001992{
1993 xmlChar *strE = NULL, *strA = NULL;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001994
1995 xmlSchemaVErr(ctxt, (xmlNodePtr) attr,
1996 error,
1997 /* XML_SCHEMAS_ERR_ATTRUNKNOWN, */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001998 "%s: The attribute '%s' is not allowed.\n",
1999 xmlSchemaFormatItemForReport(&strE, NULL, NULL, attr->parent, 0),
2000 xmlSchemaFormatNsPrefixLocal(&strA, attr->ns, attr->name));
2001 FREE_AND_NULL(strE)
2002 FREE_AND_NULL(strA)
2003}
2004
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002005
2006static int
2007xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
2008{
2009 switch (item->type) {
2010 case XML_SCHEMA_TYPE_COMPLEX:
2011 case XML_SCHEMA_TYPE_SIMPLE:
2012 case XML_SCHEMA_TYPE_GROUP:
2013 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
2014 return(1);
2015 break;
2016 case XML_SCHEMA_TYPE_ELEMENT:
2017 if ( ((xmlSchemaElementPtr) item)->flags &
2018 XML_SCHEMAS_ELEM_GLOBAL)
2019 return(1);
2020 break;
2021 case XML_SCHEMA_TYPE_ATTRIBUTE:
2022 if ( ((xmlSchemaAttributePtr) item)->flags &
2023 XML_SCHEMAS_ATTR_GLOBAL)
2024 return(1);
2025 break;
2026 /* Note that attribute groups are always global. */
2027 default:
2028 return(1);
2029 }
2030 return (0);
2031}
2032
William M. Brack2f2a6632004-08-20 23:09:47 +00002033/**
2034 * xmlSchemaVCustomErr:
2035 * @ctxt: the schema validation context
2036 * @error: the error code
2037 * @node: the validated node
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002038 * @type: the schema type of the validated node
William M. Brack2f2a6632004-08-20 23:09:47 +00002039 * @message: the error message
2040 * @str1: the optional param for the message
2041 *
2042 * Reports a validation error.
2043 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002044static void
2045xmlSchemaVCustomErr(xmlSchemaValidCtxtPtr ctxt,
2046 xmlParserErrors error,
2047 xmlNodePtr node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002048 xmlSchemaTypePtr type,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002049 const char *message,
2050 const xmlChar *str1)
2051{
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002052 xmlChar *msg = NULL, *str = NULL;
2053
2054 if (node == NULL) {
2055 xmlSchemaVErr(ctxt, NULL,
2056 XML_SCHEMAV_INTERNAL,
2057 "Internal error: xmlSchemaVCustomErr, no node "
2058 "given.\n", NULL, NULL);
2059 return;
2060 }
2061 /* TODO: Are the HTML and DOCB doc nodes expected here? */
2062 if (node->type != XML_DOCUMENT_NODE) {
2063 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002064 if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002065 msg = xmlStrcat(msg, BAD_CAST " [");
2066 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
2067 msg = xmlStrcat(msg, BAD_CAST "]");
2068 }
2069 msg = xmlStrcat(msg, BAD_CAST ": ");
2070 } else
2071 msg = xmlStrdup((const xmlChar *) "");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002072 msg = xmlStrcat(msg, (const xmlChar *) message);
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002073 msg = xmlStrcat(msg, BAD_CAST ".\n");
2074 xmlSchemaVErr(ctxt, node, error, (const char *) msg, str1, NULL);
2075 FREE_AND_NULL(msg)
2076 FREE_AND_NULL(str)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002077}
2078
William M. Brack2f2a6632004-08-20 23:09:47 +00002079/**
2080 * xmlSchemaWildcardPCToString:
2081 * @pc: the type of processContents
2082 *
2083 * Returns a string representation of the type of
2084 * processContents.
2085 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002086static const char *
2087xmlSchemaWildcardPCToString(int pc)
2088{
2089 switch (pc) {
2090 case XML_SCHEMAS_ANY_SKIP:
2091 return ("skip");
2092 case XML_SCHEMAS_ANY_LAX:
2093 return ("lax");
2094 case XML_SCHEMAS_ANY_STRICT:
2095 return ("strict");
2096 default:
2097 return ("invalid process contents");
2098 }
2099}
2100
William M. Brack2f2a6632004-08-20 23:09:47 +00002101/**
2102 * xmlSchemaVWildcardErr:
2103 * @ctxt: the schema validation context
2104 * @error: the error code
2105 * @node: the validated node
2106 * @wild: the wildcard used
2107 * @message: the error message
2108 *
2109 * Reports an validation-by-wildcard error.
2110 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002111static void
2112xmlSchemaVWildcardErr(xmlSchemaValidCtxtPtr ctxt,
2113 xmlParserErrors error,
2114 xmlNodePtr node,
2115 xmlSchemaWildcardPtr wild,
2116 const char *message)
2117{
2118 xmlChar *des = NULL, *msg = NULL;
2119
2120 xmlSchemaFormatItemForReport(&des, NULL, NULL, node, 0);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00002121 msg = xmlStrdup(BAD_CAST "%s [");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002122 msg = xmlStrcat(msg, BAD_CAST xmlSchemaWildcardPCToString(wild->processContents));
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002123 msg = xmlStrcat(msg, BAD_CAST " wildcard]: ");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002124 msg = xmlStrcat(msg, (const xmlChar *) message);
2125 msg = xmlStrcat(msg, BAD_CAST ".\n");
2126 xmlSchemaVErr(ctxt, node, error, (const char *) msg, BAD_CAST des, NULL);
2127 FREE_AND_NULL(des);
2128 FREE_AND_NULL(msg);
2129}
2130
2131/**
2132 * xmlSchemaVMissingAttrErr:
2133 * @ctxt: the schema validation context
2134 * @node: the parent element node of the missing attribute node
2135 * @type: the corresponding type of the attribute node
2136 *
2137 * Reports an illegal attribute.
2138 */
2139static void
2140xmlSchemaVMissingAttrErr(xmlSchemaValidCtxtPtr ctxt,
2141 xmlNodePtr elem,
2142 xmlSchemaAttributePtr type)
2143{
2144 const xmlChar *name, *uri;
2145 xmlChar *strE = NULL, *strA = NULL;
2146
2147 if (type->ref != NULL) {
2148 name = type->ref;
2149 uri = type->refNs;
2150 } else {
2151 name = type->name;
2152 uri = type->targetNamespace;
2153 }
2154 xmlSchemaVErr(ctxt, elem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002155 XML_SCHEMAV_CVC_COMPLEX_TYPE_4,
2156 /* XML_SCHEMAS_ERR_MISSING, */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002157 "%s: The attribute %s is required but missing.\n",
2158 xmlSchemaFormatItemForReport(&strE, NULL, NULL, elem, 0),
2159 xmlSchemaFormatNsUriLocal(&strA, uri, name));
2160 FREE_AND_NULL(strE)
2161 FREE_AND_NULL(strA)
2162}
2163
Daniel Veillard4255d502002-04-16 15:50:10 +00002164/************************************************************************
2165 * *
2166 * Allocation functions *
2167 * *
2168 ************************************************************************/
2169
2170/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002171 * xmlSchemaNewSchemaForParserCtxt:
William M. Brack08171912003-12-29 02:52:11 +00002172 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00002173 *
2174 * Allocate a new Schema structure.
2175 *
2176 * Returns the newly allocated structure or NULL in case or error
2177 */
2178static xmlSchemaPtr
2179xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
2180{
2181 xmlSchemaPtr ret;
2182
2183 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
2184 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002185 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002186 return (NULL);
2187 }
2188 memset(ret, 0, sizeof(xmlSchema));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002189 ret->dict = ctxt->dict;
Daniel Veillard500a1de2004-03-22 15:22:58 +00002190 xmlDictReference(ret->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00002191
2192 return (ret);
2193}
2194
2195/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002196 * xmlSchemaNewSchema:
2197 * @ctxt: a schema validation context
2198 *
2199 * Allocate a new Schema structure.
2200 *
2201 * Returns the newly allocated structure or NULL in case or error
2202 */
2203static xmlSchemaAssemblePtr
2204xmlSchemaNewAssemble(void)
2205{
2206 xmlSchemaAssemblePtr ret;
2207
2208 ret = (xmlSchemaAssemblePtr) xmlMalloc(sizeof(xmlSchemaAssemble));
2209 if (ret == NULL) {
2210 /* xmlSchemaPErrMemory(ctxt, "allocating assemble info", NULL); */
2211 return (NULL);
2212 }
2213 memset(ret, 0, sizeof(xmlSchemaAssemble));
2214 ret->items = NULL;
2215 return (ret);
2216}
2217
2218/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002219 * xmlSchemaNewFacet:
Daniel Veillard4255d502002-04-16 15:50:10 +00002220 *
2221 * Allocate a new Facet structure.
2222 *
2223 * Returns the newly allocated structure or NULL in case or error
2224 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00002225xmlSchemaFacetPtr
2226xmlSchemaNewFacet(void)
Daniel Veillard4255d502002-04-16 15:50:10 +00002227{
2228 xmlSchemaFacetPtr ret;
2229
2230 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
2231 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002232 return (NULL);
2233 }
2234 memset(ret, 0, sizeof(xmlSchemaFacet));
2235
2236 return (ret);
2237}
2238
2239/**
2240 * xmlSchemaNewAnnot:
William M. Brack08171912003-12-29 02:52:11 +00002241 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00002242 * @node: a node
2243 *
2244 * Allocate a new annotation structure.
2245 *
2246 * Returns the newly allocated structure or NULL in case or error
2247 */
2248static xmlSchemaAnnotPtr
2249xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
2250{
2251 xmlSchemaAnnotPtr ret;
2252
2253 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
2254 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002255 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
Daniel Veillard4255d502002-04-16 15:50:10 +00002256 return (NULL);
2257 }
2258 memset(ret, 0, sizeof(xmlSchemaAnnot));
2259 ret->content = node;
2260 return (ret);
2261}
2262
2263/**
Daniel Veillardfdc91562002-07-01 21:52:03 +00002264 * xmlSchemaFreeAnnot:
2265 * @annot: a schema type structure
2266 *
2267 * Deallocate a annotation structure
2268 */
2269static void
2270xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
2271{
2272 if (annot == NULL)
2273 return;
2274 xmlFree(annot);
2275}
2276
2277/**
Daniel Veillard1d913862003-11-21 00:28:39 +00002278 * xmlSchemaFreeImport:
2279 * @import: a schema import structure
2280 *
2281 * Deallocate an import structure
2282 */
2283static void
2284xmlSchemaFreeImport(xmlSchemaImportPtr import)
2285{
2286 if (import == NULL)
2287 return;
2288
2289 xmlSchemaFree(import->schema);
William M. Brack2f2a6632004-08-20 23:09:47 +00002290 xmlFreeDoc(import->doc);
Daniel Veillard1d913862003-11-21 00:28:39 +00002291 xmlFree(import);
2292}
2293
2294/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002295 * xmlSchemaFreeInclude:
2296 * @include: a schema include structure
2297 *
2298 * Deallocate an include structure
2299 */
2300static void
2301xmlSchemaFreeInclude(xmlSchemaIncludePtr include)
2302{
2303 if (include == NULL)
2304 return;
2305
2306 xmlFreeDoc(include->doc);
2307 xmlFree(include);
2308}
2309
2310/**
2311 * xmlSchemaFreeIncludeList:
2312 * @includes: a schema include list
2313 *
2314 * Deallocate an include structure
2315 */
2316static void
2317xmlSchemaFreeIncludeList(xmlSchemaIncludePtr includes)
2318{
2319 xmlSchemaIncludePtr next;
2320
2321 while (includes != NULL) {
2322 next = includes->next;
2323 xmlSchemaFreeInclude(includes);
2324 includes = next;
2325 }
2326}
2327
2328/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002329 * xmlSchemaFreeNotation:
2330 * @schema: a schema notation structure
2331 *
2332 * Deallocate a Schema Notation structure.
2333 */
2334static void
2335xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
2336{
2337 if (nota == NULL)
2338 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002339 xmlFree(nota);
2340}
2341
2342/**
2343 * xmlSchemaFreeAttribute:
2344 * @schema: a schema attribute structure
2345 *
2346 * Deallocate a Schema Attribute structure.
2347 */
2348static void
2349xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
2350{
2351 if (attr == NULL)
2352 return;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002353 if (attr->annot != NULL)
2354 xmlSchemaFreeAnnot(attr->annot);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002355 if (attr->defVal != NULL)
2356 xmlSchemaFreeValue(attr->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00002357 xmlFree(attr);
2358}
2359
2360/**
Daniel Veillard3646d642004-06-02 19:19:14 +00002361 * xmlSchemaFreeWildcardNsSet:
2362 * set: a schema wildcard namespace
2363 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00002364 * Deallocates a list of wildcard constraint structures.
Daniel Veillard3646d642004-06-02 19:19:14 +00002365 */
2366static void
2367xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
2368{
2369 xmlSchemaWildcardNsPtr next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002370
Daniel Veillard3646d642004-06-02 19:19:14 +00002371 while (set != NULL) {
2372 next = set->next;
2373 xmlFree(set);
2374 set = next;
2375 }
2376}
2377
2378/**
2379 * xmlSchemaFreeWildcard:
Daniel Veillard01fa6152004-06-29 17:04:39 +00002380 * @wildcard: a wildcard structure
Daniel Veillard3646d642004-06-02 19:19:14 +00002381 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00002382 * Deallocates a wildcard structure.
Daniel Veillard3646d642004-06-02 19:19:14 +00002383 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00002384void
Daniel Veillard3646d642004-06-02 19:19:14 +00002385xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
2386{
2387 if (wildcard == NULL)
2388 return;
2389 if (wildcard->annot != NULL)
2390 xmlSchemaFreeAnnot(wildcard->annot);
2391 if (wildcard->nsSet != NULL)
2392 xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
2393 if (wildcard->negNsSet != NULL)
2394 xmlFree(wildcard->negNsSet);
2395 xmlFree(wildcard);
2396}
2397
2398/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002399 * xmlSchemaFreeAttributeGroup:
2400 * @schema: a schema attribute group structure
2401 *
2402 * Deallocate a Schema Attribute Group structure.
2403 */
2404static void
2405xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attr)
2406{
2407 if (attr == NULL)
2408 return;
Daniel Veillard3646d642004-06-02 19:19:14 +00002409 if (attr->annot != NULL)
2410 xmlSchemaFreeAnnot(attr->annot);
2411 if ((attr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) &&
2412 (attr->attributeWildcard != NULL))
2413 xmlSchemaFreeWildcard(attr->attributeWildcard);
2414
Daniel Veillard4255d502002-04-16 15:50:10 +00002415 xmlFree(attr);
2416}
2417
2418/**
Daniel Veillard3646d642004-06-02 19:19:14 +00002419 * xmlSchemaFreeAttributeUseList:
Daniel Veillard01fa6152004-06-29 17:04:39 +00002420 * @attrUse: an attribute link
Daniel Veillard3646d642004-06-02 19:19:14 +00002421 *
2422 * Deallocate a list of schema attribute uses.
2423 */
2424static void
2425xmlSchemaFreeAttributeUseList(xmlSchemaAttributeLinkPtr attrUse)
2426{
2427 xmlSchemaAttributeLinkPtr next;
2428
2429 while (attrUse != NULL) {
2430 next = attrUse->next;
2431 xmlFree(attrUse);
2432 attrUse = next;
2433 }
2434}
2435
2436/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00002437 * xmlSchemaFreeTypeLinkList:
2438 * @alink: a type link
2439 *
2440 * Deallocate a list of types.
2441 */
2442static void
2443xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
2444{
2445 xmlSchemaTypeLinkPtr next;
2446
2447 while (link != NULL) {
2448 next = link->next;
2449 xmlFree(link);
2450 link = next;
2451 }
2452}
2453
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00002454#ifdef IDC_ENABLED
2455static void
2456xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
2457{
2458 xmlSchemaIDCStateObjPtr next;
2459 while (sto != NULL) {
2460 next = sto->next;
2461 if (sto->history != NULL)
2462 xmlFree(sto->history);
2463 if (sto->xpathCtxt != NULL)
2464 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
2465 xmlFree(sto);
2466 sto = next;
2467 }
2468}
2469
2470/**
2471 * xmlSchemaFreeIDC:
2472 * @idc: a identity-constraint definition
2473 *
2474 * Deallocates an identity-constraint definition.
2475 */
2476static void
2477xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)
2478{
2479 xmlSchemaIDCSelectPtr cur, prev;
2480
2481 if (idcDef == NULL)
2482 return;
2483 if (idcDef->annot != NULL)
2484 xmlSchemaFreeAnnot(idcDef->annot);
2485 if (idcDef->ref != NULL)
2486 xmlFree(idcDef->ref);
2487 /* Selector */
2488 if (idcDef->selector != NULL) {
2489 if (idcDef->selector->xpathComp != NULL)
2490 xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp);
2491 xmlFree(idcDef->selector);
2492 }
2493 /* Fields */
2494 if (idcDef->fields != NULL) {
2495 cur = idcDef->fields;
2496 do {
2497 prev = cur;
2498 cur = cur->next;
2499 if (prev->xpathComp != NULL)
2500 xmlFreePattern((xmlPatternPtr) prev->xpathComp);
2501 xmlFree(prev);
2502 } while (cur != NULL);
2503 }
2504 xmlFree(idcDef);
2505}
2506#endif /* IDC_ENABLED */
2507
Daniel Veillard01fa6152004-06-29 17:04:39 +00002508/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002509 * xmlSchemaFreeElement:
2510 * @schema: a schema element structure
2511 *
2512 * Deallocate a Schema Element structure.
2513 */
2514static void
2515xmlSchemaFreeElement(xmlSchemaElementPtr elem)
2516{
2517 if (elem == NULL)
2518 return;
Daniel Veillard32370232002-10-16 14:08:14 +00002519 if (elem->annot != NULL)
2520 xmlSchemaFreeAnnot(elem->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00002521 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002522 xmlRegFreeRegexp(elem->contModel);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002523 if (elem->defVal != NULL)
2524 xmlSchemaFreeValue(elem->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00002525 xmlFree(elem);
2526}
2527
2528/**
2529 * xmlSchemaFreeFacet:
2530 * @facet: a schema facet structure
2531 *
2532 * Deallocate a Schema Facet structure.
2533 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00002534void
Daniel Veillard4255d502002-04-16 15:50:10 +00002535xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
2536{
2537 if (facet == NULL)
2538 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002539 if (facet->val != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002540 xmlSchemaFreeValue(facet->val);
Daniel Veillard4255d502002-04-16 15:50:10 +00002541 if (facet->regexp != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002542 xmlRegFreeRegexp(facet->regexp);
Daniel Veillardfdc91562002-07-01 21:52:03 +00002543 if (facet->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002544 xmlSchemaFreeAnnot(facet->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00002545 xmlFree(facet);
2546}
2547
2548/**
2549 * xmlSchemaFreeType:
2550 * @type: a schema type structure
2551 *
2552 * Deallocate a Schema Type structure.
2553 */
2554void
2555xmlSchemaFreeType(xmlSchemaTypePtr type)
2556{
2557 if (type == NULL)
2558 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002559 if (type->annot != NULL)
Daniel Veillard32370232002-10-16 14:08:14 +00002560 xmlSchemaFreeAnnot(type->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00002561 if (type->facets != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002562 xmlSchemaFacetPtr facet, next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002563
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002564 facet = type->facets;
2565 while (facet != NULL) {
2566 next = facet->next;
2567 xmlSchemaFreeFacet(facet);
2568 facet = next;
2569 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002570 }
Daniel Veillard3646d642004-06-02 19:19:14 +00002571 if (type->type != XML_SCHEMA_TYPE_BASIC) {
2572 if (type->attributeUses != NULL)
2573 xmlSchemaFreeAttributeUseList(type->attributeUses);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002574 if ((type->attributeWildcard != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +00002575 ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002576 (type->flags & XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD))) {
2577 /*
2578 * NOTE: The only case where an attribute wildcard
2579 * is not owned, is if a complex type inherits it
2580 * from a base type.
2581 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002582 xmlSchemaFreeWildcard(type->attributeWildcard);
2583 }
2584 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00002585 if (type->memberTypes != NULL)
2586 xmlSchemaFreeTypeLinkList(type->memberTypes);
2587 if (type->facetSet != NULL) {
2588 xmlSchemaFacetLinkPtr next, link;
2589
2590 link = type->facetSet;
2591 do {
2592 next = link->next;
2593 xmlFree(link);
2594 link = next;
2595 } while (link != NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002596 }
2597 if (type->contModel != NULL)
2598 xmlRegFreeRegexp(type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00002599 xmlFree(type);
2600}
2601
2602/**
Daniel Veillardb0f397e2003-12-23 23:30:53 +00002603 * xmlSchemaFreeTypeList:
2604 * @type: a schema type structure
2605 *
2606 * Deallocate a Schema Type structure.
2607 */
2608static void
2609xmlSchemaFreeTypeList(xmlSchemaTypePtr type)
2610{
2611 xmlSchemaTypePtr next;
2612
2613 while (type != NULL) {
2614 next = type->redef;
2615 xmlSchemaFreeType(type);
2616 type = next;
2617 }
2618}
2619
2620/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002621 * xmlSchemaFree:
2622 * @schema: a schema structure
2623 *
2624 * Deallocate a Schema structure.
2625 */
2626void
2627xmlSchemaFree(xmlSchemaPtr schema)
2628{
2629 if (schema == NULL)
2630 return;
2631
Daniel Veillard4255d502002-04-16 15:50:10 +00002632 if (schema->notaDecl != NULL)
2633 xmlHashFree(schema->notaDecl,
2634 (xmlHashDeallocator) xmlSchemaFreeNotation);
2635 if (schema->attrDecl != NULL)
2636 xmlHashFree(schema->attrDecl,
2637 (xmlHashDeallocator) xmlSchemaFreeAttribute);
2638 if (schema->attrgrpDecl != NULL)
2639 xmlHashFree(schema->attrgrpDecl,
2640 (xmlHashDeallocator) xmlSchemaFreeAttributeGroup);
2641 if (schema->elemDecl != NULL)
2642 xmlHashFree(schema->elemDecl,
2643 (xmlHashDeallocator) xmlSchemaFreeElement);
2644 if (schema->typeDecl != NULL)
2645 xmlHashFree(schema->typeDecl,
Daniel Veillardb0f397e2003-12-23 23:30:53 +00002646 (xmlHashDeallocator) xmlSchemaFreeTypeList);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00002647 if (schema->groupDecl != NULL)
2648 xmlHashFree(schema->groupDecl,
2649 (xmlHashDeallocator) xmlSchemaFreeType);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00002650#ifdef IDC_ENABLED
2651 if (schema->idcDef != NULL)
2652 xmlHashFree(schema->idcDef,
2653 (xmlHashDeallocator) xmlSchemaFreeIDC);
2654#endif
Daniel Veillard1d913862003-11-21 00:28:39 +00002655 if (schema->schemasImports != NULL)
2656 xmlHashFree(schema->schemasImports,
2657 (xmlHashDeallocator) xmlSchemaFreeImport);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002658 if (schema->includes != NULL) {
2659 xmlSchemaFreeIncludeList((xmlSchemaIncludePtr) schema->includes);
2660 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002661 if (schema->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002662 xmlSchemaFreeAnnot(schema->annot);
Daniel Veillarddda22c12004-01-24 08:31:30 +00002663 if (schema->doc != NULL && !schema->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002664 xmlFreeDoc(schema->doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002665 xmlDictFree(schema->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00002666 xmlFree(schema);
2667}
2668
2669/************************************************************************
2670 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00002671 * Debug functions *
2672 * *
2673 ************************************************************************/
2674
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002675#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002676
Daniel Veillard4255d502002-04-16 15:50:10 +00002677/**
2678 * xmlSchemaElementDump:
2679 * @elem: an element
2680 * @output: the file output
2681 *
2682 * Dump the element
2683 */
2684static void
2685xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002686 const xmlChar * name ATTRIBUTE_UNUSED,
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002687 const xmlChar * namespace ATTRIBUTE_UNUSED,
2688 const xmlChar * context ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00002689{
2690 if (elem == NULL)
2691 return;
2692
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002693 if (elem->flags & XML_SCHEMAS_ELEM_REF) {
2694 fprintf(output, "Particle: %s", name);
2695 fprintf(output, ", term element: %s", elem->ref);
2696 if (elem->refNs != NULL)
2697 fprintf(output, " ns %s", elem->refNs);
2698 } else {
2699 fprintf(output, "Element");
2700 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
2701 fprintf(output, " (global)");
2702 fprintf(output, ": %s ", elem->name);
2703 if (namespace != NULL)
2704 fprintf(output, "ns %s", namespace);
2705 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002706 fprintf(output, "\n");
2707 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002708 fprintf(output, " min %d ", elem->minOccurs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002709 if (elem->maxOccurs >= UNBOUNDED)
2710 fprintf(output, "max: unbounded\n");
2711 else if (elem->maxOccurs != 1)
2712 fprintf(output, "max: %d\n", elem->maxOccurs);
2713 else
2714 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002715 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002716 /*
2717 * Misc other properties.
2718 */
2719 if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
2720 (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
2721 (elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
2722 (elem->flags & XML_SCHEMAS_ELEM_DEFAULT) ||
2723 (elem->id != NULL)) {
2724 fprintf(output, " props: ");
2725 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
2726 fprintf(output, "[fixed] ");
2727 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
2728 fprintf(output, "[default] ");
2729 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
2730 fprintf(output, "[abstract] ");
2731 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
2732 fprintf(output, "[nillable] ");
2733 if (elem->id != NULL)
2734 fprintf(output, "[id: '%s'] ", elem->id);
2735 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002736 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002737 /*
2738 * Default/fixed value.
2739 */
Daniel Veillard4255d502002-04-16 15:50:10 +00002740 if (elem->value != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002741 fprintf(output, " value: '%s'\n", elem->value);
2742 /*
2743 * Type.
2744 */
2745 if (elem->namedType != NULL) {
2746 fprintf(output, " type: %s ", elem->namedType);
2747 if (elem->namedTypeNs != NULL)
2748 fprintf(output, "ns %s\n", elem->namedTypeNs);
2749 else
2750 fprintf(output, "\n");
2751 }
2752 /*
2753 * Substitution group.
2754 */
2755 if (elem->substGroup != NULL) {
2756 fprintf(output, " substitutionGroup: %s ", elem->substGroup);
2757 if (elem->substGroupNs != NULL)
2758 fprintf(output, "ns %s\n", elem->substGroupNs);
2759 else
2760 fprintf(output, "\n");
2761 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002762}
2763
2764/**
2765 * xmlSchemaAnnotDump:
2766 * @output: the file output
2767 * @annot: a annotation
2768 *
2769 * Dump the annotation
2770 */
2771static void
2772xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
2773{
2774 xmlChar *content;
2775
2776 if (annot == NULL)
2777 return;
2778
2779 content = xmlNodeGetContent(annot->content);
2780 if (content != NULL) {
2781 fprintf(output, " Annot: %s\n", content);
2782 xmlFree(content);
2783 } else
2784 fprintf(output, " Annot: empty\n");
2785}
2786
2787/**
2788 * xmlSchemaTypeDump:
2789 * @output: the file output
2790 * @type: a type structure
2791 *
2792 * Dump a SchemaType structure
2793 */
2794static void
2795xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
2796{
2797 if (type == NULL) {
2798 fprintf(output, "Type: NULL\n");
2799 return;
2800 }
2801 fprintf(output, "Type: ");
2802 if (type->name != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002803 fprintf(output, "%s ", type->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00002804 else
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002805 fprintf(output, "no name ");
2806 if (type->targetNamespace != NULL)
2807 fprintf(output, "ns %s ", type->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00002808 switch (type->type) {
2809 case XML_SCHEMA_TYPE_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002810 fprintf(output, "[basic] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002811 break;
2812 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002813 fprintf(output, "[simple] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002814 break;
2815 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002816 fprintf(output, "[complex] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002817 break;
2818 case XML_SCHEMA_TYPE_SEQUENCE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002819 fprintf(output, "[sequence] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002820 break;
2821 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002822 fprintf(output, "[choice] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002823 break;
2824 case XML_SCHEMA_TYPE_ALL:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002825 fprintf(output, "[all] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002826 break;
2827 case XML_SCHEMA_TYPE_UR:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002828 fprintf(output, "[ur] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002829 break;
2830 case XML_SCHEMA_TYPE_RESTRICTION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002831 fprintf(output, "[restriction] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002832 break;
2833 case XML_SCHEMA_TYPE_EXTENSION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002834 fprintf(output, "[extension] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002835 break;
2836 default:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002837 fprintf(output, "[unknown type %d] ", type->type);
Daniel Veillard4255d502002-04-16 15:50:10 +00002838 break;
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002839 }
2840 fprintf(output, "content: ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002841 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002842 case XML_SCHEMA_CONTENT_UNKNOWN:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002843 fprintf(output, "[unknown] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002844 break;
2845 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002846 fprintf(output, "[empty] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002847 break;
2848 case XML_SCHEMA_CONTENT_ELEMENTS:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002849 fprintf(output, "[element] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002850 break;
2851 case XML_SCHEMA_CONTENT_MIXED:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002852 fprintf(output, "[mixed] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002853 break;
2854 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00002855 /* not used. */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002856 break;
2857 case XML_SCHEMA_CONTENT_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002858 fprintf(output, "[basic] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002859 break;
2860 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002861 fprintf(output, "[simple] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002862 break;
2863 case XML_SCHEMA_CONTENT_ANY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002864 fprintf(output, "[any] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002865 break;
Daniel Veillard4255d502002-04-16 15:50:10 +00002866 }
2867 fprintf(output, "\n");
2868 if ((type->minOccurs != 1) || (type->maxOccurs != 1)) {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002869 fprintf(output, " min: %d ", type->minOccurs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002870 if (type->maxOccurs >= UNBOUNDED)
2871 fprintf(output, "max: unbounded\n");
2872 else if (type->maxOccurs != 1)
2873 fprintf(output, "max: %d\n", type->maxOccurs);
2874 else
2875 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002876 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002877 if (type->base != NULL) {
2878 fprintf(output, " base type: %s", type->base);
2879 if (type->baseNs != NULL)
2880 fprintf(output, " ns %s\n", type->baseNs);
2881 else
2882 fprintf(output, "\n");
2883 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002884 if (type->annot != NULL)
2885 xmlSchemaAnnotDump(output, type->annot);
2886 if (type->subtypes != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002887 xmlSchemaTypePtr sub = type->subtypes;
Daniel Veillard4255d502002-04-16 15:50:10 +00002888
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002889 fprintf(output, " subtypes: ");
2890 while (sub != NULL) {
2891 fprintf(output, "%s ", sub->name);
2892 sub = sub->next;
2893 }
2894 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002895 }
2896
2897}
2898
2899/**
2900 * xmlSchemaDump:
2901 * @output: the file output
2902 * @schema: a schema structure
2903 *
2904 * Dump a Schema structure.
2905 */
2906void
2907xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
2908{
Daniel Veillardce682bc2004-11-05 17:22:25 +00002909 if (output == NULL)
2910 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002911 if (schema == NULL) {
2912 fprintf(output, "Schemas: NULL\n");
2913 return;
2914 }
2915 fprintf(output, "Schemas: ");
2916 if (schema->name != NULL)
2917 fprintf(output, "%s, ", schema->name);
2918 else
2919 fprintf(output, "no name, ");
2920 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00002921 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00002922 else
2923 fprintf(output, "no target namespace");
2924 fprintf(output, "\n");
2925 if (schema->annot != NULL)
2926 xmlSchemaAnnotDump(output, schema->annot);
2927
2928 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
2929 output);
2930 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002931 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00002932}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00002933
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00002934#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00002935#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00002936/**
2937 * xmlSchemaDebugDumpIDCTable:
2938 * @vctxt: the WXS validation context
2939 *
2940 * Displays the current IDC table for debug purposes.
2941 */
2942static void
2943xmlSchemaDebugDumpIDCTable(FILE * output,
2944 const xmlChar *namespaceName,
2945 const xmlChar *localName,
2946 xmlSchemaPSVIIDCBindingPtr bind)
2947{
2948 xmlChar *str = NULL, *value;
2949 xmlSchemaPSVIIDCNodePtr tab;
2950 xmlSchemaPSVIIDCKeyPtr key;
2951 int i, j, res;
2952
2953 fprintf(output, "IDC: TABLES on %s\n",
2954 xmlSchemaFormatNsUriLocal(&str, namespaceName, localName));
2955 FREE_AND_NULL(str)
2956
2957 if (bind == NULL)
2958 return;
2959 do {
2960 fprintf(output, "IDC: BINDING %s\n",
2961 xmlSchemaFormatNsUriLocal(&str, bind->definition->targetNamespace,
2962 bind->definition->name));
2963 FREE_AND_NULL(str)
2964 for (i = 0; i < bind->nbNodes; i++) {
2965 tab = bind->nodeTable[i];
2966 fprintf(output, " ( ");
2967 for (j = 0; j < bind->definition->nbFields; j++) {
2968 key = tab->keys[j];
2969 if ((key != NULL) && (key->compValue != NULL)) {
2970#ifdef IDC_VALUE_SUPPORT
2971 res = xmlSchemaGetCanonValue(key->compValue, &value);
2972#else
2973 value = xmlStrdup(BAD_CAST "dummy-value");
2974 res = 0;
2975#endif
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00002976 if (res >= 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00002977 fprintf(output, "\"%s\" ", value);
2978 else
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00002979 fprintf(output, "CANON-VALUE-FAILED ");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00002980 if (res == 0)
2981 FREE_AND_NULL(value)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00002982 } else if (key != NULL)
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00002983 fprintf(output, "(no val), ");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00002984 else
2985 fprintf(output, "(key missing), ");
2986 }
2987 fprintf(output, ")\n");
2988 }
2989 bind = bind->next;
2990 } while (bind != NULL);
2991}
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00002992#endif /* DEBUG_IDC */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00002993#endif /* IDC_ENABLED */
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002994#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +00002995
2996/************************************************************************
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002997 * *
2998 * Utilities *
2999 * *
3000 ************************************************************************/
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003001
Daniel Veillardc0826a72004-08-10 14:17:33 +00003002/**
3003 * xmlSchemaGetPropNode:
3004 * @node: the element node
3005 * @name: the name of the attribute
3006 *
3007 * Seeks an attribute with a name of @name in
3008 * no namespace.
3009 *
3010 * Returns the attribute or NULL if not present.
3011 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003012static xmlAttrPtr
Daniel Veillardc0826a72004-08-10 14:17:33 +00003013xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
Daniel Veillard01fa6152004-06-29 17:04:39 +00003014{
3015 xmlAttrPtr prop;
3016
Daniel Veillardc0826a72004-08-10 14:17:33 +00003017 if ((node == NULL) || (name == NULL))
3018 return(NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003019 prop = node->properties;
3020 while (prop != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00003021 if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
3022 return(prop);
3023 prop = prop->next;
3024 }
3025 return (NULL);
3026}
3027
3028/**
3029 * xmlSchemaGetPropNodeNs:
3030 * @node: the element node
3031 * @uri: the uri
3032 * @name: the name of the attribute
3033 *
3034 * Seeks an attribute with a local name of @name and
3035 * a namespace URI of @uri.
3036 *
3037 * Returns the attribute or NULL if not present.
3038 */
3039static xmlAttrPtr
3040xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
3041{
3042 xmlAttrPtr prop;
3043
3044 if ((node == NULL) || (name == NULL))
3045 return(NULL);
3046 prop = node->properties;
3047 while (prop != NULL) {
3048 if ((prop->ns != NULL) &&
3049 xmlStrEqual(prop->name, BAD_CAST name) &&
3050 xmlStrEqual(prop->ns->href, BAD_CAST uri))
Daniel Veillard01fa6152004-06-29 17:04:39 +00003051 return(prop);
3052 prop = prop->next;
3053 }
3054 return (NULL);
3055}
3056
3057static const xmlChar *
3058xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3059{
3060 xmlChar *val;
3061 const xmlChar *ret;
3062
3063 val = xmlNodeGetContent(node);
3064 if (val == NULL)
3065 return(NULL);
3066 ret = xmlDictLookup(ctxt->dict, val, -1);
3067 xmlFree(val);
3068 return(ret);
3069}
3070
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003071/**
3072 * xmlSchemaGetProp:
3073 * @ctxt: the parser context
3074 * @node: the node
3075 * @name: the property name
3076 *
3077 * Read a attribute value and internalize the string
3078 *
3079 * Returns the string or NULL if not present.
3080 */
3081static const xmlChar *
3082xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
3083 const char *name)
3084{
3085 xmlChar *val;
3086 const xmlChar *ret;
3087
3088 val = xmlGetProp(node, BAD_CAST name);
3089 if (val == NULL)
3090 return(NULL);
3091 ret = xmlDictLookup(ctxt->dict, val, -1);
3092 xmlFree(val);
3093 return(ret);
3094}
3095
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003096/************************************************************************
Daniel Veillard4255d502002-04-16 15:50:10 +00003097 * *
3098 * Parsing functions *
3099 * *
3100 ************************************************************************/
3101
3102/**
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003103 * xmlSchemaGetElem:
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003104 * @schema: the schema context
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003105 * @name: the element name
3106 * @ns: the element namespace
3107 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003108 * Lookup a global element declaration in the schema.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003109 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003110 * Returns the element declaration or NULL if not found.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003111 */
3112static xmlSchemaElementPtr
3113xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003114 const xmlChar * namespace)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003115{
3116 xmlSchemaElementPtr ret;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003117
3118 if ((name == NULL) || (schema == NULL))
3119 return (NULL);
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003120
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003121 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003122 if ((ret != NULL) &&
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003123 (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003124 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00003125 } else
3126 ret = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00003127 /*
3128 * This one was removed, since top level element declarations have
3129 * the target namespace specified in targetNamespace of the <schema>
3130 * information element, even if elementFormDefault is "unqualified".
3131 */
3132
3133 /* else if ((schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003134 if (xmlStrEqual(namespace, schema->targetNamespace))
3135 ret = xmlHashLookup2(schema->elemDecl, name, NULL);
3136 else
3137 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003138 if ((ret != NULL) &&
3139 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003140 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003141 }
William M. Bracke7091952004-05-11 15:09:58 +00003142 */
Daniel Veillard3646d642004-06-02 19:19:14 +00003143
William M. Brack2f2a6632004-08-20 23:09:47 +00003144 /*
3145 * Removed since imported components will be hold by the main schema only.
3146 *
Daniel Veillard3646d642004-06-02 19:19:14 +00003147 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003148 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003149 else
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003150 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003151 if (import != NULL) {
Daniel Veillardf2a12832003-11-24 13:04:35 +00003152 ret = xmlSchemaGetElem(import->schema, name, namespace, level + 1);
Daniel Veillard3646d642004-06-02 19:19:14 +00003153 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
3154 return (ret);
3155 } else
3156 ret = NULL;
3157 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003158 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003159#ifdef DEBUG
3160 if (ret == NULL) {
3161 if (namespace == NULL)
3162 fprintf(stderr, "Unable to lookup type %s", name);
3163 else
3164 fprintf(stderr, "Unable to lookup type %s:%s", name,
3165 namespace);
3166 }
3167#endif
3168 return (ret);
3169}
3170
3171/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003172 * xmlSchemaGetType:
3173 * @schema: the schemas context
3174 * @name: the type name
3175 * @ns: the type namespace
3176 *
3177 * Lookup a type in the schemas or the predefined types
3178 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003179 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +00003180 */
3181static xmlSchemaTypePtr
3182xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003183 const xmlChar * namespace)
3184{
Daniel Veillard4255d502002-04-16 15:50:10 +00003185 xmlSchemaTypePtr ret;
3186
3187 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003188 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003189 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003190 ret = xmlHashLookup2(schema->typeDecl, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003191 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003192 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003193 }
3194 ret = xmlSchemaGetPredefinedType(name, namespace);
Daniel Veillard1d913862003-11-21 00:28:39 +00003195 if (ret != NULL)
3196 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00003197 /*
3198 * Removed, since the imported components will be grafted on the
3199 * main schema only.
Daniel Veillard3646d642004-06-02 19:19:14 +00003200 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003201 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003202 else
Daniel Veillard1d913862003-11-21 00:28:39 +00003203 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003204 if (import != NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00003205 ret = xmlSchemaGetType(import->schema, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003206 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
3207 return (ret);
3208 } else
3209 ret = NULL;
3210 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003211 */
Daniel Veillard4255d502002-04-16 15:50:10 +00003212#ifdef DEBUG
3213 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003214 if (namespace == NULL)
3215 fprintf(stderr, "Unable to lookup type %s", name);
3216 else
3217 fprintf(stderr, "Unable to lookup type %s:%s", name,
3218 namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003219 }
3220#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003221 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003222}
3223
Daniel Veillard3646d642004-06-02 19:19:14 +00003224/**
3225 * xmlSchemaGetAttribute:
3226 * @schema: the context of the schema
3227 * @name: the name of the attribute
3228 * @ns: the target namespace of the attribute
3229 *
3230 * Lookup a an attribute in the schema or imported schemas
3231 *
3232 * Returns the attribute declaration or NULL if not found.
3233 */
3234static xmlSchemaAttributePtr
3235xmlSchemaGetAttribute(xmlSchemaPtr schema, const xmlChar * name,
3236 const xmlChar * namespace)
3237{
3238 xmlSchemaAttributePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00003239
3240 if ((name == NULL) || (schema == NULL))
3241 return (NULL);
3242
3243
3244 ret = xmlHashLookup2(schema->attrDecl, name, namespace);
3245 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL))
3246 return (ret);
3247 else
3248 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00003249 /*
3250 * Removed, since imported components will be hold by the main schema only.
3251 *
Daniel Veillard3646d642004-06-02 19:19:14 +00003252 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003253 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003254 else
3255 import = xmlHashLookup(schema->schemasImports, namespace);
3256 if (import != NULL) {
3257 ret = xmlSchemaGetAttribute(import->schema, name, namespace);
3258 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL)) {
3259 return (ret);
3260 } else
3261 ret = NULL;
3262 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003263 */
Daniel Veillard3646d642004-06-02 19:19:14 +00003264#ifdef DEBUG
3265 if (ret == NULL) {
3266 if (namespace == NULL)
3267 fprintf(stderr, "Unable to lookup attribute %s", name);
3268 else
3269 fprintf(stderr, "Unable to lookup attribute %s:%s", name,
3270 namespace);
3271 }
3272#endif
3273 return (ret);
3274}
3275
3276/**
3277 * xmlSchemaGetAttributeGroup:
3278 * @schema: the context of the schema
3279 * @name: the name of the attribute group
3280 * @ns: the target namespace of the attribute group
3281 *
3282 * Lookup a an attribute group in the schema or imported schemas
3283 *
3284 * Returns the attribute group definition or NULL if not found.
3285 */
3286static xmlSchemaAttributeGroupPtr
3287xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
3288 const xmlChar * namespace)
3289{
3290 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00003291
3292 if ((name == NULL) || (schema == NULL))
3293 return (NULL);
3294
3295
3296 ret = xmlHashLookup2(schema->attrgrpDecl, name, namespace);
3297 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
3298 return (ret);
3299 else
3300 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00003301 /*
3302 * Removed since imported components will be hold by the main schema only.
3303 *
Daniel Veillard3646d642004-06-02 19:19:14 +00003304 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003305 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003306 else
3307 import = xmlHashLookup(schema->schemasImports, namespace);
3308 if (import != NULL) {
3309 ret = xmlSchemaGetAttributeGroup(import->schema, name, namespace);
3310 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
3311 return (ret);
3312 else
3313 ret = NULL;
3314 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003315 */
Daniel Veillard3646d642004-06-02 19:19:14 +00003316#ifdef DEBUG
3317 if (ret == NULL) {
3318 if (namespace == NULL)
3319 fprintf(stderr, "Unable to lookup attribute group %s", name);
3320 else
3321 fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
3322 namespace);
3323 }
3324#endif
3325 return (ret);
3326}
3327
3328/**
3329 * xmlSchemaGetGroup:
3330 * @schema: the context of the schema
3331 * @name: the name of the group
3332 * @ns: the target namespace of the group
3333 *
3334 * Lookup a group in the schema or imported schemas
3335 *
3336 * Returns the group definition or NULL if not found.
3337 */
3338static xmlSchemaTypePtr
3339xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
3340 const xmlChar * namespace)
3341{
3342 xmlSchemaTypePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00003343
3344 if ((name == NULL) || (schema == NULL))
3345 return (NULL);
3346
3347
3348 ret = xmlHashLookup2(schema->groupDecl, name, namespace);
3349 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
3350 return (ret);
3351 else
3352 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00003353 /*
3354 * Removed since imported components will be hold by the main schema only.
3355 *
Daniel Veillard3646d642004-06-02 19:19:14 +00003356 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003357 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003358 else
3359 import = xmlHashLookup(schema->schemasImports, namespace);
3360 if (import != NULL) {
3361 ret = xmlSchemaGetGroup(import->schema, name, namespace);
3362 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
3363 return (ret);
3364 else
3365 ret = NULL;
3366 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003367 */
Daniel Veillard3646d642004-06-02 19:19:14 +00003368#ifdef DEBUG
3369 if (ret == NULL) {
3370 if (namespace == NULL)
3371 fprintf(stderr, "Unable to lookup group %s", name);
3372 else
3373 fprintf(stderr, "Unable to lookup group %s:%s", name,
3374 namespace);
3375 }
3376#endif
3377 return (ret);
3378}
3379
Daniel Veillard4255d502002-04-16 15:50:10 +00003380/************************************************************************
3381 * *
3382 * Parsing functions *
3383 * *
3384 ************************************************************************/
3385
3386#define IS_BLANK_NODE(n) \
3387 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content)))
3388
3389/**
3390 * xmlSchemaIsBlank:
3391 * @str: a string
3392 *
3393 * Check if a string is ignorable
3394 *
3395 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
3396 */
3397static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003398xmlSchemaIsBlank(xmlChar * str)
3399{
Daniel Veillard4255d502002-04-16 15:50:10 +00003400 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003401 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003402 while (*str != 0) {
William M. Brack76e95df2003-10-18 16:20:14 +00003403 if (!(IS_BLANK_CH(*str)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003404 return (0);
3405 str++;
Daniel Veillard4255d502002-04-16 15:50:10 +00003406 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003407 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003408}
3409
3410/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003411 * xmlSchemaAddAssembledItem:
3412 * @ctxt: a schema parser context
3413 * @schema: the schema being built
3414 * @item: the item
3415 *
3416 * Add a item to the schema's list of current items.
3417 * This is used if the schema was already constructed and
3418 * new schemata need to be added to it.
3419 * *WARNING* this interface is highly subject to change.
3420 *
3421 * Returns 0 if suceeds and -1 if an internal error occurs.
3422 */
3423static int
3424xmlSchemaAddAssembledItem(xmlSchemaParserCtxtPtr ctxt,
3425 xmlSchemaTypePtr item)
3426{
3427 static int growSize = 100;
3428 xmlSchemaAssemblePtr ass;
3429
3430 ass = ctxt->assemble;
3431 if (ass->sizeItems < 0) {
3432 /* If disabled. */
3433 return (0);
3434 }
3435 if (ass->sizeItems <= 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003436 ass->items = (void **) xmlMalloc(growSize * sizeof(xmlSchemaTypePtr));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003437 if (ass->items == NULL) {
3438 xmlSchemaPErrMemory(ctxt,
3439 "allocating new item buffer", NULL);
3440 return (-1);
3441 }
3442 ass->sizeItems = growSize;
3443 } else if (ass->sizeItems <= ass->nbItems) {
3444 ass->sizeItems *= 2;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003445 ass->items = (void **) xmlRealloc(ass->items,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003446 ass->sizeItems * sizeof(xmlSchemaTypePtr));
3447 if (ass->items == NULL) {
3448 xmlSchemaPErrMemory(ctxt,
3449 "growing item buffer", NULL);
3450 ass->sizeItems = 0;
3451 return (-1);
3452 }
3453 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003454 /* ass->items[ass->nbItems++] = (void *) item; */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003455 ((xmlSchemaTypePtr *) ass->items)[ass->nbItems++] = (void *) item;
3456 return (0);
3457}
3458
3459/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003460 * xmlSchemaAddNotation:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003461 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003462 * @schema: the schema being built
3463 * @name: the item name
3464 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00003465 * Add an XML schema annotation declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00003466 * *WARNING* this interface is highly subject to change
3467 *
3468 * Returns the new struture or NULL in case of error
3469 */
3470static xmlSchemaNotationPtr
3471xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003472 const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00003473{
3474 xmlSchemaNotationPtr ret = NULL;
3475 int val;
3476
3477 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3478 return (NULL);
3479
3480 if (schema->notaDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003481 schema->notaDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003482 if (schema->notaDecl == NULL)
3483 return (NULL);
3484
3485 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
3486 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003487 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003488 return (NULL);
3489 }
3490 memset(ret, 0, sizeof(xmlSchemaNotation));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003491 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003492 val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
3493 ret);
3494 if (val != 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00003495 /*
3496 * TODO: This should never happen, since a unique name will be computed.
3497 * If it fails, then an other internal error must have occured.
3498 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003499 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
3500 XML_SCHEMAP_REDEFINED_NOTATION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003501 "Annotation declaration '%s' is already declared.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003502 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003503 xmlFree(ret);
3504 return (NULL);
3505 }
3506 return (ret);
3507}
3508
3509
3510/**
3511 * xmlSchemaAddAttribute:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003512 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003513 * @schema: the schema being built
3514 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003515 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00003516 *
3517 * Add an XML schema Attrribute declaration
3518 * *WARNING* this interface is highly subject to change
3519 *
3520 * Returns the new struture or NULL in case of error
3521 */
3522static xmlSchemaAttributePtr
3523xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003524 const xmlChar * name, const xmlChar * namespace,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003525 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00003526{
3527 xmlSchemaAttributePtr ret = NULL;
3528 int val;
3529
3530 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3531 return (NULL);
3532
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003533#ifdef DEBUG
3534 fprintf(stderr, "Adding attribute %s\n", name);
3535 if (namespace != NULL)
3536 fprintf(stderr, " target namespace %s\n", namespace);
3537#endif
3538
Daniel Veillard4255d502002-04-16 15:50:10 +00003539 if (schema->attrDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003540 schema->attrDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003541 if (schema->attrDecl == NULL)
3542 return (NULL);
3543
3544 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
3545 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003546 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003547 return (NULL);
3548 }
3549 memset(ret, 0, sizeof(xmlSchemaAttribute));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003550 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00003551 ret->targetNamespace = namespace;
Daniel Veillard4255d502002-04-16 15:50:10 +00003552 val = xmlHashAddEntry3(schema->attrDecl, name,
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00003553 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003554 if (val != 0) {
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003555 if (topLevel) {
3556 xmlSchemaPCustomErr(ctxt,
3557 XML_SCHEMAP_REDEFINED_ATTR,
3558 NULL, NULL, node,
3559 "A global attribute declaration with the name '%s' does "
3560 "already exist", name);
3561 xmlFree(ret);
3562 return (NULL);
3563 } else {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003564 char buf[30];
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003565 /*
3566 * Using the ctxt->container for xmlHashAddEntry3 is ambigious
3567 * in the scenario:
3568 * 1. multiple top-level complex types have different target
3569 * namespaces but have the SAME NAME; this can happen if
3570 * schemata are imported
3571 * 2. those complex types contain attributes with an equal name
3572 * 3. those attributes are in no namespace
3573 * We will compute a new context string.
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003574 */
3575 snprintf(buf, 29, "#aCont%d", ctxt->counter++ + 1);
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003576 val = xmlHashAddEntry3(schema->attrDecl, name,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00003577 namespace, xmlDictLookup(ctxt->dict, BAD_CAST buf, -1), ret);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003578
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003579 if (val != 0) {
3580 xmlSchemaPCustomErr(ctxt,
3581 XML_SCHEMAP_INTERNAL,
3582 NULL, NULL, node,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003583 "Internal error: xmlSchemaAddAttribute, "
3584 "a dublicate attribute declaration with the name '%s' "
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003585 "could not be added to the hash.", name);
3586 xmlFree(ret);
3587 return (NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003588 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003589 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003590 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003591 if (ctxt->assemble != NULL)
3592 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003593 return (ret);
3594}
3595
3596/**
3597 * xmlSchemaAddAttributeGroup:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003598 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003599 * @schema: the schema being built
3600 * @name: the item name
3601 *
3602 * Add an XML schema Attrribute Group declaration
3603 *
3604 * Returns the new struture or NULL in case of error
3605 */
3606static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003607xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00003608 xmlSchemaPtr schema, const xmlChar * name,
3609 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003610{
3611 xmlSchemaAttributeGroupPtr ret = NULL;
3612 int val;
3613
3614 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3615 return (NULL);
3616
3617 if (schema->attrgrpDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003618 schema->attrgrpDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003619 if (schema->attrgrpDecl == NULL)
3620 return (NULL);
3621
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003622 ret =
3623 (xmlSchemaAttributeGroupPtr)
3624 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00003625 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003626 xmlSchemaPErrMemory(ctxt, "allocating attribute group", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003627 return (NULL);
3628 }
3629 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003630 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003631 val = xmlHashAddEntry3(schema->attrgrpDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003632 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003633 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003634 xmlSchemaPCustomErr(ctxt,
3635 XML_SCHEMAP_REDEFINED_ATTRGROUP,
3636 NULL, NULL, node,
3637 "A global attribute group definition with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003638 xmlFree(ret);
3639 return (NULL);
3640 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003641 if (ctxt->assemble != NULL)
3642 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003643 return (ret);
3644}
3645
3646/**
3647 * xmlSchemaAddElement:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003648 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003649 * @schema: the schema being built
3650 * @name: the type name
3651 * @namespace: the type namespace
3652 *
3653 * Add an XML schema Element declaration
3654 * *WARNING* this interface is highly subject to change
3655 *
3656 * Returns the new struture or NULL in case of error
3657 */
3658static xmlSchemaElementPtr
3659xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003660 const xmlChar * name, const xmlChar * namespace,
3661 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00003662{
3663 xmlSchemaElementPtr ret = NULL;
3664 int val;
3665
3666 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3667 return (NULL);
3668
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003669#ifdef DEBUG
3670 fprintf(stderr, "Adding element %s\n", name);
3671 if (namespace != NULL)
3672 fprintf(stderr, " target namespace %s\n", namespace);
3673#endif
3674
Daniel Veillard4255d502002-04-16 15:50:10 +00003675 if (schema->elemDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003676 schema->elemDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003677 if (schema->elemDecl == NULL)
3678 return (NULL);
3679
3680 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
3681 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003682 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003683 return (NULL);
3684 }
3685 memset(ret, 0, sizeof(xmlSchemaElement));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003686 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003687 val = xmlHashAddEntry3(schema->elemDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003688 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003689 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003690 if (topLevel) {
3691 xmlSchemaPCustomErr(ctxt,
3692 XML_SCHEMAP_REDEFINED_ELEMENT,
3693 NULL, NULL, node,
3694 "A global element declaration with the name '%s' does "
3695 "already exist", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003696 xmlFree(ret);
3697 return (NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00003698 } else {
3699 char buf[30];
3700
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003701 snprintf(buf, 29, "#eCont%d", ctxt->counter++ + 1);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003702 val = xmlHashAddEntry3(schema->elemDecl, name,
3703 namespace, (xmlChar *) buf, ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00003704 if (val != 0) {
3705 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003706 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00003707 NULL, NULL, node,
3708 "Internal error: xmlSchemaAddElement, "
3709 "a dublicate element declaration with the name '%s' "
3710 "could not be added to the hash.", name);
3711 xmlFree(ret);
3712 return (NULL);
3713 }
3714 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00003715
Daniel Veillard4255d502002-04-16 15:50:10 +00003716 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003717 if (ctxt->assemble != NULL)
3718 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003719 return (ret);
3720}
3721
3722/**
3723 * xmlSchemaAddType:
Daniel Veillard01fa6152004-06-29 17:04:39 +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 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00003729 * Add an XML schema item
Daniel Veillard4255d502002-04-16 15:50:10 +00003730 * *WARNING* this interface is highly subject to change
3731 *
3732 * Returns the new struture or NULL in case of error
3733 */
3734static xmlSchemaTypePtr
3735xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003736 const xmlChar * name, const xmlChar * namespace,
3737 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003738{
3739 xmlSchemaTypePtr 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 type %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->typeDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003752 schema->typeDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003753 if (schema->typeDecl == NULL)
3754 return (NULL);
3755
3756 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
3757 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003758 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003759 return (NULL);
3760 }
3761 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003762 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003763 ret->redef = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003764 val = xmlHashAddEntry2(schema->typeDecl, name, namespace, ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00003765 if (val != 0) {
3766 if (ctxt->includes == 0) {
3767 xmlSchemaPCustomErr(ctxt,
3768 XML_SCHEMAP_REDEFINED_TYPE,
3769 NULL, NULL, node,
3770 "A global type definition with the name '%s' does already exist", name);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003771 xmlFree(ret);
3772 return (NULL);
3773 } else {
3774 xmlSchemaTypePtr prev;
3775
3776 prev = xmlHashLookup2(schema->typeDecl, name, namespace);
3777 if (prev == NULL) {
3778 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003779 XML_ERR_INTERNAL_ERROR,
3780 "Internal error: xmlSchemaAddType, on type "
3781 "'%s'.\n",
3782 name, NULL);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003783 xmlFree(ret);
3784 return (NULL);
3785 }
3786 ret->redef = prev->redef;
3787 prev->redef = ret;
3788 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003789 }
3790 ret->minOccurs = 1;
3791 ret->maxOccurs = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +00003792 ret->attributeUses = NULL;
3793 ret->attributeWildcard = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003794 if (ctxt->assemble != NULL)
3795 xmlSchemaAddAssembledItem(ctxt,ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003796 return (ret);
3797}
3798
3799/**
3800 * xmlSchemaAddGroup:
3801 * @ctxt: a schema validation context
3802 * @schema: the schema being built
3803 * @name: the group name
3804 *
3805 * Add an XML schema Group definition
3806 *
3807 * Returns the new struture or NULL in case of error
3808 */
3809static xmlSchemaTypePtr
3810xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00003811 const xmlChar *name, const xmlChar *namespaceName,
3812 xmlNodePtr node)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003813{
3814 xmlSchemaTypePtr ret = NULL;
3815 int val;
3816
3817 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3818 return (NULL);
3819
3820 if (schema->groupDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003821 schema->groupDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003822 if (schema->groupDecl == NULL)
3823 return (NULL);
3824
3825 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
3826 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003827 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003828 return (NULL);
3829 }
3830 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003831 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003832 val =
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00003833 xmlHashAddEntry2(schema->groupDecl, name, namespaceName,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003834 ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003835 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003836 xmlSchemaPCustomErr(ctxt,
3837 XML_SCHEMAP_REDEFINED_GROUP,
3838 NULL, NULL, node,
3839 "A global model group definition with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003840 xmlFree(ret);
3841 return (NULL);
3842 }
3843 ret->minOccurs = 1;
3844 ret->maxOccurs = 1;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003845 if (ctxt->assemble != NULL)
3846 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003847 return (ret);
3848}
3849
Daniel Veillard3646d642004-06-02 19:19:14 +00003850/**
3851 * xmlSchemaNewWildcardNs:
3852 * @ctxt: a schema validation context
3853 *
3854 * Creates a new wildcard namespace constraint.
3855 *
3856 * Returns the new struture or NULL in case of error
3857 */
3858static xmlSchemaWildcardNsPtr
3859xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
3860{
3861 xmlSchemaWildcardNsPtr ret;
3862
3863 ret = (xmlSchemaWildcardNsPtr)
3864 xmlMalloc(sizeof(xmlSchemaWildcardNs));
3865 if (ret == NULL) {
3866 xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
3867 return (NULL);
3868 }
3869 ret->value = NULL;
3870 ret->next = NULL;
3871 return (ret);
3872}
3873
3874/**
3875 * xmlSchemaAddWildcard:
3876 * @ctxt: a schema validation context
Daniel Veillardc0826a72004-08-10 14:17:33 +00003877 * Adds a wildcard. It corresponds to a
3878 * xsd:anyAttribute and is used as storage for namespace
3879 * constraints on a xsd:any.
Daniel Veillard3646d642004-06-02 19:19:14 +00003880 *
3881 * Returns the new struture or NULL in case of error
3882 */
3883static xmlSchemaWildcardPtr
3884xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt)
3885{
3886 xmlSchemaWildcardPtr ret = NULL;
3887
3888 if (ctxt == NULL)
3889 return (NULL);
3890
3891 ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
3892 if (ret == NULL) {
3893 xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
3894 return (NULL);
3895 }
3896 memset(ret, 0, sizeof(xmlSchemaWildcard));
3897 ret->minOccurs = 1;
3898 ret->maxOccurs = 1;
3899
3900 return (ret);
3901}
3902
Daniel Veillard4255d502002-04-16 15:50:10 +00003903/************************************************************************
3904 * *
3905 * Utilities for parsing *
3906 * *
3907 ************************************************************************/
3908
3909/**
3910 * xmlGetQNameProp:
3911 * @ctxt: a schema validation context
3912 * @node: a subtree containing XML Schema informations
3913 * @name: the attribute name
3914 * @namespace: the result namespace if any
3915 *
3916 * Extract a QName Attribute value
3917 *
3918 * Returns the NCName or NULL if not found, and also update @namespace
3919 * with the namespace URI
3920 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003921static const xmlChar *
Daniel Veillard4255d502002-04-16 15:50:10 +00003922xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003923 const char *name, const xmlChar ** namespace)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003924{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003925 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00003926 xmlNsPtr ns;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003927 const xmlChar *ret, *prefix;
3928 int len;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00003929 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00003930
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003931 *namespace = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00003932 attr = xmlSchemaGetPropNode(node, name);
3933 if (attr == NULL)
3934 return (NULL);
3935 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003936
Daniel Veillard4255d502002-04-16 15:50:10 +00003937 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003938 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003939
Daniel Veillardba0153a2004-04-01 10:42:31 +00003940 if (!strchr((char *) val, ':')) {
Daniel Veillardebcdebd2004-03-05 00:15:50 +00003941 ns = xmlSearchNs(node->doc, node, 0);
3942 if (ns) {
3943 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
3944 return (val);
3945 }
3946 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003947 ret = xmlSplitQName3(val, &len);
3948 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003949 return (val);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003950 }
3951 ret = xmlDictLookup(ctxt->dict, ret, -1);
3952 prefix = xmlDictLookup(ctxt->dict, val, len);
Daniel Veillard4255d502002-04-16 15:50:10 +00003953
3954 ns = xmlSearchNs(node->doc, node, prefix);
3955 if (ns == NULL) {
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00003956 xmlSchemaPSimpleTypeErr(ctxt, XML_SCHEMAP_PREFIX_UNDEFINED,
3957 NULL, NULL, (xmlNodePtr) attr,
3958 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, val,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003959 "The QName value '%s' has no corresponding namespace "
3960 "declaration in scope", val, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003961 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003962 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003963 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003964 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003965}
3966
3967/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00003968 * xmlSchemaPValAttrNodeQNameValue:
3969 * @ctxt: a schema parser context
3970 * @schema: the schema context
3971 * @ownerDes: the designation of the parent element
3972 * @ownerItem: the parent as a schema object
3973 * @value: the QName value
3974 * @local: the resulting local part if found, the attribute value otherwise
3975 * @uri: the resulting namespace URI if found
3976 *
3977 * Extracts the local name and the URI of a QName value and validates it.
3978 * This one is intended to be used on attribute values that
3979 * should resolve to schema components.
3980 *
3981 * Returns 0, in case the QName is valid, a positive error code
3982 * if not valid and -1 if an internal error occurs.
3983 */
3984static int
3985xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
3986 xmlSchemaPtr schema,
3987 xmlChar **ownerDes,
3988 xmlSchemaTypePtr ownerItem,
3989 xmlAttrPtr attr,
3990 const xmlChar *value,
3991 const xmlChar **uri,
3992 const xmlChar **prefix,
3993 const xmlChar **local)
3994{
3995 const xmlChar *pref;
3996 xmlNsPtr ns;
3997 int len, ret;
3998
3999 *uri = NULL;
4000 *local = NULL;
4001 if (prefix != 0)
4002 *prefix = NULL;
4003 ret = xmlValidateQName(value, 1);
4004 if (ret > 0) {
4005 xmlSchemaPSimpleTypeErr(ctxt,
4006 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4007 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004008 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
4009 "QName", value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004010 NULL, NULL, NULL);
4011 *local = value;
4012 return (ctxt->err);
4013 } else if (ret < 0)
4014 return (-1);
4015
4016 if (!strchr((char *) value, ':')) {
4017 ns = xmlSearchNs(attr->doc, attr->parent, 0);
4018 if (ns)
4019 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
4020 else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
4021 /*
4022 * This one takes care of included schemas with no
4023 * target namespace.
4024 */
4025 *uri = schema->targetNamespace;
4026 }
4027 *local = value;
4028 return (0);
4029 }
4030 /*
4031 * At this point xmlSplitQName3 has to return a local name.
4032 */
4033 *local = xmlSplitQName3(value, &len);
4034 *local = xmlDictLookup(ctxt->dict, *local, -1);
4035 pref = xmlDictLookup(ctxt->dict, value, len);
4036 if (prefix != 0)
4037 *prefix = pref;
4038 ns = xmlSearchNs(attr->doc, attr->parent, pref);
4039 if (ns == NULL) {
4040 xmlSchemaPSimpleTypeErr(ctxt,
4041 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4042 ownerDes, ownerItem, (xmlNodePtr) attr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004043 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), "QName", value,
4044 "The QName value '%s' has no corresponding namespace "
4045 "declaration in scope", value, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004046 return (ctxt->err);
4047 } else {
4048 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
4049 }
4050 return (0);
4051}
4052
4053/**
4054 * xmlSchemaPValAttrNodeQName:
4055 * @ctxt: a schema parser context
4056 * @schema: the schema context
4057 * @ownerDes: the designation of the owner element
4058 * @ownerItem: the owner as a schema object
4059 * @attr: the attribute node
4060 * @local: the resulting local part if found, the attribute value otherwise
4061 * @uri: the resulting namespace URI if found
4062 *
4063 * Extracts and validates the QName of an attribute value.
4064 * This one is intended to be used on attribute values that
4065 * should resolve to schema components.
4066 *
4067 * Returns 0, in case the QName is valid, a positive error code
4068 * if not valid and -1 if an internal error occurs.
4069 */
4070static int
4071xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
4072 xmlSchemaPtr schema,
4073 xmlChar **ownerDes,
4074 xmlSchemaTypePtr ownerItem,
4075 xmlAttrPtr attr,
4076 const xmlChar **uri,
4077 const xmlChar **prefix,
4078 const xmlChar **local)
4079{
4080 const xmlChar *value;
4081
4082 value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4083 return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
4084 ownerDes, ownerItem, attr, value, uri, prefix, local));
4085}
4086
4087/**
4088 * xmlSchemaPValAttrQName:
4089 * @ctxt: a schema parser context
4090 * @schema: the schema context
4091 * @ownerDes: the designation of the parent element
4092 * @ownerItem: the owner as a schema object
4093 * @ownerElem: the parent node of the attribute
4094 * @name: the name of the attribute
4095 * @local: the resulting local part if found, the attribute value otherwise
4096 * @uri: the resulting namespace URI if found
4097 *
4098 * Extracts and validates the QName of an attribute value.
4099 *
4100 * Returns 0, in case the QName is valid, a positive error code
4101 * if not valid and -1 if an internal error occurs.
4102 */
4103static int
4104xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
4105 xmlSchemaPtr schema,
4106 xmlChar **ownerDes,
4107 xmlSchemaTypePtr ownerItem,
4108 xmlNodePtr ownerElem,
4109 const char *name,
4110 const xmlChar **uri,
4111 const xmlChar **prefix,
4112 const xmlChar **local)
4113{
4114 xmlAttrPtr attr;
4115
4116 attr = xmlSchemaGetPropNode(ownerElem, name);
4117 if (attr == NULL) {
4118 *local = NULL;
4119 *uri = NULL;
4120 return (0);
4121 }
4122 return (xmlSchemaPValAttrNodeQName(ctxt, schema,
4123 ownerDes, ownerItem, attr, uri, prefix, local));
4124}
4125
4126/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004127 * xmlGetMaxOccurs:
4128 * @ctxt: a schema validation context
4129 * @node: a subtree containing XML Schema informations
4130 *
4131 * Get the maxOccurs property
4132 *
4133 * Returns the default if not found, or the value
4134 */
4135static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004136xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
4137 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004138{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004139 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00004140 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004141 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00004142
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004143 attr = xmlSchemaGetPropNode(node, "maxOccurs");
4144 if (attr == NULL)
4145 return (def);
4146 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00004147
4148 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004149 if (max != UNBOUNDED) {
4150 xmlSchemaPSimpleTypeErr(ctxt,
4151 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4152 /* XML_SCHEMAP_INVALID_MINOCCURS, */
4153 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
4154 val, NULL, NULL, NULL);
4155 return (def);
4156 } else
4157 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00004158 }
4159
4160 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00004161 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004162 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004163 if (*cur == 0) {
4164 xmlSchemaPSimpleTypeErr(ctxt,
4165 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4166 /* XML_SCHEMAP_INVALID_MINOCCURS, */
4167 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
4168 val, NULL, NULL, NULL);
4169 return (def);
4170 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004171 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004172 ret = ret * 10 + (*cur - '0');
4173 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00004174 }
William M. Brack76e95df2003-10-18 16:20:14 +00004175 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004176 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004177 /*
4178 * TODO: Restrict the maximal value to Integer.
4179 */
4180 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
4181 xmlSchemaPSimpleTypeErr(ctxt,
4182 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4183 /* XML_SCHEMAP_INVALID_MINOCCURS, */
4184 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
4185 val, NULL, NULL, NULL);
4186 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00004187 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004188 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004189}
4190
4191/**
4192 * xmlGetMinOccurs:
4193 * @ctxt: a schema validation context
4194 * @node: a subtree containing XML Schema informations
4195 *
4196 * Get the minOccurs property
4197 *
4198 * Returns the default if not found, or the value
4199 */
4200static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004201xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
4202 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004203{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004204 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00004205 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004206 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00004207
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004208 attr = xmlSchemaGetPropNode(node, "minOccurs");
4209 if (attr == NULL)
4210 return (def);
4211 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00004212 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00004213 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004214 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004215 if (*cur == 0) {
4216 xmlSchemaPSimpleTypeErr(ctxt,
4217 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4218 /* XML_SCHEMAP_INVALID_MINOCCURS, */
4219 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
4220 val, NULL, NULL, NULL);
4221 return (def);
4222 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004223 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004224 ret = ret * 10 + (*cur - '0');
4225 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00004226 }
William M. Brack76e95df2003-10-18 16:20:14 +00004227 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004228 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004229 /*
4230 * TODO: Restrict the maximal value to Integer.
4231 */
4232 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
4233 xmlSchemaPSimpleTypeErr(ctxt,
4234 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4235 /* XML_SCHEMAP_INVALID_MINOCCURS, */
4236 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
4237 val, NULL, NULL, NULL);
4238 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00004239 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004240 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004241}
4242
4243/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004244 * xmlSchemaPGetBoolNodeValue:
4245 * @ctxt: a schema validation context
4246 * @ownerDes: owner designation
4247 * @ownerItem: the owner as a schema item
4248 * @node: the node holding the value
4249 *
4250 * Converts a boolean string value into 1 or 0.
4251 *
4252 * Returns 0 or 1.
4253 */
4254static int
4255xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
4256 xmlChar **ownerDes,
4257 xmlSchemaTypePtr ownerItem,
4258 xmlNodePtr node)
4259{
4260 xmlChar *value = NULL;
4261 int res = 0;
4262
4263 value = xmlNodeGetContent(node);
4264 /*
4265 * 3.2.2.1 Lexical representation
4266 * An instance of a datatype that is defined as ·boolean·
4267 * can have the following legal literals {true, false, 1, 0}.
4268 */
4269 if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
4270 res = 1;
4271 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
4272 res = 0;
4273 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
4274 res = 1;
4275 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
4276 res = 0;
4277 else {
4278 xmlSchemaPSimpleTypeErr(ctxt,
4279 XML_SCHEMAP_INVALID_BOOLEAN,
4280 ownerDes, ownerItem, node,
4281 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
4282 "(1 | 0 | true | false)", BAD_CAST value,
4283 NULL, NULL, NULL);
4284 }
4285 if (value != NULL)
4286 xmlFree(value);
4287 return (res);
4288}
4289
4290/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004291 * xmlGetBooleanProp:
4292 * @ctxt: a schema validation context
4293 * @node: a subtree containing XML Schema informations
4294 * @name: the attribute name
4295 * @def: the default value
4296 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00004297 * Evaluate if a boolean property is set
Daniel Veillard4255d502002-04-16 15:50:10 +00004298 *
4299 * Returns the default if not found, 0 if found to be false,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004300 * 1 if found to be true
Daniel Veillard4255d502002-04-16 15:50:10 +00004301 */
4302static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00004303xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
4304 xmlChar **ownerDes,
4305 xmlSchemaTypePtr ownerItem,
4306 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004307 const char *name, int def)
4308{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004309 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00004310
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004311 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004312 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004313 return (def);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004314 /*
4315 * 3.2.2.1 Lexical representation
4316 * An instance of a datatype that is defined as ·boolean·
4317 * can have the following legal literals {true, false, 1, 0}.
4318 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004319 if (xmlStrEqual(val, BAD_CAST "true"))
4320 def = 1;
4321 else if (xmlStrEqual(val, BAD_CAST "false"))
4322 def = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004323 else if (xmlStrEqual(val, BAD_CAST "1"))
4324 def = 1;
4325 else if (xmlStrEqual(val, BAD_CAST "0"))
4326 def = 0;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00004327 else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004328 xmlSchemaPSimpleTypeErr(ctxt,
4329 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00004330 ownerDes, ownerItem,
4331 (xmlNodePtr) xmlSchemaGetPropNode(node, name),
William M. Brack2f2a6632004-08-20 23:09:47 +00004332 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
4333 "(1 | 0 | true | false)", val, NULL, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004334 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004335 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00004336}
4337
4338/************************************************************************
4339 * *
4340 * Shema extraction from an Infoset *
4341 * *
4342 ************************************************************************/
4343static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
4344 ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00004345 xmlNodePtr node,
4346 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004347static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
4348 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00004349 xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00004350 xmlNodePtr node,
4351 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004352static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
4353 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00004354 xmlSchemaPtr schema,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00004355 xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00004356static xmlSchemaTypePtr xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt,
4357 xmlSchemaPtr schema,
4358 xmlNodePtr node);
4359static xmlSchemaTypePtr xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt,
4360 xmlSchemaPtr schema,
4361 xmlNodePtr node);
4362static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
4363 ctxt,
4364 xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00004365 xmlNodePtr node,
4366 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00004367static xmlSchemaAttributeGroupPtr
4368xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00004369 xmlSchemaPtr schema, xmlNodePtr node,
4370 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00004371static xmlSchemaTypePtr xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt,
4372 xmlSchemaPtr schema,
4373 xmlNodePtr node);
4374static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
4375 xmlSchemaPtr schema,
4376 xmlNodePtr node);
Daniel Veillard3646d642004-06-02 19:19:14 +00004377static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004378xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
4379 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00004380
4381/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004382 * xmlSchemaPValAttrNodeValue:
Daniel Veillard01fa6152004-06-29 17:04:39 +00004383 *
4384 * @ctxt: a schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00004385 * @ownerDes: the designation of the parent element
4386 * @ownerItem: the schema object owner if existent
4387 * @attr: the schema attribute node being validated
4388 * @value: the value
4389 * @type: the built-in type to be validated against
Daniel Veillard01fa6152004-06-29 17:04:39 +00004390 *
4391 * Validates a value against the given built-in type.
4392 * This one is intended to be used internally for validation
4393 * of schema attribute values during parsing of the schema.
4394 *
4395 * Returns 0 if the value is valid, a positive error code
4396 * number otherwise and -1 in case of an internal or API error.
4397 */
4398static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00004399xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr ctxt,
4400 xmlChar **ownerDes,
4401 xmlSchemaTypePtr ownerItem,
4402 xmlAttrPtr attr,
4403 const xmlChar *value,
4404 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +00004405{
Daniel Veillard01fa6152004-06-29 17:04:39 +00004406
Daniel Veillardc0826a72004-08-10 14:17:33 +00004407 int ret = 0;
4408
4409 /*
4410 * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
4411 * one is really meant to be used internally, so better not.
4412 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00004413 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00004414 return (-1);
4415 if (type->type != XML_SCHEMA_TYPE_BASIC) {
4416 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004417 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004418 "Internal error: xmlSchemaPValAttrNodeValue, the given "
Daniel Veillardc0826a72004-08-10 14:17:33 +00004419 "type '%s' is not a built-in type.\n",
4420 type->name, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00004421 return (-1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004422 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00004423 switch (type->builtInType) {
4424 case XML_SCHEMAS_NCNAME:
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004425 case XML_SCHEMAS_QNAME:
4426 case XML_SCHEMAS_ANYURI:
4427 case XML_SCHEMAS_TOKEN:
4428 case XML_SCHEMAS_LANGUAGE:
4429 ret = xmlSchemaValPredefTypeNode(type, value, NULL, (xmlNodePtr) attr);
4430 break;
4431
4432 /*
4433 case XML_SCHEMAS_NCNAME:
Daniel Veillard01fa6152004-06-29 17:04:39 +00004434 ret = xmlValidateNCName(value, 1);
4435 break;
4436 case XML_SCHEMAS_QNAME:
Daniel Veillardc0826a72004-08-10 14:17:33 +00004437 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004438 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004439 "Internal error: xmlSchemaPvalueAttrNode, use "
4440 "the function xmlSchemaExtractSchemaQNamePropvalueidated "
4441 "for extracting QName valueues instead.\n",
4442 NULL, NULL);
4443 return (-1);
4444 case XML_SCHEMAS_ANYURI:
4445 if (value != NULL) {
4446 xmlURIPtr uri = xmlParseURI((const char *) value);
4447 if (uri == NULL)
4448 ret = 1;
4449 else
4450 xmlFreeURI(uri);
Daniel Veillard01fa6152004-06-29 17:04:39 +00004451 }
4452 break;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004453 case XML_SCHEMAS_TOKEN: {
4454 const xmlChar *cur = value;
4455
4456 if (IS_BLANK_CH(*cur)) {
4457 ret = 1;
4458 } else while (*cur != 0) {
4459 if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) {
4460 ret = 1;
4461 break;
4462 } else if (*cur == ' ') {
4463 cur++;
4464 if ((*cur == 0) || (*cur == ' ')) {
4465 ret = 1;
4466 break;
4467 }
4468 } else {
4469 cur++;
4470 }
4471 }
4472 }
4473 break;
4474 case XML_SCHEMAS_LANGUAGE:
4475 if (xmlCheckLanguageID(value) != 1)
4476 ret = 1;
4477 break;
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004478 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00004479 default: {
4480 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004481 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004482 "Internal error: xmlSchemaPValAttrNodeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +00004483 "valueidation using the type '%s' is not implemented "
4484 "yet.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +00004485 type->name, NULL);
4486 return (-1);
4487 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004488 }
4489 /*
4490 * TODO: Should we use the S4S error codes instead?
4491 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004492 if (ret < 0) {
4493 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
4494 XML_SCHEMAP_INTERNAL,
4495 "Internal error: xmlSchemaPValAttrNodeValue, "
4496 "failed to validate a schema attribute value.\n",
4497 NULL, NULL);
4498 return (-1);
4499 } else if (ret > 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004500 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
4501 xmlSchemaPSimpleTypeErr(ctxt,
4502 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2,
4503 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004504 type, NULL, value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004505 NULL, NULL, NULL);
4506 return(XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2);
4507 } else {
4508 xmlSchemaPSimpleTypeErr(ctxt,
4509 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
4510 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004511 type, NULL, value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004512 NULL, NULL, NULL);
4513 return(XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
4514 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00004515 }
4516 return (ret);
4517}
4518
4519/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00004520 * xmlSchemaPValAttrNode:
4521 *
4522 * @ctxt: a schema parser context
4523 * @ownerDes: the designation of the parent element
4524 * @ownerItem: the schema object owner if existent
4525 * @attr: the schema attribute node being validated
4526 * @type: the built-in type to be validated against
4527 * @value: the resulting value if any
4528 *
4529 * Extracts and validates a value against the given built-in type.
4530 * This one is intended to be used internally for validation
4531 * of schema attribute values during parsing of the schema.
4532 *
4533 * Returns 0 if the value is valid, a positive error code
4534 * number otherwise and -1 in case of an internal or API error.
4535 */
4536static int
4537xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
4538 xmlChar **ownerDes,
4539 xmlSchemaTypePtr ownerItem,
4540 xmlAttrPtr attr,
4541 xmlSchemaTypePtr type,
4542 const xmlChar **value)
4543{
4544 const xmlChar *val;
4545
4546 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
4547 return (-1);
4548
4549 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4550 if (value != NULL)
4551 *value = val;
4552
4553 return (xmlSchemaPValAttrNodeValue(ctxt, ownerDes, ownerItem, attr,
4554 val, type));
4555}
4556
4557/**
4558 * xmlSchemaPValAttr:
4559 *
4560 * @ctxt: a schema parser context
4561 * @node: the element node of the attribute
4562 * @ownerDes: the designation of the parent element
4563 * @ownerItem: the schema object owner if existent
4564 * @ownerElem: the owner element node
4565 * @name: the name of the schema attribute node
4566 * @type: the built-in type to be validated against
4567 * @value: the resulting value if any
4568 *
4569 * Extracts and validates a value against the given built-in type.
4570 * This one is intended to be used internally for validation
4571 * of schema attribute values during parsing of the schema.
4572 *
4573 * Returns 0 if the value is valid, a positive error code
4574 * number otherwise and -1 in case of an internal or API error.
4575 */
4576static int
4577xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
4578 xmlChar **ownerDes,
4579 xmlSchemaTypePtr ownerItem,
4580 xmlNodePtr ownerElem,
4581 const char *name,
4582 xmlSchemaTypePtr type,
4583 const xmlChar **value)
4584{
4585 xmlAttrPtr attr;
4586
4587 if ((ctxt == NULL) || (type == NULL)) {
4588 if (value != NULL)
4589 *value = NULL;
4590 return (-1);
4591 }
4592 if (type->type != XML_SCHEMA_TYPE_BASIC) {
4593 if (value != NULL)
4594 *value = NULL;
4595 xmlSchemaPErr(ctxt, ownerElem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004596 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004597 "Internal error: xmlSchemaPValAttr, the given "
4598 "type '%s' is not a built-in type.\n",
4599 type->name, NULL);
4600 return (-1);
4601 }
4602 attr = xmlSchemaGetPropNode(ownerElem, name);
4603 if (attr == NULL) {
4604 if (value != NULL)
4605 *value = NULL;
4606 return (0);
4607 }
4608 return (xmlSchemaPValAttrNode(ctxt, ownerDes, ownerItem, attr,
4609 type, value));
4610}
4611/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004612 * xmlSchemaParseAttrDecls:
4613 * @ctxt: a schema validation context
4614 * @schema: the schema being built
4615 * @node: a subtree containing XML Schema informations
4616 * @type: the hosting type
4617 *
4618 * parse a XML schema attrDecls declaration corresponding to
4619 * <!ENTITY % attrDecls
4620 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
4621 */
4622static xmlNodePtr
4623xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4624 xmlNodePtr child, xmlSchemaTypePtr type)
4625{
4626 xmlSchemaAttributePtr lastattr, attr;
4627
4628 lastattr = NULL;
4629 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004630 (IS_SCHEMA(child, "attributeGroup"))) {
4631 attr = NULL;
4632 if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00004633 attr = xmlSchemaParseAttribute(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004634 } else if (IS_SCHEMA(child, "attributeGroup")) {
4635 attr = (xmlSchemaAttributePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00004636 xmlSchemaParseAttributeGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004637 }
4638 if (attr != NULL) {
4639 if (lastattr == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00004640 if (type->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
4641 ((xmlSchemaAttributeGroupPtr) type)->attributes = attr;
4642 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004643 type->attributes = attr;
4644 lastattr = attr;
4645 } else {
4646 lastattr->next = attr;
4647 lastattr = attr;
4648 }
4649 }
4650 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004651 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004652 return (child);
Daniel Veillard4255d502002-04-16 15:50:10 +00004653}
4654
4655/**
4656 * xmlSchemaParseAnnotation:
4657 * @ctxt: a schema validation context
4658 * @schema: the schema being built
4659 * @node: a subtree containing XML Schema informations
4660 *
4661 * parse a XML schema Attrribute declaration
4662 * *WARNING* this interface is highly subject to change
4663 *
William M. Bracke7091952004-05-11 15:09:58 +00004664 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00004665 * 1 in case of success.
4666 */
4667static xmlSchemaAnnotPtr
4668xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4669 xmlNodePtr node)
4670{
4671 xmlSchemaAnnotPtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004672 xmlNodePtr child = NULL;
4673 xmlAttrPtr attr;
4674 int barked = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00004675
Daniel Veillardc0826a72004-08-10 14:17:33 +00004676 /*
4677 * INFO: S4S completed.
4678 */
4679 /*
4680 * id = ID
4681 * {any attributes with non-schema namespace . . .}>
4682 * Content: (appinfo | documentation)*
4683 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004684 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4685 return (NULL);
4686 ret = xmlSchemaNewAnnot(ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004687 attr = node->properties;
4688 while (attr != NULL) {
4689 if (((attr->ns == NULL) &&
4690 (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
4691 ((attr->ns != NULL) &&
4692 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
4693
4694 xmlSchemaPIllegalAttrErr(ctxt,
4695 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4696 NULL, NULL, attr);
4697 }
4698 attr = attr->next;
4699 }
4700 /* TODO: Check id. */
4701
4702 /*
4703 * And now for the children...
4704 */
4705 child = node->children;
4706 while (child != NULL) {
4707 if (IS_SCHEMA(child, "appinfo")) {
4708 /* TODO: make available the content of "appinfo". */
4709 /*
4710 * source = anyURI
4711 * {any attributes with non-schema namespace . . .}>
4712 * Content: ({any})*
4713 */
4714 attr = child->properties;
4715 while (attr != NULL) {
4716 if (((attr->ns == NULL) &&
4717 (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
4718 ((attr->ns != NULL) &&
4719 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004720
Daniel Veillardc0826a72004-08-10 14:17:33 +00004721 xmlSchemaPIllegalAttrErr(ctxt,
4722 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4723 NULL, NULL, attr);
4724 }
4725 attr = attr->next;
4726 }
4727 xmlSchemaPValAttr(ctxt, NULL, NULL, child, "source",
4728 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
4729 child = child->next;
4730 } else if (IS_SCHEMA(child, "documentation")) {
4731 /* TODO: make available the content of "documentation". */
4732 /*
4733 * source = anyURI
4734 * {any attributes with non-schema namespace . . .}>
4735 * Content: ({any})*
4736 */
4737 attr = child->properties;
4738 while (attr != NULL) {
4739 if (attr->ns == NULL) {
4740 if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
4741 xmlSchemaPIllegalAttrErr(ctxt,
4742 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4743 NULL, NULL, attr);
4744 }
4745 } else {
4746 if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
4747 (xmlStrEqual(attr->name, BAD_CAST "lang") &&
4748 (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
4749
4750 xmlSchemaPIllegalAttrErr(ctxt,
4751 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4752 NULL, NULL, attr);
4753 }
4754 }
4755 attr = attr->next;
4756 }
4757 /*
4758 * Attribute "xml:lang".
4759 */
4760 attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
4761 if (attr != NULL)
4762 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
4763 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
4764 child = child->next;
4765 } else {
4766 if (!barked)
4767 xmlSchemaPContentErr(ctxt,
4768 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
4769 NULL, NULL, node, child, NULL, "(appinfo | documentation)*");
4770 barked = 1;
4771 child = child->next;
4772 }
4773 }
4774
Daniel Veillard4255d502002-04-16 15:50:10 +00004775 return (ret);
4776}
4777
4778/**
4779 * xmlSchemaParseFacet:
4780 * @ctxt: a schema validation context
4781 * @schema: the schema being built
4782 * @node: a subtree containing XML Schema informations
4783 *
4784 * parse a XML schema Facet declaration
4785 * *WARNING* this interface is highly subject to change
4786 *
4787 * Returns the new type structure or NULL in case of error
4788 */
4789static xmlSchemaFacetPtr
4790xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004791 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004792{
4793 xmlSchemaFacetPtr facet;
4794 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004795 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00004796
4797 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4798 return (NULL);
4799
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004800 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004801 if (facet == NULL) {
4802 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
4803 return (NULL);
4804 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004805 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004806 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00004807 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004808 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
4809 "Facet %s has no value\n", node->name, NULL);
4810 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00004811 return (NULL);
4812 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004813 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004814 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004815 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004816 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004817 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004818 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004819 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004820 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004821 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004822 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004823 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004824 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004825 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004826 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004827 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004828 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004829 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004830 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004831 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004832 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004833 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004834 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
4835 } else if (IS_SCHEMA(node, "minLength")) {
4836 facet->type = XML_SCHEMA_FACET_MINLENGTH;
4837 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004838 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
4839 "Unknown facet type %s\n", node->name, NULL);
4840 xmlSchemaFreeFacet(facet);
4841 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004842 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004843 facet->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00004844 facet->value = value;
Daniel Veillard01fa6152004-06-29 17:04:39 +00004845 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
4846 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
4847 const xmlChar *fixed;
4848
4849 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
4850 if (fixed != NULL) {
4851 if (xmlStrEqual(fixed, BAD_CAST "true"))
4852 facet->fixed = 1;
4853 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004854 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004855 child = node->children;
4856
4857 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004858 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4859 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004860 }
4861 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004862 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
4863 "Facet %s has unexpected child content\n",
4864 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004865 }
4866 return (facet);
4867}
4868
4869/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00004870 * xmlSchemaParseWildcardNs:
4871 * @ctxt: a schema parser context
4872 * @wildc: the wildcard, already created
4873 * @node: a subtree containing XML Schema informations
4874 *
4875 * Parses the attribute "processContents" and "namespace"
4876 * of a xsd:anyAttribute and xsd:any.
4877 * *WARNING* this interface is highly subject to change
4878 *
4879 * Returns 0 if everything goes fine, a positive error code
4880 * if something is not valid and -1 if an internal error occurs.
4881 */
4882static int
4883xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
4884 xmlSchemaPtr schema,
4885 xmlSchemaWildcardPtr wildc,
4886 xmlNodePtr node)
4887{
4888 const xmlChar *pc, *ns, *dictnsItem;
4889 int ret = 0;
4890 xmlChar *nsItem;
4891 xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
4892 xmlAttrPtr attr;
4893
4894 pc = xmlSchemaGetProp(ctxt, node, "processContents");
4895 if ((pc == NULL)
4896 || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
4897 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
4898 } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
4899 wildc->processContents = XML_SCHEMAS_ANY_SKIP;
4900 } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
4901 wildc->processContents = XML_SCHEMAS_ANY_LAX;
4902 } else {
4903 xmlSchemaPSimpleTypeErr(ctxt,
4904 XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD,
4905 NULL, NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00004906 NULL, "(strict | skip | lax)", pc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004907 NULL, NULL, NULL);
4908 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
4909 ret = XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD;
4910 }
4911 /*
4912 * Build the namespace constraints.
4913 */
4914 attr = xmlSchemaGetPropNode(node, "namespace");
4915 ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4916 if ((ns == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
4917 wildc->any = 1;
4918 else if (xmlStrEqual(ns, BAD_CAST "##other")) {
4919 wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
4920 if (wildc->negNsSet == NULL) {
4921 return (-1);
4922 }
4923 wildc->negNsSet->value = schema->targetNamespace;
4924 } else {
4925 const xmlChar *end, *cur;
4926
4927 cur = ns;
4928 do {
4929 while (IS_BLANK_CH(*cur))
4930 cur++;
4931 end = cur;
4932 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
4933 end++;
4934 if (end == cur)
4935 break;
4936 nsItem = xmlStrndup(cur, end - cur);
4937 if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
4938 (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
4939 xmlSchemaPSimpleTypeErr(ctxt,
4940 XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
4941 NULL, NULL, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004942 NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004943 "((##any | ##other) | List of (anyURI | "
4944 "(##targetNamespace | ##local)))",
4945 nsItem, NULL, NULL, NULL);
4946 ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
4947 } else {
4948 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
4949 dictnsItem = schema->targetNamespace;
4950 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
4951 dictnsItem = NULL;
4952 } else {
4953 /*
4954 * Validate the item (anyURI).
4955 */
4956 xmlSchemaPValAttrNodeValue(ctxt, NULL, NULL, attr,
4957 nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
4958 dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
4959 }
4960 /*
4961 * Avoid dublicate namespaces.
4962 */
4963 tmp = wildc->nsSet;
4964 while (tmp != NULL) {
4965 if (dictnsItem == tmp->value)
4966 break;
4967 tmp = tmp->next;
4968 }
4969 if (tmp == NULL) {
4970 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
4971 if (tmp == NULL) {
4972 xmlFree(nsItem);
4973 return (-1);
4974 }
4975 tmp->value = dictnsItem;
4976 tmp->next = NULL;
4977 if (wildc->nsSet == NULL)
4978 wildc->nsSet = tmp;
4979 else
4980 lastNs->next = tmp;
4981 lastNs = tmp;
4982 }
4983
4984 }
4985 xmlFree(nsItem);
4986 cur = end;
4987 } while (*cur != 0);
4988 }
4989 return (ret);
4990}
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004991
4992static int
4993xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
4994 xmlSchemaTypePtr item,
4995 xmlNodePtr node,
4996 int minOccurs,
4997 int maxOccurs) {
4998
4999 if (maxOccurs != UNBOUNDED) {
5000 /*
5001 * TODO: Maby we should better not create the particle,
5002 * if min/max is invalid, since it could confuse the build of the
5003 * content model.
5004 */
5005 /*
5006 * 3.9.6 Schema Component Constraint: Particle Correct
5007 *
5008 */
5009 if (maxOccurs < 1) {
5010 /*
5011 * 2.2 {max occurs} must be greater than or equal to 1.
5012 */
5013 xmlSchemaPCustomAttrErr(ctxt,
5014 XML_SCHEMAP_P_PROPS_CORRECT_2_2,
5015 NULL, item, xmlSchemaGetPropNode(node, "maxOccurs"),
5016 "The value must be greater than or equal to 1");
5017 return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
5018 } else if (minOccurs > maxOccurs) {
5019 /*
5020 * 2.1 {min occurs} must not be greater than {max occurs}.
5021 */
5022 xmlSchemaPCustomAttrErr(ctxt,
5023 XML_SCHEMAP_P_PROPS_CORRECT_2_1,
5024 NULL, item, xmlSchemaGetPropNode(node, "minOccurs"),
5025 "The value must not be greater than the value of 'maxOccurs'");
5026 return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
5027 }
5028 }
5029 return (0);
5030}
5031
Daniel Veillardc0826a72004-08-10 14:17:33 +00005032/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005033 * xmlSchemaParseAny:
5034 * @ctxt: a schema validation context
5035 * @schema: the schema being built
5036 * @node: a subtree containing XML Schema informations
5037 *
5038 * parse a XML schema Any declaration
5039 * *WARNING* this interface is highly subject to change
5040 *
5041 * Returns the new type structure or NULL in case of error
5042 */
5043static xmlSchemaTypePtr
5044xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5045 xmlNodePtr node)
5046{
5047 xmlSchemaTypePtr type;
5048 xmlNodePtr child = NULL;
5049 xmlChar name[30];
Daniel Veillardc0826a72004-08-10 14:17:33 +00005050 xmlSchemaWildcardPtr wildc;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005051 int minOccurs, maxOccurs;
Daniel Veillard4255d502002-04-16 15:50:10 +00005052
5053 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5054 return (NULL);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005055 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
5056 "(nonNegativeInteger | unbounded)");
5057 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
5058 "nonNegativeInteger");
5059 if ((minOccurs == 0) && (maxOccurs == 0))
5060 return (NULL);
5061
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005062 snprintf((char *) name, 30, "#any%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00005063 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005064 if (type == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005065 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005066 type->node = node;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005067 type->type = XML_SCHEMA_TYPE_ANY;
5068
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005069 /*
5070 * TODO: Use a particle component here.
5071 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00005072 wildc = xmlSchemaAddWildcard(ctxt);
5073 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005074 * Check min/max sanity.
5075 */
5076 type->maxOccurs = maxOccurs;
5077 type->minOccurs = minOccurs;
5078 xmlSchemaPCheckParticleCorrect_2(ctxt, type,
5079 node, type->minOccurs, type->maxOccurs);
5080 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005081 * This is not nice, since it is won't be used as a attribute wildcard,
5082 * but better than adding a field to the structure.
5083 */
5084 type->attributeWildcard = wildc;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005085 xmlSchemaParseWildcardNs(ctxt, schema, wildc, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005086 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00005087 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005088 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5089 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005090 }
5091 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005092 xmlSchemaPErr2(ctxt, node, child,
5093 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
5094 "Sequence %s has unexpected content\n", type->name,
5095 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005096 }
5097
5098 return (type);
5099}
5100
5101/**
5102 * xmlSchemaParseNotation:
5103 * @ctxt: a schema validation context
5104 * @schema: the schema being built
5105 * @node: a subtree containing XML Schema informations
5106 *
5107 * parse a XML schema Notation declaration
5108 *
5109 * Returns the new structure or NULL in case of error
5110 */
5111static xmlSchemaNotationPtr
5112xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005113 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005114{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005115 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00005116 xmlSchemaNotationPtr ret;
5117 xmlNodePtr child = NULL;
5118
5119 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5120 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005121 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00005122 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005123 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
5124 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005125 return (NULL);
5126 }
5127 ret = xmlSchemaAddNotation(ctxt, schema, name);
5128 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005129 return (NULL);
5130 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005131 ret->targetNamespace = schema->targetNamespace;
Daniel Veillard4255d502002-04-16 15:50:10 +00005132 child = node->children;
5133 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005134 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5135 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005136 }
5137 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005138 xmlSchemaPErr2(ctxt, node, child,
5139 XML_SCHEMAP_UNKNOWN_NOTATION_CHILD,
5140 "notation %s has unexpected content\n", name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005141 }
5142
5143 return (ret);
5144}
5145
5146/**
5147 * xmlSchemaParseAnyAttribute:
5148 * @ctxt: a schema validation context
5149 * @schema: the schema being built
5150 * @node: a subtree containing XML Schema informations
5151 *
5152 * parse a XML schema AnyAttrribute declaration
5153 * *WARNING* this interface is highly subject to change
5154 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005155 * Returns a wildcard or NULL.
Daniel Veillard4255d502002-04-16 15:50:10 +00005156 */
Daniel Veillard3646d642004-06-02 19:19:14 +00005157static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005158xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
5159 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005160{
Daniel Veillard3646d642004-06-02 19:19:14 +00005161 xmlSchemaWildcardPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00005162 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005163 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005164
5165 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5166 return (NULL);
5167
Daniel Veillard3646d642004-06-02 19:19:14 +00005168 ret = xmlSchemaAddWildcard(ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00005169 if (ret == NULL) {
5170 return (NULL);
5171 }
William M. Bracke7091952004-05-11 15:09:58 +00005172 ret->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005173 /*
5174 * Check for illegal attributes.
5175 */
5176 attr = node->properties;
5177 while (attr != NULL) {
5178 if (attr->ns == NULL) {
5179 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5180 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
5181 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
5182 xmlSchemaPIllegalAttrErr(ctxt,
5183 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5184 NULL, NULL, attr);
5185 }
5186 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5187 xmlSchemaPIllegalAttrErr(ctxt,
5188 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5189 NULL, NULL, attr);
5190 }
5191 attr = attr->next;
5192 }
5193 /* ret->id = xmlSchemaGetProp(ctxt, node, "id"); */
5194 /*
5195 * Parse the namespace list.
5196 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00005197 if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0) {
5198 xmlSchemaFreeWildcard(ret);
5199 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005200 }
5201 /*
5202 * And now for the children...
5203 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005204 child = node->children;
5205 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005206 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5207 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005208 }
5209 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005210 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005211 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5212 NULL, NULL, node, child,
5213 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005214 }
5215
5216 return (ret);
5217}
5218
5219
5220/**
5221 * xmlSchemaParseAttribute:
5222 * @ctxt: a schema validation context
5223 * @schema: the schema being built
5224 * @node: a subtree containing XML Schema informations
5225 *
5226 * parse a XML schema Attrribute declaration
5227 * *WARNING* this interface is highly subject to change
5228 *
William M. Bracke7091952004-05-11 15:09:58 +00005229 * Returns the attribute declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00005230 */
5231static xmlSchemaAttributePtr
5232xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00005233 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005234{
Daniel Veillardc0826a72004-08-10 14:17:33 +00005235 const xmlChar *name, *attrValue;
5236 xmlChar *repName = NULL; /* The reported designation. */
Daniel Veillard4255d502002-04-16 15:50:10 +00005237 xmlSchemaAttributePtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005238 xmlNodePtr child = NULL;
5239 xmlAttrPtr attr, nameAttr;
5240 int isRef = 0;
William M. Bracke7091952004-05-11 15:09:58 +00005241
5242 /*
5243 * Note that the w3c spec assumes the schema to be validated with schema
5244 * for schemas beforehand.
5245 *
5246 * 3.2.3 Constraints on XML Representations of Attribute Declarations
William M. Bracke7091952004-05-11 15:09:58 +00005247 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005248
5249 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5250 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005251 attr = xmlSchemaGetPropNode(node, "ref");
5252 nameAttr = xmlSchemaGetPropNode(node, "name");
5253
5254 if ((attr == NULL) && (nameAttr == NULL)) {
5255 /*
5256 * 3.2.3 : 3.1
5257 * One of ref or name must be present, but not both
5258 */
5259 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
5260 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, node, NULL,
5261 "One of the attributes 'ref' or 'name' must be present");
5262 return (NULL);
5263 }
5264 if ((topLevel) || (attr == NULL)) {
5265 if (nameAttr == NULL) {
5266 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
5267 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, node,
5268 "name", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005269 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005270 }
5271 } else
5272 isRef = 1;
5273
5274 if (isRef) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005275 char buf[50];
Daniel Veillardc0826a72004-08-10 14:17:33 +00005276 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix = NULL;
5277
5278 /*
5279 * Parse as attribute reference.
5280 */
5281 if (xmlSchemaPValAttrNodeQName(ctxt, schema,
5282 (xmlChar **) &xmlSchemaElemDesAttrRef, NULL, attr, &refNs,
5283 &refPrefix, &ref) != 0) {
5284 return (NULL);
5285 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005286 snprintf(buf, 49, "#aRef%d", ctxt->counter++ + 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005287 name = (const xmlChar *) buf;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005288 ret = xmlSchemaAddAttribute(ctxt, schema, name, NULL, node, 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005289 if (ret == NULL) {
5290 if (repName != NULL)
5291 xmlFree(repName);
5292 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005293 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005294 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
5295 ret->node = node;
5296 ret->refNs = refNs;
5297 ret->refPrefix = refPrefix;
5298 ret->ref = ref;
5299 /*
5300 xmlSchemaFormatTypeRep(&repName, (xmlSchemaTypePtr) ret, NULL, NULL);
5301 */
5302 if (nameAttr != NULL)
5303 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
5304 &repName, (xmlSchemaTypePtr) ret, nameAttr,
5305 "ref", "name");
5306 /*
5307 * Check for illegal attributes.
5308 */
5309 attr = node->properties;
5310 while (attr != NULL) {
5311 if (attr->ns == NULL) {
5312 if (xmlStrEqual(attr->name, BAD_CAST "type") ||
5313 xmlStrEqual(attr->name, BAD_CAST "form")) {
5314 /*
5315 * 3.2.3 : 3.2
5316 * If ref is present, then all of <simpleType>,
5317 * form and type must be absent.
5318 */
5319 xmlSchemaPIllegalAttrErr(ctxt,
5320 XML_SCHEMAP_SRC_ATTRIBUTE_3_2, &repName,
5321 (xmlSchemaTypePtr) ret, attr);
5322 } else if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
5323 (!xmlStrEqual(attr->name, BAD_CAST "use")) &&
5324 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5325 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
5326 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
5327 (!xmlStrEqual(attr->name, BAD_CAST "default"))) {
5328 xmlSchemaPIllegalAttrErr(ctxt,
5329 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5330 &repName, (xmlSchemaTypePtr) ret, attr);
5331 }
5332 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5333 xmlSchemaPIllegalAttrErr(ctxt,
5334 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5335 &repName, (xmlSchemaTypePtr) ret, attr);
5336 }
5337 attr = attr->next;
5338 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005339 } else {
William M. Bracke7091952004-05-11 15:09:58 +00005340 const xmlChar *ns = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005341
5342 /*
5343 * Parse as attribute declaration.
5344 */
5345 if (xmlSchemaPValAttrNode(ctxt,
5346 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, nameAttr,
5347 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
5348 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005349 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005350 /*
5351 xmlSchemaFormatTypeRep(&repName, NULL, xmlSchemaElemDesAttrDecl, name);
5352 */
5353 /*
5354 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
5355 */
5356 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
5357 xmlSchemaPSimpleTypeErr(ctxt,
5358 XML_SCHEMAP_NO_XMLNS,
5359 &repName, NULL, (xmlNodePtr) nameAttr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005360 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), "NCName", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005361 "The value must not match 'xmlns'",
5362 NULL, NULL);
5363 if (repName != NULL)
5364 xmlFree(repName);
5365 return (NULL);
5366 }
5367 /*
5368 * Evaluate the target namespace
5369 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005370 if (topLevel) {
5371 ns = schema->targetNamespace;
5372 } else {
5373 attr = xmlSchemaGetPropNode(node, "form");
5374 if (attr != NULL) {
5375 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5376 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
5377 ns = schema->targetNamespace;
5378 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
5379 xmlSchemaPSimpleTypeErr(ctxt,
5380 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5381 &repName, NULL, (xmlNodePtr) attr,
5382 NULL, "(qualified | unqualified)",
5383 attrValue, NULL, NULL, NULL);
5384 }
5385 } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
5386 ns = schema->targetNamespace;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005387 }
5388 ret = xmlSchemaAddAttribute(ctxt, schema, name, ns, node, topLevel);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005389 if (ret == NULL) {
5390 if (repName != NULL)
5391 xmlFree(repName);
Daniel Veillard3646d642004-06-02 19:19:14 +00005392 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005393 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005394 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005395 ret->node = node;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005396 if (topLevel)
5397 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
5398 /*
5399 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
5400 */
5401 if (xmlStrEqual(ret->targetNamespace, xmlSchemaInstanceNs)) {
5402 xmlSchemaPCustomErr(ctxt,
5403 XML_SCHEMAP_NO_XSI,
5404 &repName, (xmlSchemaTypePtr) ret, node,
5405 "The target namespace must not match '%s'",
5406 xmlSchemaInstanceNs);
5407 }
5408 /*
5409 * Check for illegal attributes.
5410 */
5411 attr = node->properties;
5412 while (attr != NULL) {
5413 if (attr->ns == NULL) {
5414 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5415 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
5416 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
5417 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
5418 (!xmlStrEqual(attr->name, BAD_CAST "type"))) {
5419 if ((topLevel) ||
5420 ((!xmlStrEqual(attr->name, BAD_CAST "form")) &&
5421 (!xmlStrEqual(attr->name, BAD_CAST "use")))) {
5422 xmlSchemaPIllegalAttrErr(ctxt,
5423 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5424 &repName, (xmlSchemaTypePtr) ret, attr);
5425 }
5426 }
5427 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5428 xmlSchemaPIllegalAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5429 &repName, (xmlSchemaTypePtr) ret, attr);
5430 }
5431 attr = attr->next;
5432 }
5433 xmlSchemaPValAttrQName(ctxt, schema, &repName, (xmlSchemaTypePtr) ret,
5434 node, "type", &ret->typeNs, NULL, &ret->typeName);
William M. Bracke7091952004-05-11 15:09:58 +00005435 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005436 /* TODO: Check ID. */
5437 ret->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Bracke7091952004-05-11 15:09:58 +00005438 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005439 * Attribute "fixed".
William M. Bracke7091952004-05-11 15:09:58 +00005440 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00005441 ret->defValue = xmlSchemaGetProp(ctxt, node, "fixed");
5442 if (ret->defValue != NULL)
5443 ret->flags |= XML_SCHEMAS_ATTR_FIXED;
5444 /*
5445 * Attribute "default".
5446 */
5447 attr = xmlSchemaGetPropNode(node, "default");
5448 if (attr != NULL) {
5449 /*
5450 * 3.2.3 : 1
5451 * default and fixed must not both be present.
5452 */
5453 if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
5454 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
5455 &repName, (xmlSchemaTypePtr) ret, attr, "default", "fixed");
5456 } else
5457 ret->defValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5458 }
5459 if (topLevel == 0) {
5460 /*
5461 * Attribute "use".
5462 */
5463 attr = xmlSchemaGetPropNode(node, "use");
5464 if (attr != NULL) {
5465 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5466 if (xmlStrEqual(attrValue, BAD_CAST "optional"))
5467 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
5468 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
5469 ret->occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
5470 else if (xmlStrEqual(attrValue, BAD_CAST "required"))
5471 ret->occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
5472 else
5473 xmlSchemaPSimpleTypeErr(ctxt,
5474 XML_SCHEMAP_INVALID_ATTR_USE,
5475 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005476 NULL, "(optional | prohibited | required)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00005477 attrValue, NULL, NULL, NULL);
5478 } else
5479 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
5480 /*
5481 * 3.2.3 : 2
5482 * If default and use are both present, use must have
5483 * the actual value optional.
5484 */
5485 if ((ret->occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
5486 (ret->defValue != NULL) &&
5487 ((ret->flags & XML_SCHEMAS_ATTR_FIXED) == 0)) {
5488 xmlSchemaPSimpleTypeErr(ctxt,
5489 XML_SCHEMAP_SRC_ATTRIBUTE_2,
5490 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005491 NULL, "(optional | prohibited | required)", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005492 "The value must be 'optional' if the attribute "
5493 "'default' is present as well", NULL, NULL);
5494 }
5495 }
5496 /*
5497 * And now for the children...
5498 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005499 child = node->children;
5500 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005501 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5502 child = child->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005503 }
5504 if (isRef) {
5505 if (child != NULL) {
5506 if (IS_SCHEMA(child, "simpleType"))
5507 /*
5508 * 3.2.3 : 3.2
5509 * If ref is present, then all of <simpleType>,
5510 * form and type must be absent.
5511 */
5512 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
5513 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
5514 "(annotation?)");
5515 else
5516 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5517 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
5518 "(annotation?)");
5519 }
5520 } else {
5521 if (IS_SCHEMA(child, "simpleType")) {
5522 if (ret->typeName != NULL) {
5523 /*
5524 * 3.2.3 : 4
5525 * type and <simpleType> must not both be present.
5526 */
5527 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
5528 &repName, (xmlSchemaTypePtr) ret, node, child,
5529 "The attribute 'type' and the <simpleType> child "
5530 "are mutually exclusive", NULL);
5531 } else
5532 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
5533 child = child->next;
5534 }
5535 if (child != NULL)
5536 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5537 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
5538 "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005539 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005540 /*
5541 * Cleanup.
5542 */
5543 if (repName != NULL)
5544 xmlFree(repName);
Daniel Veillard4255d502002-04-16 15:50:10 +00005545 return (ret);
5546}
5547
5548/**
5549 * xmlSchemaParseAttributeGroup:
5550 * @ctxt: a schema validation context
5551 * @schema: the schema being built
5552 * @node: a subtree containing XML Schema informations
5553 *
5554 * parse a XML schema Attribute Group declaration
5555 * *WARNING* this interface is highly subject to change
5556 *
5557 * Returns the attribute group or NULL in case of error.
5558 */
5559static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005560xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00005561 xmlSchemaPtr schema, xmlNodePtr node,
5562 int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005563{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005564 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00005565 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00005566 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005567 const xmlChar *oldcontainer;
5568 xmlAttrPtr attr, nameAttr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005569
5570 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5571 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005572
5573 nameAttr = xmlSchemaGetPropNode(node, "name");
5574 attr = xmlSchemaGetPropNode(node, "ref");
5575 if ((topLevel) || (attr == NULL)) {
5576 /*
5577 * Parse as an attribute group definition.
5578 * Note that those are allowed at top level only.
5579 */
5580 if (nameAttr == NULL) {
5581 xmlSchemaPMissingAttrErr(ctxt,
5582 XML_SCHEMAP_S4S_ATTR_MISSING,
5583 NULL, NULL, node, "name", NULL);
5584 return (NULL);
5585 }
5586 name = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) nameAttr);
5587 /*
5588 * The name is crucial, exit if invalid.
5589 */
5590 if (xmlSchemaPValAttrNode(ctxt,
5591 NULL, NULL, nameAttr,
5592 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
5593 return (NULL);
5594 }
5595 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
5596 if (ret == NULL)
5597 return (NULL);
5598 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
5599 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
5600 ret->node = node;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005601 ret->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005602 } else {
5603 char buf[50];
5604 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix;
5605
5606 /*
5607 * Parse as an attribute group definition reference.
5608 */
5609 if (attr == NULL) {
5610 xmlSchemaPMissingAttrErr(ctxt,
5611 XML_SCHEMAP_S4S_ATTR_MISSING,
5612 NULL, NULL, node, "ref", NULL);
5613 }
5614 xmlSchemaPValAttrNodeQName(ctxt, schema,
5615 NULL, NULL, attr, &refNs, &refPrefix, &ref);
5616
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005617 snprintf(buf, 49, "#agRef%d", ctxt->counter++ + 1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005618 name = (const xmlChar *) buf;
5619 if (name == NULL) {
5620 xmlSchemaPErrMemory(ctxt, "creating internal name for an "
5621 "attribute group definition reference", node);
5622 return (NULL);
5623 }
5624 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
5625 if (ret == NULL)
5626 return (NULL);
5627 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
5628 ret->ref = ref;
5629 ret->refNs = refNs;
5630 /* TODO: Is @refPrefix currently used? */
5631 ret->refPrefix = refPrefix;
5632 ret->node = node;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005633 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005634 /*
5635 * Check for illegal attributes.
5636 */
5637 attr = node->properties;
5638 while (attr != NULL) {
5639 if (attr->ns == NULL) {
5640 if ((((topLevel == 0) && (!xmlStrEqual(attr->name, BAD_CAST "ref"))) ||
5641 (topLevel && (!xmlStrEqual(attr->name, BAD_CAST "name")))) &&
5642 (!xmlStrEqual(attr->name, BAD_CAST "id")))
5643 {
5644 xmlSchemaPIllegalAttrErr(ctxt,
5645 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5646 NULL, NULL, attr);
5647 }
5648 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5649 xmlSchemaPIllegalAttrErr(ctxt,
5650 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5651 NULL, NULL, attr);
5652 }
5653 attr = attr->next;
5654 }
5655 /* TODO: Validate "id" ? */
5656 /*
5657 * And now for the children...
5658 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005659 oldcontainer = ctxt->container;
Daniel Veillard4255d502002-04-16 15:50:10 +00005660 ctxt->container = name;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005661 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00005662 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005663 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5664 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005665 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005666 if (topLevel) {
5667 child = xmlSchemaParseAttrDecls(ctxt, schema, child, (xmlSchemaTypePtr) ret);
5668 if (IS_SCHEMA(child, "anyAttribute")) {
5669 ret->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
5670 child = child->next;
5671 }
5672 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005673 if (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005674 xmlSchemaPContentErr(ctxt,
5675 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5676 NULL, NULL, node, child, NULL,
5677 "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005678 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005679 ctxt->container = oldcontainer;
5680 return (ret);
5681}
5682
5683/**
William M. Brack2f2a6632004-08-20 23:09:47 +00005684 * xmlSchemaPValAttrFormDefault:
5685 * @value: the value
5686 * @flags: the flags to be modified
5687 * @flagQualified: the specific flag for "qualified"
5688 *
5689 * Returns 0 if the value is valid, 1 otherwise.
5690 */
5691static int
5692xmlSchemaPValAttrFormDefault(const xmlChar *value,
5693 int *flags,
5694 int flagQualified)
5695{
5696 if (xmlStrEqual(value, BAD_CAST "qualified")) {
5697 if ((*flags & flagQualified) == 0)
5698 *flags |= flagQualified;
5699 } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
5700 return (1);
5701
5702 return (0);
5703}
5704
5705/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005706 * xmlSchemaPValAttrBlockFinal:
5707 * @value: the value
5708 * @flags: the flags to be modified
5709 * @flagAll: the specific flag for "#all"
5710 * @flagExtension: the specific flag for "extension"
5711 * @flagRestriction: the specific flag for "restriction"
5712 * @flagSubstitution: the specific flag for "substitution"
5713 * @flagList: the specific flag for "list"
5714 * @flagUnion: the specific flag for "union"
5715 *
5716 * Validates the value of the attribute "final" and "block". The value
5717 * is converted into the specified flag values and returned in @flags.
5718 *
5719 * Returns 0 if the value is valid, 1 otherwise.
5720 */
5721
5722static int
5723xmlSchemaPValAttrBlockFinal(const xmlChar *value,
5724 int *flags,
5725 int flagAll,
5726 int flagExtension,
5727 int flagRestriction,
5728 int flagSubstitution,
5729 int flagList,
5730 int flagUnion)
5731{
5732 int ret = 0;
5733
5734 /*
5735 * TODO: This does not check for dublicate entries.
5736 */
William M. Brack2f2a6632004-08-20 23:09:47 +00005737 if (value == NULL)
5738 return (1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005739 if (xmlStrEqual(value, BAD_CAST "#all")) {
5740 if (flagAll != -1)
5741 *flags |= flagAll;
5742 else {
5743 if (flagExtension != -1)
5744 *flags |= flagExtension;
5745 if (flagRestriction != -1)
5746 *flags |= flagRestriction;
5747 if (flagSubstitution != -1)
5748 *flags |= flagSubstitution;
5749 if (flagList != -1)
5750 *flags |= flagList;
5751 if (flagUnion != -1)
5752 *flags |= flagUnion;
5753 }
5754 } else {
5755 const xmlChar *end, *cur = value;
5756 xmlChar *item;
5757
5758 do {
5759 while (IS_BLANK_CH(*cur))
5760 cur++;
5761 end = cur;
5762 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
5763 end++;
5764 if (end == cur)
5765 break;
5766 item = xmlStrndup(cur, end - cur);
5767 if (xmlStrEqual(item, BAD_CAST "extension")) {
5768 if (flagExtension != -1) {
5769 if ((*flags & flagExtension) == 0)
5770 *flags |= flagExtension;
5771 } else
5772 ret = 1;
5773 } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
5774 if (flagRestriction != -1) {
5775 if ((*flags & flagRestriction) == 0)
5776 *flags |= flagRestriction;
5777 } else
5778 ret = 1;
5779 } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
5780 if (flagSubstitution != -1) {
5781 if ((*flags & flagSubstitution) == 0)
5782 *flags |= flagSubstitution;
5783 } else
5784 ret = 1;
5785 } else if (xmlStrEqual(item, BAD_CAST "list")) {
5786 if (flagList != -1) {
5787 if ((*flags & flagList) == 0)
5788 *flags |= flagList;
5789 } else
5790 ret = 1;
5791 } else if (xmlStrEqual(item, BAD_CAST "union")) {
5792 if (flagUnion != -1) {
5793 if ((*flags & flagUnion) == 0)
5794 *flags |= flagUnion;
5795 } else
5796 ret = 1;
5797 } else
5798 ret = 1;
5799 if (item != NULL)
5800 xmlFree(item);
5801 cur = end;
5802 } while ((ret == 0) && (*cur != 0));
5803 }
5804
5805 return (ret);
5806}
5807
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005808#ifdef IDC_ENABLED
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00005809static int
5810xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00005811 xmlSchemaIDCPtr idc,
5812 xmlSchemaIDCSelectPtr selector,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00005813 xmlAttrPtr attr,
5814 int isField)
5815{
5816 xmlNodePtr node;
5817
5818 /*
5819 * c-selector-xpath:
5820 * Schema Component Constraint: Selector Value OK
5821 *
5822 * TODO: 1 The {selector} must be a valid XPath expression, as defined
5823 * in [XPath].
5824 */
5825 if (selector == NULL) {
5826 xmlSchemaPErr(ctxt, idc->node,
5827 XML_SCHEMAP_INTERNAL,
5828 "Internal error: xmlSchemaCheckCSelectorXPath, "
5829 "the selector is not specified.\n", NULL, NULL);
5830 return (-1);
5831 }
5832 if (attr == NULL)
5833 node = idc->node;
5834 else
5835 node = (xmlNodePtr) attr;
5836 if (selector->xpath == NULL) {
5837 xmlSchemaPCustomErr(ctxt,
5838 /* TODO: Adjust error code. */
5839 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5840 NULL, NULL, node,
5841 "The XPath expression of the selector is not valid", NULL);
5842 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
5843 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00005844 const xmlChar **nsArray = NULL;
5845 xmlNsPtr *nsList = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00005846 /*
5847 * Compile the XPath expression.
5848 */
5849 /*
5850 * TODO: We need the array of in-scope namespaces for compilation.
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00005851 * TODO: Call xmlPatterncompile with different options for selector/
5852 * field.
5853 */
5854 nsList = xmlGetNsList(attr->doc, attr->parent);
5855 /*
5856 * Build an array of prefixes and namespaces.
5857 */
5858 if (nsList != NULL) {
5859 int i, count = 0;
5860 xmlNsPtr ns;
5861
5862 for (i = 0; nsList[i] != NULL; i++)
5863 count++;
5864
5865 nsArray = (const xmlChar **) xmlMalloc(
5866 (count * 2 + 1) * sizeof(const xmlChar *));
5867 if (nsArray == NULL) {
5868 xmlSchemaPErrMemory(ctxt, "allocating a namespace array",
5869 NULL);
5870 return (-1);
5871 }
5872 for (i = 0; i < count; i++) {
5873 ns = nsList[i];
5874 nsArray[2 * i] = nsList[i]->href;
5875 nsArray[2 * i + 1] = nsList[i]->prefix;
5876 }
5877 nsArray[count * 2] = NULL;
5878 xmlFree(nsList);
5879 }
5880 if (isField)
5881 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
5882 NULL, 0, nsArray);
5883 else
5884 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
5885 NULL, 0, nsArray);
5886 if (nsArray != NULL)
5887 xmlFree((xmlChar **) nsArray);
5888
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00005889#ifdef IDC_XPATH_SUPPORT
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00005890 if (selector->xpathComp == NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00005891 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00005892 /* TODO: Adjust error code? */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00005893 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5894 NULL, NULL, node,
5895 "The XPath expression '%s' could not be "
5896 "compiled", selector->xpath);
5897 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
5898 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00005899#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00005900 }
5901 return (0);
5902}
5903
5904/**
5905 * xmlSchemaAssignAnnotation:
5906 * @item: the schema component
5907 * @annot: the annotation
5908 *
5909 * Adds the annotation to the given schema component.
5910 *
5911 * Returns the given annotaion.
5912 */
5913static xmlSchemaAnnotPtr
5914xmlSchemaAssignAnnotation(xmlSchemaBasicItemPtr item,
5915 xmlSchemaAnnotPtr annot)
5916{
5917 xmlSchemaAnnotPtr cur = item->annot;
5918
5919 if (item->annot == NULL) {
5920 item->annot = annot;
5921 return (annot);
5922 }
5923 cur = item->annot;
5924 if (cur->next != NULL) {
5925 cur = cur->next;
5926 }
5927 cur->next = annot;
5928 return (annot);
5929}
5930
5931/**
5932 * xmlSchemaParseIDCSelectorAndField:
5933 * @ctxt: a schema validation context
5934 * @schema: the schema being built
5935 * @node: a subtree containing XML Schema informations
5936 *
5937 * Parses a XML Schema identity-contraint definition's
5938 * <selector> and <field> elements.
5939 *
5940 * Returns the parsed identity-constraint definition.
5941 */
5942static xmlSchemaIDCSelectPtr
5943xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
5944 xmlSchemaPtr schema,
5945 xmlSchemaIDCPtr idc,
5946 xmlNodePtr node,
5947 int isField)
5948{
5949 xmlSchemaIDCSelectPtr item;
5950 xmlNodePtr child = NULL;
5951 xmlAttrPtr attr;
5952
5953 /*
5954 * Check for illegal attributes.
5955 */
5956 attr = node->properties;
5957 while (attr != NULL) {
5958 if (attr->ns == NULL) {
5959 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5960 (!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
5961 xmlSchemaPIllegalAttrErr(ctxt,
5962 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5963 NULL, NULL, attr);
5964 }
5965 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5966 xmlSchemaPIllegalAttrErr(ctxt,
5967 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5968 NULL, NULL, attr);
5969 }
5970 attr = attr->next;
5971 }
5972 /*
5973 * Create the item.
5974 */
5975 item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
5976 if (item == NULL) {
5977 xmlSchemaPErrMemory(ctxt,
5978 "allocating a 'selector' of an identity-constraint definition",
5979 NULL);
5980 return (NULL);
5981 }
5982 memset(item, 0, sizeof(xmlSchemaIDCSelect));
5983 /*
5984 * Attribute "xpath" (mandatory).
5985 */
5986 attr = xmlSchemaGetPropNode(node, "xpath");
5987 if (attr == NULL) {
5988 xmlSchemaPMissingAttrErr(ctxt,
5989 XML_SCHEMAP_S4S_ATTR_MISSING,
5990 NULL, NULL, node,
5991 "name", NULL);
5992 } else {
5993 item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5994 /*
5995 * URGENT TODO: "field"s have an other syntax than "selector"s.
5996 */
5997
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00005998 if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr,
5999 isField) == -1) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006000 xmlSchemaPErr(ctxt,
6001 (xmlNodePtr) attr,
6002 XML_SCHEMAP_INTERNAL,
6003 "Internal error: xmlSchemaParseIDCSelectorAndField, "
6004 "validating the XPath expression of a IDC selector.\n",
6005 NULL, NULL);
6006 }
6007
6008 }
6009 /*
6010 * And now for the children...
6011 */
6012 child = node->children;
6013 if (IS_SCHEMA(child, "annotation")) {
6014 /*
6015 * Add the annotation to the parent IDC.
6016 */
6017 xmlSchemaAssignAnnotation((xmlSchemaBasicItemPtr) idc,
6018 xmlSchemaParseAnnotation(ctxt, schema, child));
6019 child = child->next;
6020 }
6021 if (child != NULL) {
6022 xmlSchemaPContentErr(ctxt,
6023 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6024 NULL, NULL, node, child,
6025 NULL, "(annotation?)");
6026 }
6027
6028 return (item);
6029}
6030
6031/**
6032 * xmlSchemaParseIDC:
6033 * @ctxt: a schema validation context
6034 * @schema: the schema being built
6035 * @node: a subtree containing XML Schema informations
6036 *
6037 * Parses a XML Schema identity-contraint definition.
6038 *
6039 * Returns the parsed identity-constraint definition.
6040 */
6041static xmlSchemaIDCPtr
6042xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
6043 xmlSchemaPtr schema,
6044 xmlNodePtr node,
6045 xmlSchemaTypeType idcCategory,
6046 const xmlChar *targetNamespace)
6047{
6048 xmlSchemaIDCPtr item = NULL;
6049 xmlNodePtr child = NULL;
6050 xmlAttrPtr attr;
6051 const xmlChar *name = NULL;
6052 xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
6053 int resAdd;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00006054
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006055 /*
6056 * Check for illegal attributes.
6057 */
6058 attr = node->properties;
6059 while (attr != NULL) {
6060 if (attr->ns == NULL) {
6061 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6062 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
6063 ((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
6064 (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
6065 xmlSchemaPIllegalAttrErr(ctxt,
6066 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6067 NULL, NULL, attr);
6068 }
6069 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6070 xmlSchemaPIllegalAttrErr(ctxt,
6071 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6072 NULL, NULL, attr);
6073 }
6074 attr = attr->next;
6075 }
6076 /*
6077 * Attribute "name" (mandatory).
6078 */
6079 attr = xmlSchemaGetPropNode(node, "name");
6080 if (attr == NULL) {
6081 xmlSchemaPMissingAttrErr(ctxt,
6082 XML_SCHEMAP_S4S_ATTR_MISSING,
6083 NULL, NULL, node,
6084 "name", NULL);
6085 return (NULL);
6086 } else if (xmlSchemaPValAttrNode(ctxt,
6087 NULL, NULL, attr,
6088 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
6089 return (NULL);
6090 }
6091 /*
6092 * Create the component.
6093 */
6094 if (schema->idcDef == NULL)
6095 schema->idcDef = xmlHashCreateDict(10, ctxt->dict);
6096 if (schema->idcDef == NULL)
6097 return (NULL);
6098
6099 item = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
6100 if (item == NULL) {
6101 xmlSchemaPErrMemory(ctxt,
6102 "allocating an identity-constraint definition", NULL);
6103 return (NULL);
6104 }
6105 /*
6106 * Add the IDC to the list of IDCs on the schema component.
6107 */
6108 resAdd = xmlHashAddEntry2(schema->idcDef, name, targetNamespace, item);
6109 if (resAdd != 0) {
6110 xmlSchemaPCustomErrExt(ctxt,
6111 XML_SCHEMAP_REDEFINED_TYPE,
6112 NULL, NULL, node,
6113 "An identity-constraint definition with the name '%s' "
6114 "and targetNamespace '%s' does already exist",
6115 name, targetNamespace, NULL);
6116 xmlFree(item);
6117 return (NULL);
6118 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006119 memset(item, 0, sizeof(xmlSchemaIDC));
6120 item->name = name;
6121 item->type = idcCategory;
6122 item->node = node;
6123 /*
6124 * The target namespace of the parent element declaration.
6125 */
6126 item->targetNamespace = targetNamespace;
6127 /* TODO: Handle attribute "id". */
6128 if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
6129 /*
6130 * Attribute "refer" (mandatory).
6131 */
6132 attr = xmlSchemaGetPropNode(node, "refer");
6133 if (attr == NULL) {
6134 xmlSchemaPMissingAttrErr(ctxt,
6135 XML_SCHEMAP_S4S_ATTR_MISSING,
6136 NULL, NULL, node,
6137 "refer", NULL);
6138 } else {
6139 /*
6140 * Create a reference item.
6141 */
6142 item->ref = (xmlSchemaItemQNRefPtr) xmlMalloc(
6143 sizeof(xmlSchemaItemQNRef));
6144 if (item->ref == NULL) {
6145 xmlSchemaPErrMemory(ctxt,
6146 "allocating a QName reference item", NULL);
6147 return (NULL);
6148 }
6149 memset(item->ref, 0, sizeof(xmlSchemaItemQNRef));
6150 xmlSchemaPValAttrNodeQName(ctxt, schema,
6151 NULL, NULL, attr,
6152 &(item->ref->targetNamespace), 0,
6153 &(item->ref->name));
6154 }
6155 }
6156 /*
6157 * And now for the children...
6158 */
6159 child = node->children;
6160 if (IS_SCHEMA(child, "annotation")) {
6161 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6162 child = child->next;
6163 }
6164 /*
6165 * Child element <selector>.
6166 */
6167 if (IS_SCHEMA(child, "selector")) {
6168 item->selector = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
6169 item, child, 0);
6170 child = child->next;
6171 /*
6172 * Child elements <field>.
6173 */
6174 if (IS_SCHEMA(child, "field")) {
6175 do {
6176 field = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
6177 item, child, 1);
6178 if (field != NULL) {
6179 field->index = item->nbFields;
6180 item->nbFields++;
6181 if (lastField != NULL)
6182 lastField->next = field;
6183 else
6184 item->fields = field;
6185 lastField = field;
6186 }
6187 child = child->next;
6188 } while (IS_SCHEMA(child, "field"));
6189 } else {
6190 xmlSchemaPContentErr(ctxt,
6191 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6192 NULL, NULL, node, child,
6193 NULL, "(annotation?, (selector, field+))");
6194 }
6195 }
6196 if (child != NULL) {
6197 xmlSchemaPContentErr(ctxt,
6198 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6199 NULL, NULL, node, child,
6200 NULL, "(annotation?, (selector, field+))");
6201 }
6202
6203 return (item);
6204}
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006205#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006206
Daniel Veillardc0826a72004-08-10 14:17:33 +00006207/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006208 * xmlSchemaParseElement:
6209 * @ctxt: a schema validation context
6210 * @schema: the schema being built
6211 * @node: a subtree containing XML Schema informations
6212 *
6213 * parse a XML schema Element declaration
6214 * *WARNING* this interface is highly subject to change
6215 *
William M. Bracke7091952004-05-11 15:09:58 +00006216 * Returns the parsed element declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00006217 */
6218static xmlSchemaElementPtr
6219xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00006220 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006221{
Daniel Veillardc0826a72004-08-10 14:17:33 +00006222 const xmlChar *name = NULL;
6223 const xmlChar *attrValue;
6224 xmlChar *repName = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00006225 xmlSchemaElementPtr ret;
6226 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006227 const xmlChar *oldcontainer;
6228 xmlAttrPtr attr, nameAttr;
6229 int minOccurs, maxOccurs;
6230 int isRef = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006231#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006232 xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006233#endif
William M. Bracke7091952004-05-11 15:09:58 +00006234
6235 /* 3.3.3 Constraints on XML Representations of Element Declarations */
6236 /* TODO: Complete implementation of 3.3.6 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006237
Daniel Veillard4255d502002-04-16 15:50:10 +00006238 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6239 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006240
Daniel Veillardc0826a72004-08-10 14:17:33 +00006241 oldcontainer = ctxt->container;
6242
6243 nameAttr = xmlSchemaGetPropNode(node, "name");
6244 attr = xmlSchemaGetPropNode(node, "ref");
6245 if ((topLevel) || (attr == NULL)) {
6246 if (nameAttr == NULL) {
6247 xmlSchemaPMissingAttrErr(ctxt,
6248 XML_SCHEMAP_S4S_ATTR_MISSING,
6249 (xmlChar **) &xmlSchemaElemDesElemDecl, NULL, node,
6250 "name", NULL);
6251 return (NULL);
6252 }
6253 name = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) nameAttr);
6254 } else {
6255 isRef = 1;
6256
6257 }
6258 /*
6259 * ... unless minOccurs=maxOccurs=0, in which case the item corresponds
6260 * to no component at all
6261 * TODO: It might be better to validate the element, even if it won't be
6262 * used.
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006263 */
6264 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
6265 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(nonNegativeInteger | unbounded)");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006266 if ((minOccurs == 0) && (maxOccurs == 0))
6267 return (NULL);
6268 /*
6269 * If we get a "ref" attribute on a local <element> we will assume it's
6270 * a reference - even if there's a "name" attribute; this seems to be more
6271 * robust.
6272 */
6273 if (isRef) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006274 char buf[50];
Daniel Veillardc0826a72004-08-10 14:17:33 +00006275 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix;
6276
6277 /*
6278 * Parse as a particle.
6279 */
6280 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006281 (xmlChar **) &xmlSchemaElemDesElemRef,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006282 NULL, attr, &refNs, &refPrefix, &ref);
6283
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006284 snprintf(buf, 49, "#eRef%d", ctxt->counter++ + 1);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006285 ret = xmlSchemaAddElement(ctxt, schema, (const xmlChar *) buf, NULL, node, 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006286 if (ret == NULL) {
6287 if (repName != NULL)
6288 xmlFree(repName);
6289 return (NULL);
6290 }
6291 ret->type = XML_SCHEMA_TYPE_ELEMENT;
6292 ret->node = node;
6293 ret->ref = ref;
6294 ret->refNs = refNs;
6295 ret->refPrefix = refPrefix;
6296 ret->flags |= XML_SCHEMAS_ELEM_REF;
6297 /*
6298 * Check for illegal attributes.
6299 */
6300 /*
6301 * 3.3.3 : 2.1
6302 * One of ref or name must be present, but not both
6303 */
6304 if (nameAttr != NULL) {
6305 xmlSchemaPMutualExclAttrErr(ctxt,
6306 XML_SCHEMAP_SRC_ELEMENT_2_1,
6307 &repName, (xmlSchemaTypePtr) ret, nameAttr,
6308 "ref", "name");
6309 }
6310 /* 3.3.3 : 2.2 */
6311 attr = node->properties;
6312 while (attr != NULL) {
6313 if (attr->ns == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006314 if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
6315 xmlStrEqual(attr->name, BAD_CAST "name") ||
6316 xmlStrEqual(attr->name, BAD_CAST "id") ||
6317 xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
6318 xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
6319 {
6320 attr = attr->next;
6321 continue;
6322 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006323 xmlSchemaPCustomAttrErr(ctxt,
6324 XML_SCHEMAP_SRC_ELEMENT_2_2,
6325 &repName, (xmlSchemaTypePtr) ret, attr,
6326 "Only the attributes 'minOccurs', 'maxOccurs' and "
6327 "'id' are allowed in addition to 'ref'");
6328 break;
6329 }
6330 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6331 xmlSchemaPIllegalAttrErr(ctxt,
6332 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6333 &repName, (xmlSchemaTypePtr) ret, attr);
6334 }
6335 attr = attr->next;
6336 }
6337 } else {
6338 const xmlChar *ns = NULL, *fixed;
6339
6340 /*
6341 * Parse as an element declaration.
6342 */
6343 if (xmlSchemaPValAttrNode(ctxt,
6344 (xmlChar **) &xmlSchemaElemDesElemDecl, NULL, nameAttr,
6345 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
6346 return (NULL);
6347 /*
6348 * Evaluate the target namespace.
6349 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006350 if (topLevel) {
6351 ns = schema->targetNamespace;
6352 } else {
6353 attr = xmlSchemaGetPropNode(node, "form");
6354 if (attr != NULL) {
6355 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6356 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
William M. Bracke7091952004-05-11 15:09:58 +00006357 ns = schema->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006358 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
6359 xmlSchemaPSimpleTypeErr(ctxt,
6360 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6361 &repName, NULL, (xmlNodePtr) attr,
6362 NULL, "(qualified | unqualified)",
6363 attrValue, NULL, NULL, NULL);
6364 }
6365 } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
6366 ns = schema->targetNamespace;
William M. Brack2f2a6632004-08-20 23:09:47 +00006367 }
6368 ret = xmlSchemaAddElement(ctxt, schema, name, ns, node, topLevel);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006369 if (ret == NULL) {
6370 if (repName != NULL)
6371 xmlFree(repName);
6372 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006373 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006374 ret->type = XML_SCHEMA_TYPE_ELEMENT;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006375 ret->node = node;
6376 ret->targetNamespace = ns;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006377 /*
6378 * Check for illegal attributes.
6379 */
William M. Bracke7091952004-05-11 15:09:58 +00006380 attr = node->properties;
6381 while (attr != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006382 if (attr->ns == NULL) {
6383 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
6384 (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
6385 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6386 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
6387 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
6388 (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006389 (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
6390 {
6391 if (topLevel == 0) {
6392 if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006393 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006394 (!xmlStrEqual(attr->name, BAD_CAST "form")))
6395 {
6396 if (xmlStrEqual(attr->name, BAD_CAST "substitutionGroup")) {
6397 /*
6398 * 3.3.6 : 3 If there is a non-·absent· {substitution
6399 * group affiliation}, then {scope} must be global.
6400 * TODO: This one is redundant, since the S4S does
6401 * prohibit this attribute on local declarations already;
6402 * so why an explicit error code? Weird spec.
6403 * TODO: Move this to the proper constraint layer.
6404 * TODO: Or better wait for spec 1.1 to come.
6405 */
6406 xmlSchemaPIllegalAttrErr(ctxt,
6407 XML_SCHEMAP_E_PROPS_CORRECT_3,
6408 &repName, (xmlSchemaTypePtr) ret, attr);
6409 } else {
6410 xmlSchemaPIllegalAttrErr(ctxt,
6411 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6412 &repName, (xmlSchemaTypePtr) ret, attr);
6413 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006414 }
6415 } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
6416 (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
6417 (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
6418
6419 xmlSchemaPIllegalAttrErr(ctxt,
6420 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6421 &repName, (xmlSchemaTypePtr) ret, attr);
6422 }
6423 }
6424 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6425
6426 xmlSchemaPIllegalAttrErr(ctxt,
6427 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6428 &repName, (xmlSchemaTypePtr) ret, attr);
William M. Bracke7091952004-05-11 15:09:58 +00006429 }
6430 attr = attr->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006431 }
William M. Bracke7091952004-05-11 15:09:58 +00006432 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006433 * Extract/validate attributes.
6434 */
6435 if (topLevel) {
6436 /*
6437 * Process top attributes of global element declarations here.
6438 */
6439 ret->flags |= XML_SCHEMAS_ELEM_GLOBAL;
6440 ret->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
6441 xmlSchemaPValAttrQName(ctxt, schema, &repName,
6442 (xmlSchemaTypePtr) ret, node, "substitutionGroup",
6443 &(ret->substGroupNs), NULL, &(ret->substGroup));
6444 if (xmlGetBooleanProp(ctxt, &repName, (xmlSchemaTypePtr) ret,
6445 node, "abstract", 0))
6446 ret->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
6447 /*
6448 * Attribute "final".
6449 */
6450 attr = xmlSchemaGetPropNode(node, "final");
6451 if (attr == NULL) {
6452 ret->flags |= XML_SCHEMAS_ELEM_FINAL_ABSENT;
6453 } else {
6454 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6455 if (xmlSchemaPValAttrBlockFinal(attrValue, &(ret->flags),
6456 -1,
6457 XML_SCHEMAS_ELEM_FINAL_EXTENSION,
6458 XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
6459 xmlSchemaPSimpleTypeErr(ctxt,
6460 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6461 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00006462 NULL, "(#all | List of (extension | restriction))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00006463 attrValue, NULL, NULL, NULL);
6464 }
6465 }
6466 }
6467 /*
6468 * Attribute "block".
6469 */
6470 attr = xmlSchemaGetPropNode(node, "block");
6471 if (attr == NULL) {
6472 ret->flags |= XML_SCHEMAS_ELEM_BLOCK_ABSENT;
6473 } else {
6474 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6475 if (xmlSchemaPValAttrBlockFinal(attrValue, &(ret->flags),
6476 -1,
6477 XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
6478 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
6479 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
6480 xmlSchemaPSimpleTypeErr(ctxt,
6481 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6482 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00006483 NULL, "(#all | List of (extension | "
Daniel Veillardc0826a72004-08-10 14:17:33 +00006484 "restriction | substitution))", attrValue,
6485 NULL, NULL, NULL);
6486 }
6487 }
6488 if (xmlGetBooleanProp(ctxt, &repName, (xmlSchemaTypePtr) ret,
6489 node, "nillable", 0))
6490 ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006491
Daniel Veillardc0826a72004-08-10 14:17:33 +00006492 xmlSchemaPValAttrQName(ctxt, schema,
6493 &repName, (xmlSchemaTypePtr) ret, node,
6494 "type", &(ret->namedTypeNs), NULL, &(ret->namedType));
Daniel Veillard4255d502002-04-16 15:50:10 +00006495
Daniel Veillardc0826a72004-08-10 14:17:33 +00006496 ret->value = xmlSchemaGetProp(ctxt, node, "default");
6497 attr = xmlSchemaGetPropNode(node, "fixed");
6498 if (attr != NULL) {
6499 fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6500 if (ret->value != NULL) {
6501 /*
6502 * 3.3.3 : 1
6503 * default and fixed must not both be present.
6504 */
6505 xmlSchemaPMutualExclAttrErr(ctxt,
6506 XML_SCHEMAP_SRC_ELEMENT_1,
6507 &repName, (xmlSchemaTypePtr) ret, attr,
6508 "default", "fixed");
6509 } else {
6510 ret->flags |= XML_SCHEMAS_ELEM_FIXED;
6511 ret->value = fixed;
6512 }
6513 }
6514 }
6515 /*
6516 * Extract/validate common attributes.
6517 */
6518 /* TODO: Check ID: */
6519 ret->id = xmlSchemaGetProp(ctxt, node, "id");
6520 ret->minOccurs = minOccurs;
6521 ret->maxOccurs = maxOccurs;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006522 if (topLevel != 1)
6523 xmlSchemaPCheckParticleCorrect_2(ctxt, (xmlSchemaTypePtr) ret,
6524 node, minOccurs, maxOccurs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006525 /*
6526 * And now for the children...
6527 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006528 ctxt->container = ret->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006529 child = node->children;
6530 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006531 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6532 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006533 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006534 if (isRef) {
6535 if (child != NULL) {
6536 xmlSchemaPContentErr(ctxt,
6537 XML_SCHEMAP_SRC_ELEMENT_2_2,
6538 &repName, (xmlSchemaTypePtr) ret, node, child,
6539 NULL, "(annotation?)");
William M. Bracke7091952004-05-11 15:09:58 +00006540 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006541 } else {
William M. Bracke7091952004-05-11 15:09:58 +00006542 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006543 /*
6544 * 3.3.3 : 3
6545 * "type" and either <simpleType> or <complexType> are mutually
6546 * exclusive
6547 */
William M. Bracke7091952004-05-11 15:09:58 +00006548 if (ret->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006549 xmlSchemaPContentErr(ctxt,
6550 XML_SCHEMAP_SRC_ELEMENT_3,
6551 &repName, (xmlSchemaTypePtr) ret, node, child,
6552 "The attribute 'type' and the <complexType> child are "
6553 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006554 } else
Daniel Veillard3646d642004-06-02 19:19:14 +00006555 ret->subtypes = xmlSchemaParseComplexType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00006556 child = child->next;
6557 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006558 /*
6559 * 3.3.3 : 3
6560 * "type" and either <simpleType> or <complexType> are
6561 * mutually exclusive
6562 */
William M. Bracke7091952004-05-11 15:09:58 +00006563 if (ret->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006564 xmlSchemaPContentErr(ctxt,
6565 XML_SCHEMAP_SRC_ELEMENT_3,
6566 &repName, (xmlSchemaTypePtr) ret, node, child,
6567 "The attribute 'type' and the <simpleType> child are "
6568 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006569 } else
Daniel Veillard3646d642004-06-02 19:19:14 +00006570 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00006571 child = child->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006572 }
William M. Bracke7091952004-05-11 15:09:58 +00006573 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00006574 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006575#ifdef IDC_ENABLED
6576 if (IS_SCHEMA(child, "unique")) {
6577 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
6578 XML_SCHEMA_TYPE_IDC_UNIQUE, ret->targetNamespace);
6579 } else if (IS_SCHEMA(child, "key")) {
6580 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
6581 XML_SCHEMA_TYPE_IDC_KEY, ret->targetNamespace);
6582 } else if (IS_SCHEMA(child, "keyref")) {
6583 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
6584 XML_SCHEMA_TYPE_IDC_KEYREF, ret->targetNamespace);
6585 }
6586 if (lastIDC != NULL)
6587 lastIDC->next = curIDC;
6588 else
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006589 ret->idcs = (void *) curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006590 lastIDC = curIDC;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006591#else
6592 TODO
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006593#endif
6594 child = child->next;
William M. Bracke7091952004-05-11 15:09:58 +00006595 }
6596 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006597 xmlSchemaPContentErr(ctxt,
6598 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6599 &repName, (xmlSchemaTypePtr) ret, node, child,
6600 NULL, "(annotation?, ((simpleType | complexType)?, "
6601 "(unique | key | keyref)*))");
6602 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006603
Daniel Veillardc0826a72004-08-10 14:17:33 +00006604 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006605 ctxt->container = oldcontainer;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006606 /*
6607 * Cleanup.
6608 */
6609 if (repName != NULL)
6610 xmlFree(repName);
6611 /*
6612 * NOTE: Element Declaration Representation OK 4. will be checked at a
6613 * different layer.
6614 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006615 return (ret);
6616}
6617
6618/**
6619 * xmlSchemaParseUnion:
6620 * @ctxt: a schema validation context
6621 * @schema: the schema being built
6622 * @node: a subtree containing XML Schema informations
6623 *
6624 * parse a XML schema Union definition
6625 * *WARNING* this interface is highly subject to change
6626 *
William M. Bracke7091952004-05-11 15:09:58 +00006627 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00006628 * 1 in case of success.
6629 */
6630static xmlSchemaTypePtr
6631xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006632 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006633{
6634 xmlSchemaTypePtr type, subtype, last = NULL;
6635 xmlNodePtr child = NULL;
6636 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00006637 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006638
6639 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6640 return (NULL);
6641
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006642 snprintf((char *) name, 30, "#union%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00006643 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006644 if (type == NULL)
6645 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00006646 type->type = XML_SCHEMA_TYPE_UNION;
Daniel Veillard4255d502002-04-16 15:50:10 +00006647 type->node = node;
William M. Brack2f2a6632004-08-20 23:09:47 +00006648 /*
6649 * Check for illegal attributes.
6650 */
6651 attr = node->properties;
6652 while (attr != NULL) {
6653 if (attr->ns == NULL) {
6654 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6655 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
6656 xmlSchemaPIllegalAttrErr(ctxt,
6657 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6658 NULL, type, attr);
6659 }
6660 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6661 xmlSchemaPIllegalAttrErr(ctxt,
6662 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6663 NULL, type, attr);
6664 }
6665 attr = attr->next;
6666 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006667 type->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00006668 /*
6669 * Attribute "memberTypes". This is a list of QNames.
6670 * TODO: Validate the QNames.
6671 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00006672 type->base = xmlSchemaGetProp(ctxt, node, "memberTypes");
William M. Brack2f2a6632004-08-20 23:09:47 +00006673 /*
6674 * And now for the children...
6675 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006676 child = node->children;
6677 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006678 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6679 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006680 }
William M. Brack2f2a6632004-08-20 23:09:47 +00006681 while (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006682 subtype = (xmlSchemaTypePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00006683 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006684 if (subtype != NULL) {
6685 if (last == NULL) {
6686 type->subtypes = subtype;
6687 last = subtype;
6688 } else {
6689 last->next = subtype;
6690 last = subtype;
6691 }
6692 last->next = NULL;
6693 }
6694 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006695 }
6696 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006697 /* TODO: Think about the error code. */
6698 xmlSchemaPContentErr(ctxt,
6699 XML_SCHEMAP_UNKNOWN_UNION_CHILD,
6700 NULL, type, node, child, NULL, "(annotation?, simpleType*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006701 }
6702 return (type);
6703}
6704
6705/**
6706 * xmlSchemaParseList:
6707 * @ctxt: a schema validation context
6708 * @schema: the schema being built
6709 * @node: a subtree containing XML Schema informations
6710 *
6711 * parse a XML schema List definition
6712 * *WARNING* this interface is highly subject to change
6713 *
William M. Bracke7091952004-05-11 15:09:58 +00006714 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00006715 * 1 in case of success.
6716 */
6717static xmlSchemaTypePtr
6718xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006719 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006720{
6721 xmlSchemaTypePtr type, subtype;
6722 xmlNodePtr child = NULL;
6723 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00006724 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006725
6726 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6727 return (NULL);
6728
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006729 snprintf((char *) name, 30, "#list%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00006730 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006731 if (type == NULL)
6732 return (NULL);
6733 type->node = node;
6734 type->type = XML_SCHEMA_TYPE_LIST;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006735 type->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00006736 /*
6737 * Check for illegal attributes.
6738 */
6739 attr = node->properties;
6740 while (attr != NULL) {
6741 if (attr->ns == NULL) {
6742 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6743 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
6744 xmlSchemaPIllegalAttrErr(ctxt,
6745 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6746 NULL, type, attr);
6747 }
6748 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6749 xmlSchemaPIllegalAttrErr(ctxt,
6750 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6751 NULL, type, attr);
6752 }
6753 attr = attr->next;
6754 }
6755 /*
6756 * Attribute "itemType".
6757 */
6758 xmlSchemaPValAttrQName(ctxt, schema, NULL, NULL,
6759 node, "itemType", &(type->baseNs), NULL, &(type->base));
6760 /*
6761 * And now for the children...
6762 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006763 child = node->children;
6764 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006765 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6766 child = child->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00006767 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006768 subtype = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00006769 if (IS_SCHEMA(child, "simpleType")) {
6770 if (type->base != NULL) {
6771 xmlSchemaPCustomErr(ctxt,
6772 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
6773 NULL, type, node,
6774 "The attribute 'itemType' and the <simpleType> child "
6775 "are mutually exclusive", NULL);
6776 } else {
6777 subtype = (xmlSchemaTypePtr)
6778 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
6779 type->subtypes = subtype;
6780 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00006781 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006782 }
6783 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006784 /* TODO: Think about the error code. */
6785 xmlSchemaPContentErr(ctxt,
6786 XML_SCHEMAP_UNKNOWN_LIST_CHILD,
6787 NULL, type, node, child, NULL, "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006788 }
6789 return (type);
6790}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006791
Daniel Veillard4255d502002-04-16 15:50:10 +00006792/**
6793 * xmlSchemaParseSimpleType:
6794 * @ctxt: a schema validation context
6795 * @schema: the schema being built
6796 * @node: a subtree containing XML Schema informations
6797 *
6798 * parse a XML schema Simple Type definition
6799 * *WARNING* this interface is highly subject to change
6800 *
William M. Bracke7091952004-05-11 15:09:58 +00006801 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardc0826a72004-08-10 14:17:33 +00006802 * 1 in case of success.
Daniel Veillard4255d502002-04-16 15:50:10 +00006803 */
6804static xmlSchemaTypePtr
6805xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00006806 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006807{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006808 xmlSchemaTypePtr type, subtype, oldCtxtType, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00006809 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006810 const xmlChar *attrValue = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006811 xmlChar *des = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006812 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006813
6814 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6815 return (NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006816
Daniel Veillardc0826a72004-08-10 14:17:33 +00006817 if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006818 attr = xmlSchemaGetPropNode(node, "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006819 if (attr == NULL) {
6820 xmlSchemaPMissingAttrErr(ctxt,
6821 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006822 (xmlChar **) &xmlSchemaElemDesST, NULL, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006823 "name", NULL);
6824 return (NULL);
6825 } else if (xmlSchemaPValAttrNode(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006826 (xmlChar **) &xmlSchemaElemDesST, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006827 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00006828 return (NULL);
6829 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006830 }
6831
6832 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006833 char buf[40];
Daniel Veillardc0826a72004-08-10 14:17:33 +00006834
Daniel Veillard01fa6152004-06-29 17:04:39 +00006835 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006836 * Parse as local simple type definition.
Daniel Veillard01fa6152004-06-29 17:04:39 +00006837 */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006838 snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00006839 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006840 if (type == NULL)
6841 return (NULL);
6842 type->node = node;
6843 type->type = XML_SCHEMA_TYPE_SIMPLE;
6844 /*
6845 * Check for illegal attributes.
6846 */
6847 attr = node->properties;
6848 while (attr != NULL) {
6849 if (attr->ns == NULL) {
6850 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
6851 xmlSchemaPIllegalAttrErr(ctxt,
6852 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006853 &des, type, attr);
Daniel Veillard01fa6152004-06-29 17:04:39 +00006854 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006855 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6856 xmlSchemaPIllegalAttrErr(ctxt,
6857 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006858 &des, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006859 }
6860 attr = attr->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +00006861 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006862 } else {
6863 /*
6864 * Parse as global simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006865 *
6866 * Note that attrValue is the value of the attribute "name" here.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006867 */
William M. Brack2f2a6632004-08-20 23:09:47 +00006868 type = xmlSchemaAddType(ctxt, schema, attrValue, schema->targetNamespace, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006869 if (type == NULL)
6870 return (NULL);
6871 type->node = node;
6872 type->type = XML_SCHEMA_TYPE_SIMPLE;
6873 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
6874 /*
6875 * Check for illegal attributes.
6876 */
6877 attr = node->properties;
6878 while (attr != NULL) {
6879 if (attr->ns == NULL) {
6880 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6881 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006882 (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006883 xmlSchemaPIllegalAttrErr(ctxt,
6884 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006885 &des, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006886 }
6887 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6888 xmlSchemaPIllegalAttrErr(ctxt,
6889 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006890 &des, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006891 }
6892 attr = attr->next;
6893 }
6894 /*
6895 * Attribute "final".
6896 */
6897 attr = xmlSchemaGetPropNode(node, "final");
6898 if (attr == NULL) {
6899 type->flags |= XML_SCHEMAS_TYPE_FINAL_DEFAULT;
6900 } else {
6901 attrValue = xmlSchemaGetProp(ctxt, node, "final");
6902 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
6903 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
6904 XML_SCHEMAS_TYPE_FINAL_LIST,
6905 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
6906
6907 xmlSchemaPSimpleTypeErr(ctxt,
6908 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006909 &des, type, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00006910 NULL, "(#all | List of (list | union | restriction)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00006911 attrValue, NULL, NULL, NULL);
6912 }
6913 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006914 }
6915 type->targetNamespace = schema->targetNamespace;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006916 /* TODO: Check id. */
6917 type->id = xmlSchemaGetProp(ctxt, node, "id");
6918 /*
6919 * And now for the children...
6920 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006921 oldCtxtType = ctxt->ctxtType;
6922 oldParentItem = ctxt->parentItem;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006923 ctxt->ctxtType = type;
6924 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00006925 child = node->children;
6926 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006927 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6928 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006929 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006930 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00006931 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006932 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00006933 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006934 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006935 } else if (IS_SCHEMA(child, "list")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006936 subtype = (xmlSchemaTypePtr)
6937 xmlSchemaParseList(ctxt, schema, child);
6938 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006939 } else if (IS_SCHEMA(child, "union")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006940 subtype = (xmlSchemaTypePtr)
6941 xmlSchemaParseUnion(ctxt, schema, child);
6942 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006943 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006944 type->subtypes = subtype;
6945 if ((child != NULL) || (subtype == NULL)) {
6946 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006947 &des, type, node, child, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006948 "(annotation?, (restriction | list | union))");
Daniel Veillard4255d502002-04-16 15:50:10 +00006949 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006950 ctxt->parentItem = oldParentItem;
6951 ctxt->ctxtType = oldCtxtType;
6952 FREE_AND_NULL(des)
Daniel Veillard01fa6152004-06-29 17:04:39 +00006953
Daniel Veillard4255d502002-04-16 15:50:10 +00006954 return (type);
6955}
6956
6957
6958/**
6959 * xmlSchemaParseGroup:
6960 * @ctxt: a schema validation context
6961 * @schema: the schema being built
6962 * @node: a subtree containing XML Schema informations
6963 *
6964 * parse a XML schema Group definition
6965 * *WARNING* this interface is highly subject to change
6966 *
William M. Bracke7091952004-05-11 15:09:58 +00006967 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00006968 * 1 in case of success.
6969 */
6970static xmlSchemaTypePtr
6971xmlSchemaParseGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00006972 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006973{
6974 xmlSchemaTypePtr type, subtype;
6975 xmlNodePtr child = NULL;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006976 const xmlChar *name, *ns = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006977 const xmlChar *ref = NULL, *refNs = NULL;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006978 char buf[50];
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00006979 int minOccurs, maxOccurs;
Daniel Veillard4255d502002-04-16 15:50:10 +00006980
6981 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6982 return (NULL);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00006983 /*
6984 * TODO: Validate the element even if no item is created
6985 * (i.e. min/maxOccurs == 0).
6986 */
6987 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
6988 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(nonNegativeInteger | unbounded)");
6989 if ((minOccurs == 0) && (maxOccurs == 0)) {
6990 return (NULL);
6991 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006992 if (topLevel)
6993 ns = schema->targetNamespace;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006994 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00006995 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006996 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
6997 if (ref == NULL) {
6998 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006999 XML_SCHEMAP_GROUP_NONAME_NOREF,
7000 "Group definition or particle: One of the attributes \"name\" "
7001 "or \"ref\" must be present.\n", NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007002 return (NULL);
7003 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007004 if (refNs == NULL)
7005 refNs = schema->targetNamespace;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00007006 snprintf(buf, 49, "#grRef%d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007007 name = (const xmlChar *) buf;
Daniel Veillard4255d502002-04-16 15:50:10 +00007008 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00007009 type = xmlSchemaAddGroup(ctxt, schema, name, ns, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007010 if (type == NULL)
7011 return (NULL);
7012 type->node = node;
7013 type->type = XML_SCHEMA_TYPE_GROUP;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00007014 if (topLevel)
7015 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007016 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00007017 type->ref = ref;
7018 type->refNs = refNs;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00007019 type->minOccurs = minOccurs;
7020 type->maxOccurs = maxOccurs;
7021 xmlSchemaPCheckParticleCorrect_2(ctxt, type,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007022 node, type->minOccurs, type->maxOccurs);
Daniel Veillard4255d502002-04-16 15:50:10 +00007023
7024 child = node->children;
7025 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007026 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7027 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007028 }
7029 subtype = NULL;
7030 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007031 subtype = (xmlSchemaTypePtr)
7032 xmlSchemaParseAll(ctxt, schema, child);
7033 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007034 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007035 subtype = xmlSchemaParseChoice(ctxt, schema, child);
7036 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007037 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007038 subtype = (xmlSchemaTypePtr)
7039 xmlSchemaParseSequence(ctxt, schema, child);
7040 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007041 }
7042 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007043 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00007044 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007045 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_GROUP_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007046 "Group definition \"%s\" has unexpected content.\n", type->name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007047 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007048 }
7049
7050 return (type);
7051}
7052
7053/**
7054 * xmlSchemaParseAll:
7055 * @ctxt: a schema validation context
7056 * @schema: the schema being built
7057 * @node: a subtree containing XML Schema informations
7058 *
7059 * parse a XML schema All definition
7060 * *WARNING* this interface is highly subject to change
7061 *
William M. Bracke7091952004-05-11 15:09:58 +00007062 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00007063 * 1 in case of success.
7064 */
7065static xmlSchemaTypePtr
7066xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007067 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007068{
7069 xmlSchemaTypePtr type, subtype, last = NULL;
7070 xmlNodePtr child = NULL;
7071 xmlChar name[30];
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00007072 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007073
7074 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7075 return (NULL);
7076
7077
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00007078 snprintf((char *) name, 30, "#all%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007079 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007080 if (type == NULL)
7081 return (NULL);
7082 type->node = node;
Daniel Veillard7646b182002-04-20 06:41:40 +00007083 type->type = XML_SCHEMA_TYPE_ALL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007084 type->id = xmlSchemaGetProp(ctxt, node, "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007085
7086 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
7087 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00007088
7089 oldcontainer = ctxt->container;
7090 ctxt->container = (const xmlChar *) name;
Daniel Veillard4255d502002-04-16 15:50:10 +00007091 child = node->children;
7092 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007093 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7094 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007095 }
7096 while (IS_SCHEMA(child, "element")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007097 subtype = (xmlSchemaTypePtr)
7098 xmlSchemaParseElement(ctxt, schema, child, 0);
7099 if (subtype != NULL) {
William M. Brackb15351e2003-12-27 04:34:42 +00007100 if (subtype->minOccurs > 1)
7101 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MINOCCURS,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007102 "invalid value for minOccurs (must be 0 or 1).\n",
William M. Brackb15351e2003-12-27 04:34:42 +00007103 NULL, NULL);
7104 if (subtype->maxOccurs > 1)
7105 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MAXOCCURS,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007106 "invalid value for maxOccurs (must be 0 or 1).\n",
William M. Brackb15351e2003-12-27 04:34:42 +00007107 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007108 if (last == NULL) {
7109 type->subtypes = subtype;
7110 last = subtype;
7111 } else {
7112 last->next = subtype;
7113 last = subtype;
7114 }
7115 last->next = NULL;
7116 }
7117 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007118 }
7119 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007120 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ALL_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007121 "<all> has unexpected content.\n", type->name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007122 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007123 }
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00007124 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007125 return (type);
7126}
7127
7128/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007129 * xmlSchemaCleanupDoc:
7130 * @ctxt: a schema validation context
7131 * @node: the root of the document.
7132 *
7133 * removes unwanted nodes in a schemas document tree
7134 */
7135static void
7136xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
7137{
7138 xmlNodePtr delete, cur;
7139
7140 if ((ctxt == NULL) || (root == NULL)) return;
7141
7142 /*
7143 * Remove all the blank text nodes
7144 */
7145 delete = NULL;
7146 cur = root;
7147 while (cur != NULL) {
7148 if (delete != NULL) {
7149 xmlUnlinkNode(delete);
7150 xmlFreeNode(delete);
7151 delete = NULL;
7152 }
7153 if (cur->type == XML_TEXT_NODE) {
7154 if (IS_BLANK_NODE(cur)) {
7155 if (xmlNodeGetSpacePreserve(cur) != 1) {
7156 delete = cur;
7157 }
7158 }
7159 } else if ((cur->type != XML_ELEMENT_NODE) &&
7160 (cur->type != XML_CDATA_SECTION_NODE)) {
7161 delete = cur;
7162 goto skip_children;
7163 }
7164
7165 /*
7166 * Skip to next node
7167 */
7168 if (cur->children != NULL) {
7169 if ((cur->children->type != XML_ENTITY_DECL) &&
7170 (cur->children->type != XML_ENTITY_REF_NODE) &&
7171 (cur->children->type != XML_ENTITY_NODE)) {
7172 cur = cur->children;
7173 continue;
7174 }
7175 }
7176 skip_children:
7177 if (cur->next != NULL) {
7178 cur = cur->next;
7179 continue;
7180 }
7181
7182 do {
7183 cur = cur->parent;
7184 if (cur == NULL)
7185 break;
7186 if (cur == root) {
7187 cur = NULL;
7188 break;
7189 }
7190 if (cur->next != NULL) {
7191 cur = cur->next;
7192 break;
7193 }
7194 } while (cur != NULL);
7195 }
7196 if (delete != NULL) {
7197 xmlUnlinkNode(delete);
7198 xmlFreeNode(delete);
7199 delete = NULL;
7200 }
7201}
7202
William M. Brack2f2a6632004-08-20 23:09:47 +00007203
7204/**
7205 * xmlSchemaImportSchema
7206 *
7207 * @ctxt: a schema validation context
7208 * @schemaLocation: an URI defining where to find the imported schema
7209 *
7210 * import a XML schema
7211 * *WARNING* this interface is highly subject to change
7212 *
7213 * Returns -1 in case of error and 1 in case of success.
7214 */
7215#if 0
7216static xmlSchemaImportPtr
7217xmlSchemaImportSchema(xmlSchemaParserCtxtPtr ctxt,
7218 const xmlChar *schemaLocation)
7219{
7220 xmlSchemaImportPtr import;
7221 xmlSchemaParserCtxtPtr newctxt;
7222
7223 newctxt = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
7224 if (newctxt == NULL) {
7225 xmlSchemaPErrMemory(ctxt, "allocating schema parser context",
7226 NULL);
7227 return (NULL);
7228 }
7229 memset(newctxt, 0, sizeof(xmlSchemaParserCtxt));
7230 /* Keep the same dictionnary for parsing, really */
7231 xmlDictReference(ctxt->dict);
7232 newctxt->dict = ctxt->dict;
7233 newctxt->includes = 0;
7234 newctxt->URL = xmlDictLookup(newctxt->dict, schemaLocation, -1);
7235
7236 xmlSchemaSetParserErrors(newctxt, ctxt->error, ctxt->warning,
7237 ctxt->userData);
7238
7239 import = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
7240 if (import == NULL) {
7241 xmlSchemaPErrMemory(NULL, "allocating imported schema",
7242 NULL);
7243 xmlSchemaFreeParserCtxt(newctxt);
7244 return (NULL);
7245 }
7246
7247 memset(import, 0, sizeof(xmlSchemaImport));
7248 import->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
7249 import->schema = xmlSchemaParse(newctxt);
7250
7251 if (import->schema == NULL) {
7252 /* FIXME use another error enum here ? */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00007253 xmlSchemaPErr(ctxt, NULL, XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00007254 "Failed to import schema from location \"%s\".\n",
7255 schemaLocation, NULL);
7256
7257 xmlSchemaFreeParserCtxt(newctxt);
7258 /* The schemaLocation is held by the dictionary.
7259 if (import->schemaLocation != NULL)
7260 xmlFree((xmlChar *)import->schemaLocation);
7261 */
7262 xmlFree(import);
7263 return NULL;
7264 }
7265
7266 xmlSchemaFreeParserCtxt(newctxt);
7267 return import;
7268}
7269#endif
7270
7271static void
7272xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
7273{
7274 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
7275 schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
7276
7277 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
7278 schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
7279
7280 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
7281 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
7282 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
7283 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
7284 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
7285 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
7286 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
7287 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
7288
7289 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
7290 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
7291 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
7292 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
7293 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
7294 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
7295}
7296
7297static void
7298xmlSchemaParseSchemaDefaults(xmlSchemaParserCtxtPtr ctxt,
7299 xmlSchemaPtr schema,
7300 xmlNodePtr node)
7301{
7302 xmlAttrPtr attr;
7303 const xmlChar *val;
7304
7305 attr = xmlSchemaGetPropNode(node, "elementFormDefault");
7306 if (attr != NULL) {
7307 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7308 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
7309 XML_SCHEMAS_QUALIF_ELEM) != 0) {
7310 xmlSchemaPSimpleTypeErr(ctxt,
7311 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
7312 NULL, NULL, (xmlNodePtr) attr, NULL,
7313 "(qualified | unqualified)", val, NULL, NULL, NULL);
7314 }
7315 }
7316
7317 attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
7318 if (attr != NULL) {
7319 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7320 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
7321 XML_SCHEMAS_QUALIF_ATTR) != 0) {
7322 xmlSchemaPSimpleTypeErr(ctxt,
7323 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
7324 NULL, NULL, (xmlNodePtr) attr, NULL,
7325 "(qualified | unqualified)", val, NULL, NULL, NULL);
7326 }
7327 }
7328
7329 attr = xmlSchemaGetPropNode(node, "finalDefault");
7330 if (attr != NULL) {
7331 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7332 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
7333 XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
7334 XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
7335 -1,
7336 XML_SCHEMAS_FINAL_DEFAULT_LIST,
7337 XML_SCHEMAS_FINAL_DEFAULT_UNION) != 0) {
7338 xmlSchemaPSimpleTypeErr(ctxt,
7339 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7340 NULL, NULL, (xmlNodePtr) attr, NULL,
7341 "(#all | List of (extension | restriction | list | union))",
7342 val, NULL, NULL, NULL);
7343 }
7344 }
7345
7346 attr = xmlSchemaGetPropNode(node, "blockDefault");
7347 if (attr != NULL) {
7348 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7349 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
7350 XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
7351 XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
7352 XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1) != 0) {
7353 xmlSchemaPSimpleTypeErr(ctxt,
7354 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7355 NULL, NULL, (xmlNodePtr) attr, NULL,
7356 "(#all | List of (extension | restriction | substitution))",
7357 val, NULL, NULL, NULL);
7358 }
7359 }
7360}
7361
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007362/**
7363 * xmlSchemaParseSchemaTopLevel:
7364 * @ctxt: a schema validation context
7365 * @schema: the schemas
7366 * @nodes: the list of top level nodes
7367 *
7368 * Returns the internal XML Schema structure built from the resource or
7369 * NULL in case of error
7370 */
7371static void
7372xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
7373 xmlSchemaPtr schema, xmlNodePtr nodes)
7374{
7375 xmlNodePtr child;
7376 xmlSchemaAnnotPtr annot;
7377
7378 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
7379 return;
7380
7381 child = nodes;
7382 while ((IS_SCHEMA(child, "include")) ||
7383 (IS_SCHEMA(child, "import")) ||
7384 (IS_SCHEMA(child, "redefine")) ||
7385 (IS_SCHEMA(child, "annotation"))) {
7386 if (IS_SCHEMA(child, "annotation")) {
7387 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7388 if (schema->annot == NULL)
7389 schema->annot = annot;
7390 else
7391 xmlSchemaFreeAnnot(annot);
7392 } else if (IS_SCHEMA(child, "import")) {
7393 xmlSchemaParseImport(ctxt, schema, child);
7394 } else if (IS_SCHEMA(child, "include")) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00007395 ctxt->includes++;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007396 xmlSchemaParseInclude(ctxt, schema, child);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00007397 ctxt->includes--;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007398 } else if (IS_SCHEMA(child, "redefine")) {
7399 TODO
7400 }
7401 child = child->next;
7402 }
7403 while (child != NULL) {
7404 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007405 xmlSchemaParseComplexType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007406 child = child->next;
7407 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007408 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007409 child = child->next;
7410 } else if (IS_SCHEMA(child, "element")) {
7411 xmlSchemaParseElement(ctxt, schema, child, 1);
7412 child = child->next;
7413 } else if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00007414 xmlSchemaParseAttribute(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007415 child = child->next;
7416 } else if (IS_SCHEMA(child, "attributeGroup")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007417 xmlSchemaParseAttributeGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007418 child = child->next;
7419 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007420 xmlSchemaParseGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007421 child = child->next;
7422 } else if (IS_SCHEMA(child, "notation")) {
7423 xmlSchemaParseNotation(ctxt, schema, child);
7424 child = child->next;
7425 } else {
7426 xmlSchemaPErr2(ctxt, NULL, child,
7427 XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007428 "Unexpected element \"%s\" as child of <schema>.\n",
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007429 child->name, NULL);
7430 child = child->next;
7431 }
7432 while (IS_SCHEMA(child, "annotation")) {
7433 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7434 if (schema->annot == NULL)
7435 schema->annot = annot;
7436 else
7437 xmlSchemaFreeAnnot(annot);
7438 child = child->next;
7439 }
7440 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00007441 ctxt->parentItem = NULL;
7442 ctxt->ctxtType = NULL;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007443}
7444
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007445static xmlSchemaImportPtr
7446xmlSchemaAddImport(xmlSchemaParserCtxtPtr ctxt,
7447 xmlHashTablePtr *imports,
7448 const xmlChar *nsName)
7449{
7450 xmlSchemaImportPtr ret;
7451
7452 if (*imports == NULL) {
Daniel Veillardb9e2f262005-01-23 23:48:34 +00007453 *imports = xmlHashCreateDict(10, ctxt->dict);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007454 if (*imports == NULL) {
7455 xmlSchemaPCustomErr(ctxt,
7456 XML_SCHEMAP_FAILED_BUILD_IMPORT,
7457 NULL, NULL, (xmlNodePtr) ctxt->doc,
7458 "Internal error: failed to build the import table",
7459 NULL);
7460 return (NULL);
7461 }
7462 }
7463 ret = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
7464 if (ret == NULL) {
7465 xmlSchemaPErrMemory(NULL, "allocating import struct", NULL);
7466 return (NULL);
7467 }
7468 memset(ret, 0, sizeof(xmlSchemaImport));
7469 if (nsName == NULL)
7470 nsName = XML_SCHEMAS_NO_NAMESPACE;
7471 xmlHashAddEntry(*imports, nsName, ret);
7472
7473 return (ret);
7474}
7475
7476static int
7477xmlSchemaAcquireSchemaDoc(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007478 xmlSchemaPtr schema,
7479 xmlNodePtr node,
7480 const xmlChar *nsName,
7481 const xmlChar *location,
7482 xmlDocPtr *doc,
7483 const xmlChar **targetNamespace,
7484 int absolute)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007485{
7486 xmlParserCtxtPtr parserCtxt;
7487 xmlSchemaImportPtr import;
7488 const xmlChar *ns;
7489 xmlNodePtr root;
7490
7491 /*
7492 * NOTE: This will be used for <import>, <xsi:schemaLocation> and
7493 * <xsi:noNamespaceSchemaLocation>.
7494 */
7495 *doc = NULL;
7496 /*
7497 * Given that the schemaLocation [attribute] is only a hint, it is open
7498 * to applications to ignore all but the first <import> for a given
7499 * namespace, regardless of the ·actual value· of schemaLocation, but
7500 * such a strategy risks missing useful information when new
7501 * schemaLocations are offered.
7502 *
7503 * XSV (ver 2.5-2) does use the first <import> which resolves to a valid schema.
7504 * Xerces-J (ver 2.5.1) ignores all but the first given <import> - regardless if
7505 * valid or not.
7506 * We will follow XSV here.
7507 */
7508 if (location == NULL) {
7509 /*
7510 * Schema Document Location Strategy:
7511 *
7512 * 3 Based on the namespace name, identify an existing schema document,
7513 * either as a resource which is an XML document or a <schema> element
7514 * information item, in some local schema repository;
7515 *
7516 * 5 Attempt to resolve the namespace name to locate such a resource.
7517 *
7518 * NOTE: Those stategies are not supported, so we will skip.
7519 */
7520 return (0);
7521 }
7522 if (nsName == NULL)
7523 ns = XML_SCHEMAS_NO_NAMESPACE;
7524 else
7525 ns = nsName;
7526
7527 import = xmlHashLookup(schema->schemasImports, ns);
7528 if (import != NULL) {
7529 /*
7530 * There was a valid resource for the specified namespace already
7531 * defined, so skip.
7532 * TODO: This might be changed someday to allow import of
7533 * components from multiple documents for a single target namespace.
7534 */
7535 return (0);
7536 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007537
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007538 /*
7539 * Schema Document Location Strategy:
7540 *
7541 * 2 Based on the location URI, identify an existing schema document,
7542 * either as a resource which is an XML document or a <schema> element
7543 * information item, in some local schema repository;
7544 *
7545 * 4 Attempt to resolve the location URI, to locate a resource on the
7546 * web which is or contains or references a <schema> element;
7547 * TODO: Hmm, I don't know if the reference stuff in 4. will work.
7548 *
7549 */
7550 if ((absolute == 0) && (node != NULL)) {
7551 xmlChar *base, *URI;
7552
7553 base = xmlNodeGetBase(node->doc, node);
7554 if (base == NULL) {
7555 URI = xmlBuildURI(location, node->doc->URL);
7556 } else {
7557 URI = xmlBuildURI(location, base);
7558 xmlFree(base);
7559 }
7560 if (URI != NULL) {
7561 location = xmlDictLookup(ctxt->dict, URI, -1);
7562 xmlFree(URI);
7563 }
7564 }
7565 parserCtxt = xmlNewParserCtxt();
7566 if (parserCtxt == NULL) {
7567 xmlSchemaPErrMemory(NULL, "xmlSchemaParseImport: "
7568 "allocating a parser context", NULL);
7569 return(-1);
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00007570 }
7571
7572 if ((ctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
7573 xmlDictFree(parserCtxt->dict);
7574 parserCtxt->dict = ctxt->dict;
7575 xmlDictReference(parserCtxt->dict);
7576 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007577
7578 *doc = xmlCtxtReadFile(parserCtxt, (const char *) location,
7579 NULL, SCHEMAS_PARSE_OPTIONS);
7580
7581 /*
7582 * 2.1 The referent is (a fragment of) a resource which is an
7583 * XML document (see clause 1.1), which in turn corresponds to
7584 * a <schema> element information item in a well-formed information
7585 * set, which in turn corresponds to a valid schema.
7586 * TODO: What to do with the "fragment" stuff?
7587 *
7588 * 2.2 The referent is a <schema> element information item in
7589 * a well-formed information set, which in turn corresponds
7590 * to a valid schema.
7591 * NOTE: 2.2 won't apply, since only XML documents will be processed
7592 * here.
7593 */
7594 if (*doc == NULL) {
7595 xmlErrorPtr lerr;
7596 /*
7597 * It is *not* an error for the application schema reference
7598 * strategy to fail.
7599 *
7600 * If the doc is NULL and the parser error is an IO error we
7601 * will assume that the resource could not be located or accessed.
7602 *
7603 * TODO: Try to find specific error codes to react only on
7604 * localisation failures.
7605 *
7606 * TODO, FIXME: Check the spec: is a namespace added to the imported
7607 * namespaces, even if the schemaLocation did not provide
7608 * a resource? I guess so, since omitting the "schemaLocation"
7609 * attribute, imports a namespace as well.
7610 */
7611 lerr = xmlGetLastError();
7612 if ((lerr != NULL) && (lerr->domain == XML_FROM_IO)) {
7613 xmlFreeParserCtxt(parserCtxt);
7614 return(0);
7615 }
7616
7617 xmlSchemaPCustomErr(ctxt,
7618 XML_SCHEMAP_SRC_IMPORT_2_1,
7619 NULL, NULL, node,
7620 "Failed to parse the resource '%s' for import",
7621 location);
7622 xmlFreeParserCtxt(parserCtxt);
7623 return(XML_SCHEMAP_SRC_IMPORT_2_1);
7624 }
7625 xmlFreeParserCtxt(parserCtxt);
7626
7627 root = xmlDocGetRootElement(*doc);
7628 if (root == NULL) {
7629 xmlSchemaPCustomErr(ctxt,
7630 XML_SCHEMAP_SRC_IMPORT_2_1,
7631 NULL, NULL, node,
7632 "The XML document '%s' to be imported has no document "
7633 "element", location);
7634 xmlFreeDoc(*doc);
7635 *doc = NULL;
7636 return (XML_SCHEMAP_SRC_IMPORT_2_1);
7637 }
7638
7639 xmlSchemaCleanupDoc(ctxt, root);
7640
7641 if (!IS_SCHEMA(root, "schema")) {
7642 xmlSchemaPCustomErr(ctxt,
7643 XML_SCHEMAP_SRC_IMPORT_2_1,
7644 NULL, NULL, node,
7645 "The XML document '%s' to be imported is not a XML schema document",
7646 location);
7647 xmlFreeDoc(*doc);
7648 *doc = NULL;
7649 return (XML_SCHEMAP_SRC_IMPORT_2_1);
7650 }
7651 *targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
7652 /*
7653 * Schema Representation Constraint: Import Constraints and Semantics
7654 */
7655 if (nsName == NULL) {
7656 if (*targetNamespace != NULL) {
7657 xmlSchemaPCustomErr(ctxt,
7658 XML_SCHEMAP_SRC_IMPORT_3_2,
7659 NULL, NULL, node,
7660 "The XML schema to be imported is not expected "
7661 "to have a target namespace; this differs from "
7662 "its target namespace of '%s'", *targetNamespace);
7663 xmlFreeDoc(*doc);
7664 *doc = NULL;
7665 return (XML_SCHEMAP_SRC_IMPORT_3_2);
7666 }
7667 } else {
7668 if (*targetNamespace == NULL) {
7669 xmlSchemaPCustomErr(ctxt,
7670 XML_SCHEMAP_SRC_IMPORT_3_1,
7671 NULL, NULL, node,
7672 "The XML schema to be imported is expected to have a target "
7673 "namespace of '%s'", nsName);
7674 xmlFreeDoc(*doc);
7675 *doc = NULL;
7676 return (XML_SCHEMAP_SRC_IMPORT_3_1);
7677 } else if (!xmlStrEqual(*targetNamespace, nsName)) {
7678 xmlSchemaPCustomErrExt(ctxt,
7679 XML_SCHEMAP_SRC_IMPORT_3_1,
7680 NULL, NULL, node,
7681 "The XML schema to be imported is expected to have a "
7682 "target namespace of '%s'; this differs from "
7683 "its target namespace of '%s'",
7684 nsName, *targetNamespace, NULL);
7685 xmlFreeDoc(*doc);
7686 *doc = NULL;
7687 return (XML_SCHEMAP_SRC_IMPORT_3_1);
7688 }
7689 }
7690
7691 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports), nsName);
7692 if (import == NULL) {
7693 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT,
7694 NULL, NULL, NULL,
7695 "Internal error: xmlSchemaAcquireSchemaDoc, "
7696 "failed to build import table", NULL);
7697 xmlFreeDoc(*doc);
7698 *doc = NULL;
7699 return (-1);
7700 }
7701 import->schemaLocation = location;
7702 import->doc = *doc;
7703 return (0);
7704}
William M. Brack2f2a6632004-08-20 23:09:47 +00007705
7706/**
7707 * xmlSchemaParseImport:
7708 * @ctxt: a schema validation context
7709 * @schema: the schema being built
7710 * @node: a subtree containing XML Schema informations
7711 *
7712 * parse a XML schema Import definition
7713 * *WARNING* this interface is highly subject to change
7714 *
7715 * Returns 0 in case of success, a positive error code if
7716 * not valid and -1 in case of an internal error.
7717 */
7718static int
7719xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
7720 xmlNodePtr node)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007721{
7722 xmlNodePtr child;
7723 const xmlChar *namespace = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00007724 const xmlChar *schemaLocation = NULL;
7725 const xmlChar *targetNamespace, *oldTNS, *url;
7726 xmlAttrPtr attr;
7727 xmlDocPtr doc;
7728 xmlNodePtr root;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007729 int flags, ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00007730
7731
7732 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7733 return (-1);
7734
7735 /*
7736 * Check for illegal attributes.
7737 */
7738 attr = node->properties;
7739 while (attr != NULL) {
7740 if (attr->ns == NULL) {
7741 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7742 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
7743 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
7744 xmlSchemaPIllegalAttrErr(ctxt,
7745 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7746 NULL, NULL, attr);
7747 }
7748 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7749 xmlSchemaPIllegalAttrErr(ctxt,
7750 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7751 NULL, NULL, attr);
7752 }
7753 attr = attr->next;
7754 }
7755 /*
7756 * Extract and validate attributes.
7757 */
7758 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
7759 "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
7760 &namespace) != 0) {
7761 xmlSchemaPSimpleTypeErr(ctxt,
7762 XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI,
7763 NULL, NULL, node,
7764 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
7765 NULL, namespace, NULL, NULL, NULL);
7766 return (XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI);
7767 }
7768
7769 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
7770 "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
7771 &schemaLocation) != 0) {
7772 xmlSchemaPSimpleTypeErr(ctxt,
7773 XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI,
7774 NULL, NULL, node,
7775 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
7776 NULL, namespace, NULL, NULL, NULL);
7777 return (XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI);
7778 }
7779 /*
7780 * And now for the children...
7781 */
7782 child = node->children;
7783 if (IS_SCHEMA(child, "annotation")) {
7784 /*
7785 * the annotation here is simply discarded ...
7786 */
7787 child = child->next;
7788 }
7789 if (child != NULL) {
7790 xmlSchemaPContentErr(ctxt,
7791 XML_SCHEMAP_UNKNOWN_IMPORT_CHILD,
7792 NULL, NULL, node, child, NULL,
7793 "(annotation?)");
7794 }
7795 /*
7796 * Apply additional constraints.
7797 */
7798 if (namespace != NULL) {
7799 /*
7800 * 1.1 If the namespace [attribute] is present, then its ·actual value·
7801 * must not match the ·actual value· of the enclosing <schema>'s
7802 * targetNamespace [attribute].
7803 */
7804 if (xmlStrEqual(schema->targetNamespace, namespace)) {
7805 xmlSchemaPCustomErr(ctxt,
7806 XML_SCHEMAP_SRC_IMPORT_1_1,
7807 NULL, NULL, node,
7808 "The value of the attribute 'namespace' must not match "
7809 "the target namespace '%s' of the importing schema",
7810 schema->targetNamespace);
7811 return (XML_SCHEMAP_SRC_IMPORT_1_1);
7812 }
7813 } else {
7814 /*
7815 * 1.2 If the namespace [attribute] is not present, then the enclosing
7816 * <schema> must have a targetNamespace [attribute].
7817 */
7818 if (schema->targetNamespace == NULL) {
7819 xmlSchemaPCustomErr(ctxt,
7820 XML_SCHEMAP_SRC_IMPORT_1_2,
7821 NULL, NULL, node,
7822 "The attribute 'namespace' must be existent if "
7823 "the importing schema has no target namespace",
7824 NULL);
7825 return (XML_SCHEMAP_SRC_IMPORT_1_2);
7826 }
7827 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007828 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007829 * Locate and aquire the schema document.
William M. Brack2f2a6632004-08-20 23:09:47 +00007830 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007831 ret = xmlSchemaAcquireSchemaDoc(ctxt, schema, node, namespace,
7832 schemaLocation, &doc, &targetNamespace, 0);
7833 if (ret != 0) {
7834 if (doc != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00007835 xmlFreeDoc(doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007836 return (ret);
7837 } else if (doc != NULL) {
7838 /*
7839 * Save and reset the context & schema.
7840 */
7841 url = ctxt->URL;
7842 /* TODO: Is using the doc->URL here correct? */
7843 ctxt->URL = doc->URL;
7844 flags = schema->flags;
7845 oldTNS = schema->targetNamespace;
7846 /*
7847 * Parse the schema.
7848 */
7849 root = xmlDocGetRootElement(doc);
7850 xmlSchemaClearSchemaDefaults(schema);
7851 xmlSchemaParseSchemaDefaults(ctxt, schema, root);
7852 schema->targetNamespace = targetNamespace;
7853 xmlSchemaParseSchemaTopLevel(ctxt, schema, root->children);
7854 /*
7855 * Restore the context & schema.
7856 */
7857 schema->flags = flags;
7858 schema->targetNamespace = oldTNS;
7859 ctxt->URL = url;
William M. Brack2f2a6632004-08-20 23:09:47 +00007860 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007861
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007862 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +00007863}
7864
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007865/**
7866 * xmlSchemaParseInclude:
7867 * @ctxt: a schema validation context
7868 * @schema: the schema being built
7869 * @node: a subtree containing XML Schema informations
7870 *
7871 * parse a XML schema Include definition
7872 *
William M. Bracke7091952004-05-11 15:09:58 +00007873 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007874 * 1 in case of success.
7875 */
7876static int
7877xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
7878 xmlNodePtr node)
7879{
7880 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007881 const xmlChar *schemaLocation, *targetNamespace;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007882 xmlDocPtr doc;
7883 xmlNodePtr root;
7884 xmlSchemaIncludePtr include;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007885 int wasConvertingNs = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00007886 xmlAttrPtr attr;
7887 int saveFlags;
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00007888 xmlParserCtxtPtr parserCtxt;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007889
7890
7891 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7892 return (-1);
7893
7894 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00007895 * Check for illegal attributes.
7896 */
7897 attr = node->properties;
7898 while (attr != NULL) {
7899 if (attr->ns == NULL) {
7900 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7901 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
7902 xmlSchemaPIllegalAttrErr(ctxt,
7903 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7904 NULL, NULL, attr);
7905 }
7906 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7907 xmlSchemaPIllegalAttrErr(ctxt,
7908 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7909 NULL, NULL, attr);
7910 }
7911 attr = attr->next;
7912 }
7913 /*
7914 * Extract and validate attributes.
7915 */
7916 /*
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007917 * Preliminary step, extract the URI-Reference for the include and
7918 * make an URI from the base.
7919 */
William M. Brack2f2a6632004-08-20 23:09:47 +00007920 attr = xmlSchemaGetPropNode(node, "schemaLocation");
7921 if (attr != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007922 xmlChar *base = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00007923 xmlChar *uri = NULL;
7924
7925 if (xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
7926 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &schemaLocation) != 0)
7927 return (-1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007928 base = xmlNodeGetBase(node->doc, node);
7929 if (base == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007930 uri = xmlBuildURI(schemaLocation, node->doc->URL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007931 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00007932 uri = xmlBuildURI(schemaLocation, base);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007933 xmlFree(base);
7934 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007935 if (uri != NULL) {
7936 schemaLocation = xmlDictLookup(ctxt->dict, uri, -1);
7937 xmlFree(uri);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007938 }
7939 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00007940 xmlSchemaPMissingAttrErr(ctxt,
7941 XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI,
7942 NULL, NULL, node, "schemaLocation", NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007943 return (-1);
7944 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007945 /*
7946 * And now for the children...
7947 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007948 child = node->children;
7949 while (IS_SCHEMA(child, "annotation")) {
7950 /*
7951 * the annotations here are simply discarded ...
7952 */
7953 child = child->next;
7954 }
7955 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007956 xmlSchemaPContentErr(ctxt,
7957 XML_SCHEMAP_UNKNOWN_INCLUDE_CHILD,
7958 NULL, NULL, node, child, NULL,
7959 "(annotation?)");
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007960 }
7961
7962 /*
7963 * First step is to parse the input document into an DOM/Infoset
7964 */
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00007965 /*
7966 * TODO: Use xmlCtxtReadFile to share the dictionary.
7967 */
7968 parserCtxt = xmlNewParserCtxt();
7969 if (parserCtxt == NULL) {
7970 xmlSchemaPErrMemory(NULL, "xmlSchemaParseInclude: "
7971 "allocating a parser context", NULL);
7972 return(-1);
7973 }
7974
7975 if ((ctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
7976 xmlDictFree(parserCtxt->dict);
7977 parserCtxt->dict = ctxt->dict;
7978 xmlDictReference(parserCtxt->dict);
7979 }
7980
7981 doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
7982 NULL, SCHEMAS_PARSE_OPTIONS);
7983 xmlFreeParserCtxt(parserCtxt);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007984 if (doc == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007985 /*
7986 * TODO: It is not an error for the ·actual value· of the
7987 * schemaLocation [attribute] to fail to resolve it all, in which
7988 * case no corresponding inclusion is performed.
7989 * So do we need a warning report here?
7990 */
7991 xmlSchemaPCustomErr(ctxt,
7992 XML_SCHEMAP_FAILED_LOAD,
7993 NULL, NULL, node,
7994 "Failed to load the document '%s' for inclusion", schemaLocation);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007995 return(-1);
7996 }
7997
7998 /*
7999 * Then extract the root of the schema
8000 */
8001 root = xmlDocGetRootElement(doc);
8002 if (root == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008003 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008004 XML_SCHEMAP_NOROOT,
William M. Brack2f2a6632004-08-20 23:09:47 +00008005 NULL, NULL, node,
8006 "The included document '%s' has no document "
8007 "element", schemaLocation);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008008 xmlFreeDoc(doc);
8009 return (-1);
8010 }
8011
8012 /*
8013 * Remove all the blank text nodes
8014 */
8015 xmlSchemaCleanupDoc(ctxt, root);
8016
8017 /*
8018 * Check the schemas top level element
8019 */
8020 if (!IS_SCHEMA(root, "schema")) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008021 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008022 XML_SCHEMAP_NOT_SCHEMA,
William M. Brack2f2a6632004-08-20 23:09:47 +00008023 NULL, NULL, node,
8024 "The document '%s' to be included is not a schema document",
8025 schemaLocation);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008026 xmlFreeDoc(doc);
8027 return (-1);
8028 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008029
William M. Brack2f2a6632004-08-20 23:09:47 +00008030 targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008031 /*
8032 * 2.1 SII has a targetNamespace [attribute], and its ·actual
8033 * value· is identical to the ·actual value· of the targetNamespace
8034 * [attribute] of SIIÂ’ (which must have such an [attribute]).
8035 */
8036 if (targetNamespace != NULL) {
8037 if (schema->targetNamespace == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008038 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008039 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00008040 NULL, NULL, node,
8041 "The target namespace of the included schema "
8042 "'%s' has to be absent, since the including schema "
8043 "has no target namespace",
8044 schemaLocation);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008045 xmlFreeDoc(doc);
8046 return (-1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008047 } else if (!xmlStrEqual(targetNamespace, schema->targetNamespace)) {
8048 xmlSchemaPCustomErrExt(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008049 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00008050 NULL, NULL, node,
8051 "The target namespace '%s' of the included schema '%s' "
8052 "differs from '%s' of the including schema",
8053 targetNamespace, schemaLocation, schema->targetNamespace);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008054 xmlFreeDoc(doc);
8055 return (-1);
8056 }
8057 } else if (schema->targetNamespace != NULL) {
8058 if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
8059 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
8060 } else
8061 wasConvertingNs = 1;
8062 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008063 /*
8064 * register the include
8065 */
8066 include = (xmlSchemaIncludePtr) xmlMalloc(sizeof(xmlSchemaInclude));
8067 if (include == NULL) {
8068 xmlSchemaPErrMemory(ctxt, "allocating included schema", NULL);
8069 xmlFreeDoc(doc);
8070 return (-1);
8071 }
8072
8073 memset(include, 0, sizeof(xmlSchemaInclude));
8074 include->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
8075 include->doc = doc;
8076 include->next = schema->includes;
8077 schema->includes = include;
8078
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008079 /*
8080 * parse the declarations in the included file like if they
8081 * were in the original file.
Daniel Veillardc0826a72004-08-10 14:17:33 +00008082 */
8083 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00008084 * TODO: The complete validation of the <schema> element is not done.
Daniel Veillardc0826a72004-08-10 14:17:33 +00008085 */
William M. Brack2f2a6632004-08-20 23:09:47 +00008086 /*
8087 * The default values ("blockDefault", "elementFormDefault", etc.)
8088 * are set to the values of the included schema and restored afterwards.
8089 */
8090 saveFlags = schema->flags;
8091 xmlSchemaClearSchemaDefaults(schema);
8092 xmlSchemaParseSchemaDefaults(ctxt, schema, root);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008093 xmlSchemaParseSchemaTopLevel(ctxt, schema, root->children);
William M. Brack2f2a6632004-08-20 23:09:47 +00008094 schema->flags = saveFlags;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008095 /*
8096 * Remove the converting flag.
8097 */
William M. Brack2f2a6632004-08-20 23:09:47 +00008098 if ((wasConvertingNs == 0) &&
8099 (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS))
Daniel Veillardc0826a72004-08-10 14:17:33 +00008100 schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008101 return (1);
8102}
8103
8104/**
Daniel Veillard4255d502002-04-16 15:50:10 +00008105 * xmlSchemaParseChoice:
8106 * @ctxt: a schema validation context
8107 * @schema: the schema being built
8108 * @node: a subtree containing XML Schema informations
8109 *
8110 * parse a XML schema Choice definition
8111 * *WARNING* this interface is highly subject to change
8112 *
William M. Bracke7091952004-05-11 15:09:58 +00008113 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00008114 * 1 in case of success.
8115 */
8116static xmlSchemaTypePtr
8117xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008118 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008119{
8120 xmlSchemaTypePtr type, subtype, last = NULL;
8121 xmlNodePtr child = NULL;
8122 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00008123 xmlAttrPtr attr;
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00008124 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00008125
8126 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8127 return (NULL);
8128
8129
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008130 snprintf((char *) name, 30, "#ch%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008131 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00008132 if (type == NULL)
8133 return (NULL);
8134 type->node = node;
8135 type->type = XML_SCHEMA_TYPE_CHOICE;
William M. Brack2f2a6632004-08-20 23:09:47 +00008136 /*
8137 * Check for illegal attributes.
8138 */
8139 attr = node->properties;
8140 while (attr != NULL) {
8141 if (attr->ns == NULL) {
8142 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8143 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
8144 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
8145 xmlSchemaPIllegalAttrErr(ctxt,
8146 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8147 NULL, type, attr);
8148 }
8149 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8150 xmlSchemaPIllegalAttrErr(ctxt,
8151 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8152 NULL, type, attr);
8153 }
8154 attr = attr->next;
8155 }
8156 /*
8157 * Extract and validate attributes.
8158 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008159 type->id = xmlSchemaGetProp(ctxt, node, "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008160 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
8161 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
8162 "(nonNegativeInteger | unbounded)");
William M. Brack2f2a6632004-08-20 23:09:47 +00008163 /*
8164 * And now for the children...
8165 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00008166 oldcontainer = ctxt->container;
8167 ctxt->container = (const xmlChar *) name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008168 child = node->children;
8169 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008170 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8171 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008172 }
8173 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008174 (IS_SCHEMA(child, "group")) ||
8175 (IS_SCHEMA(child, "any")) ||
8176 (IS_SCHEMA(child, "choice")) ||
8177 (IS_SCHEMA(child, "sequence"))) {
8178 subtype = NULL;
8179 if (IS_SCHEMA(child, "element")) {
8180 subtype = (xmlSchemaTypePtr)
8181 xmlSchemaParseElement(ctxt, schema, child, 0);
8182 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008183 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008184 } else if (IS_SCHEMA(child, "any")) {
8185 subtype = xmlSchemaParseAny(ctxt, schema, child);
8186 } else if (IS_SCHEMA(child, "sequence")) {
8187 subtype = xmlSchemaParseSequence(ctxt, schema, child);
8188 } else if (IS_SCHEMA(child, "choice")) {
8189 subtype = xmlSchemaParseChoice(ctxt, schema, child);
8190 }
8191 if (subtype != NULL) {
8192 if (last == NULL) {
8193 type->subtypes = subtype;
8194 last = subtype;
8195 } else {
8196 last->next = subtype;
8197 last = subtype;
8198 }
8199 last->next = NULL;
8200 }
8201 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008202 }
8203 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008204 /* TODO: error code. */
8205 xmlSchemaPContentErr(ctxt,
8206 XML_SCHEMAP_UNKNOWN_CHOICE_CHILD,
8207 NULL, type, node, child, NULL,
8208 "(annotation?, (element | group | choice | sequence | any)*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00008209 }
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00008210 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00008211 return (type);
8212}
8213
8214/**
8215 * xmlSchemaParseSequence:
8216 * @ctxt: a schema validation context
8217 * @schema: the schema being built
8218 * @node: a subtree containing XML Schema informations
8219 *
8220 * parse a XML schema Sequence definition
8221 * *WARNING* this interface is highly subject to change
8222 *
William M. Bracke7091952004-05-11 15:09:58 +00008223 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00008224 * 1 in case of success.
8225 */
8226static xmlSchemaTypePtr
8227xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008228 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008229{
8230 xmlSchemaTypePtr type, subtype, last = NULL;
8231 xmlNodePtr child = NULL;
8232 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00008233 xmlAttrPtr attr;
8234 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00008235
8236 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8237 return (NULL);
8238
William M. Brack2f2a6632004-08-20 23:09:47 +00008239 oldcontainer = ctxt->container;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008240 snprintf((char *) name, 30, "#seq%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008241 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00008242 if (type == NULL)
8243 return (NULL);
8244 type->node = node;
8245 type->type = XML_SCHEMA_TYPE_SEQUENCE;
William M. Brack2f2a6632004-08-20 23:09:47 +00008246 /*
8247 * Check for illegal attributes.
8248 */
8249 attr = node->properties;
8250 while (attr != NULL) {
8251 if (attr->ns == NULL) {
8252 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8253 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
8254 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
8255 xmlSchemaPIllegalAttrErr(ctxt,
8256 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8257 NULL, type, attr);
8258 }
8259 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8260 xmlSchemaPIllegalAttrErr(ctxt,
8261 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8262 NULL, type, attr);
8263 }
8264 attr = attr->next;
8265 }
8266 /*
8267 * Extract and validate attributes.
8268 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008269 type->id = xmlSchemaGetProp(ctxt, node, "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008270 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
8271 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
8272 "(nonNegativeInteger | unbounded)");
William M. Brack2f2a6632004-08-20 23:09:47 +00008273 /*
8274 * And now for the children...
8275 */
8276 ctxt->container = (const xmlChar *) name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008277 child = node->children;
8278 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008279 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8280 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008281 }
8282 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008283 (IS_SCHEMA(child, "group")) ||
8284 (IS_SCHEMA(child, "any")) ||
8285 (IS_SCHEMA(child, "choice")) ||
8286 (IS_SCHEMA(child, "sequence"))) {
8287 subtype = NULL;
8288 if (IS_SCHEMA(child, "element")) {
8289 subtype = (xmlSchemaTypePtr)
8290 xmlSchemaParseElement(ctxt, schema, child, 0);
8291 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008292 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008293 } else if (IS_SCHEMA(child, "any")) {
8294 subtype = xmlSchemaParseAny(ctxt, schema, child);
8295 } else if (IS_SCHEMA(child, "choice")) {
8296 subtype = xmlSchemaParseChoice(ctxt, schema, child);
8297 } else if (IS_SCHEMA(child, "sequence")) {
8298 subtype = xmlSchemaParseSequence(ctxt, schema, child);
8299 }
8300 if (subtype != NULL) {
8301 if (last == NULL) {
8302 type->subtypes = subtype;
8303 last = subtype;
8304 } else {
8305 last->next = subtype;
8306 last = subtype;
8307 }
8308 last->next = NULL;
8309 }
8310 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008311 }
8312 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008313 xmlSchemaPContentErr(ctxt,
8314 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
8315 NULL, type, node, child, NULL,
8316 "(annotation?, (element | group | choice | sequence | any)*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00008317 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008318 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00008319
8320 return (type);
8321}
8322
8323/**
8324 * xmlSchemaParseRestriction:
8325 * @ctxt: a schema validation context
8326 * @schema: the schema being built
8327 * @node: a subtree containing XML Schema informations
Daniel Veillard4255d502002-04-16 15:50:10 +00008328 *
8329 * parse a XML schema Restriction definition
8330 * *WARNING* this interface is highly subject to change
8331 *
8332 * Returns the type definition or NULL in case of error
8333 */
8334static xmlSchemaTypePtr
8335xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00008336 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008337{
Daniel Veillard01fa6152004-06-29 17:04:39 +00008338 xmlSchemaTypePtr type, subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00008339 xmlNodePtr child = NULL;
8340 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008341 const xmlChar *oldcontainer;
William M. Brack2f2a6632004-08-20 23:09:47 +00008342 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00008343
8344 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8345 return (NULL);
8346
8347 oldcontainer = ctxt->container;
8348
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008349 snprintf((char *) name, 30, "#restr%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008350 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00008351 if (type == NULL)
8352 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00008353 type->type = XML_SCHEMA_TYPE_RESTRICTION;
Daniel Veillard4255d502002-04-16 15:50:10 +00008354 type->node = node;
William M. Brack2f2a6632004-08-20 23:09:47 +00008355 /*
8356 * Check for illegal attributes.
8357 */
8358 attr = node->properties;
8359 while (attr != NULL) {
8360 if (attr->ns == NULL) {
8361 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8362 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
8363 xmlSchemaPIllegalAttrErr(ctxt,
8364 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8365 NULL, type, attr);
8366 }
8367 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8368 xmlSchemaPIllegalAttrErr(ctxt,
8369 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8370 NULL, type, attr);
8371 }
8372 attr = attr->next;
8373 }
8374 /*
8375 * Extract and validate attributes.
8376 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008377 type->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00008378 /*
8379 * Attribute "base".
8380 */
Daniel Veillard4255d502002-04-16 15:50:10 +00008381 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
Daniel Veillard01fa6152004-06-29 17:04:39 +00008382 if ((type->base == NULL) &&
William M. Brack2f2a6632004-08-20 23:09:47 +00008383 (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX)) {
8384 /* TODO: Think about the error code. */
8385 xmlSchemaPMissingAttrErr(ctxt,
8386 XML_SCHEMAP_RESTRICTION_NONAME_NOREF,
8387 NULL, type, node, "base", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008388 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008389 /*
8390 * And now for the children...
8391 */
Daniel Veillard4255d502002-04-16 15:50:10 +00008392 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008393 child = node->children;
8394 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008395 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8396 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008397 }
8398 subtype = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008399 if (ctxt->parentItem->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
8400 if (IS_SCHEMA(child, "all")) {
8401 subtype = (xmlSchemaTypePtr)
8402 xmlSchemaParseAll(ctxt, schema, child);
8403 child = child->next;
8404 type->subtypes = subtype;
8405 } else if (IS_SCHEMA(child, "choice")) {
8406 subtype = xmlSchemaParseChoice(ctxt, schema, child);
8407 child = child->next;
8408 type->subtypes = subtype;
8409 } else if (IS_SCHEMA(child, "sequence")) {
8410 subtype = (xmlSchemaTypePtr)
8411 xmlSchemaParseSequence(ctxt, schema, child);
8412 child = child->next;
8413 type->subtypes = subtype;
8414 } else if (IS_SCHEMA(child, "group")) {
8415 subtype = (xmlSchemaTypePtr)
8416 xmlSchemaParseGroup(ctxt, schema, child, 0);
8417 child = child->next;
8418 type->subtypes = subtype;
8419 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008420 } else if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_SIMPLE) {
8421 if (IS_SCHEMA(child, "simpleType")) {
8422 if (type->base != NULL) {
8423 /*
8424 * src-restriction-base-or-simpleType
8425 * Either the base [attribute] or the simpleType [child] of the
8426 * <restriction> element must be present, but not both.
8427 */
8428 xmlSchemaPContentErr(ctxt,
8429 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
8430 NULL, NULL, type->node, child,
8431 "The attribute 'base' and the <simpleType> child are "
8432 "mutually exclusive", NULL);
8433 } else {
8434 subtype = (xmlSchemaTypePtr)
8435 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
8436 type->baseType = subtype;
8437 }
8438 child = child->next;
8439 }
8440 } else if (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00008441 if (IS_SCHEMA(child, "simpleType")) {
8442 subtype = (xmlSchemaTypePtr)
8443 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008444 type->subtypes = subtype;
8445 child = child->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00008446 }
8447 }
8448 if ((ctxt->ctxtType->type == XML_SCHEMA_TYPE_SIMPLE) ||
8449 (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
8450 xmlSchemaFacetPtr facet, lastfacet = NULL;
8451
Daniel Veillard01fa6152004-06-29 17:04:39 +00008452 /*
8453 * Add the facets to the parent simpleType/complexType.
8454 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00008455 /*
8456 * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
8457 * Simple Type Definition Schema Representation Constraint:
8458 * *Single Facet Value*
8459 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00008460 while ((IS_SCHEMA(child, "minInclusive")) ||
8461 (IS_SCHEMA(child, "minExclusive")) ||
8462 (IS_SCHEMA(child, "maxInclusive")) ||
8463 (IS_SCHEMA(child, "maxExclusive")) ||
8464 (IS_SCHEMA(child, "totalDigits")) ||
8465 (IS_SCHEMA(child, "fractionDigits")) ||
8466 (IS_SCHEMA(child, "pattern")) ||
8467 (IS_SCHEMA(child, "enumeration")) ||
8468 (IS_SCHEMA(child, "whiteSpace")) ||
8469 (IS_SCHEMA(child, "length")) ||
8470 (IS_SCHEMA(child, "maxLength")) ||
8471 (IS_SCHEMA(child, "minLength"))) {
8472 facet = xmlSchemaParseFacet(ctxt, schema, child);
8473 if (facet != NULL) {
8474 if (lastfacet == NULL)
8475 ctxt->ctxtType->facets = facet;
8476 else
8477 lastfacet->next = facet;
8478 lastfacet = facet;
8479 lastfacet->next = NULL;
8480 }
8481 child = child->next;
8482 }
8483 /*
8484 * Create links for derivation and validation.
8485 */
8486 if (lastfacet != NULL) {
8487 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
8488
8489 facet = ctxt->ctxtType->facets;
8490 do {
8491 facetLink = (xmlSchemaFacetLinkPtr) xmlMalloc(sizeof(xmlSchemaFacetLink));
8492 if (facetLink == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008493 xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008494 xmlFree(facetLink);
8495 return (NULL);
8496 }
8497 facetLink->facet = facet;
8498 facetLink->next = NULL;
8499 if (lastFacetLink == NULL)
8500 ctxt->ctxtType->facetSet = facetLink;
8501 else
8502 lastFacetLink->next = facetLink;
8503 lastFacetLink = facetLink;
8504 facet = facet->next;
8505 } while (facet != NULL);
8506 }
8507 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008508 if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX) {
8509 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
8510 if (IS_SCHEMA(child, "anyAttribute")) {
8511 ctxt->ctxtType->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
8512 child = child->next;
8513 }
8514 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008515 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008516 /* TODO: Think about the error code. */
8517 if (ctxt->parentItem->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
8518 xmlSchemaPContentErr(ctxt,
8519 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
8520 NULL, type, node, child, NULL,
8521 "annotation?, (group | all | choice | sequence)?, "
8522 "((attribute | attributeGroup)*, anyAttribute?))");
8523 } else if (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
8524 xmlSchemaPContentErr(ctxt,
8525 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
8526 NULL, type, node, child, NULL,
8527 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
8528 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
8529 "length | minLength | maxLength | enumeration | whiteSpace | "
8530 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
8531 } else {
8532 /* Simple type */
8533 xmlSchemaPContentErr(ctxt,
8534 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
8535 NULL, type, node, child, NULL,
8536 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
8537 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
8538 "length | minLength | maxLength | enumeration | whiteSpace | "
8539 "pattern)*))");
8540 }
8541 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008542 ctxt->container = oldcontainer;
8543 return (type);
8544}
8545
8546/**
8547 * xmlSchemaParseExtension:
8548 * @ctxt: a schema validation context
8549 * @schema: the schema being built
8550 * @node: a subtree containing XML Schema informations
8551 *
8552 * parse a XML schema Extension definition
8553 * *WARNING* this interface is highly subject to change
8554 *
8555 * Returns the type definition or NULL in case of error
8556 */
8557static xmlSchemaTypePtr
8558xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008559 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008560{
8561 xmlSchemaTypePtr type, subtype;
8562 xmlNodePtr child = NULL;
8563 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008564 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00008565
8566 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8567 return (NULL);
8568
8569 oldcontainer = ctxt->container;
8570
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008571 snprintf((char *) name, 30, "#ext%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008572 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00008573 if (type == NULL)
8574 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00008575 type->type = XML_SCHEMA_TYPE_EXTENSION;
Daniel Veillard4255d502002-04-16 15:50:10 +00008576 type->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008577 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00008578 ctxt->container = name;
8579
8580 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
8581 if (type->base == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008582 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_EXTENSION_NO_BASE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008583 "<extension>: The attribute \"base\" is missing.\n",
8584 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008585 }
8586 child = node->children;
8587 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008588 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8589 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008590 }
8591 subtype = NULL;
8592
8593 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008594 subtype = xmlSchemaParseAll(ctxt, schema, child);
8595 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008596 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008597 subtype = xmlSchemaParseChoice(ctxt, schema, child);
8598 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008599 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008600 subtype = xmlSchemaParseSequence(ctxt, schema, child);
8601 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008602 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008603 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008604 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008605 }
8606 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008607 type->subtypes = subtype;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008608 if ((ctxt->ctxtType != NULL) &&
8609 (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX)) {
8610 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
8611 if (IS_SCHEMA(child, "anyAttribute")) {
8612 ctxt->ctxtType->attributeWildcard =
8613 xmlSchemaParseAnyAttribute(ctxt, schema, child);
8614 child = child->next;
8615 }
8616 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008617 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008618 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008619 XML_SCHEMAP_UNKNOWN_EXTENSION_CHILD,
8620 "<extension> has unexpected content.\n", type->name,
8621 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008622 }
8623 ctxt->container = oldcontainer;
8624 return (type);
8625}
8626
8627/**
8628 * xmlSchemaParseSimpleContent:
8629 * @ctxt: a schema validation context
8630 * @schema: the schema being built
8631 * @node: a subtree containing XML Schema informations
8632 *
8633 * parse a XML schema SimpleContent definition
8634 * *WARNING* this interface is highly subject to change
8635 *
8636 * Returns the type definition or NULL in case of error
8637 */
8638static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008639xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
8640 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008641{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008642 xmlSchemaTypePtr type, subtype, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00008643 xmlNodePtr child = NULL;
8644 xmlChar name[30];
8645
8646 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8647 return (NULL);
8648
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008649 snprintf((char *) name, 30, "#SC%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008650 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00008651 if (type == NULL)
8652 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00008653 type->type = XML_SCHEMA_TYPE_SIMPLE_CONTENT;
Daniel Veillard4255d502002-04-16 15:50:10 +00008654 type->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008655 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00008656
8657 child = node->children;
8658 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008659 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8660 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008661 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008662 oldParentItem = ctxt->parentItem;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008663 ctxt->parentItem = type;
8664 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00008665 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008666 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00008667 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008668 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008669 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008670 subtype = (xmlSchemaTypePtr)
8671 xmlSchemaParseExtension(ctxt, schema, child);
8672 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008673 }
8674 type->subtypes = subtype;
8675 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008676 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008677 XML_SCHEMAP_UNKNOWN_SIMPLECONTENT_CHILD,
8678 "<simpleContent> has unexpected content.\n",
8679 NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008680 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008681 ctxt->parentItem = oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00008682 return (type);
8683}
8684
8685/**
8686 * xmlSchemaParseComplexContent:
8687 * @ctxt: a schema validation context
8688 * @schema: the schema being built
8689 * @node: a subtree containing XML Schema informations
8690 *
8691 * parse a XML schema ComplexContent definition
8692 * *WARNING* this interface is highly subject to change
8693 *
8694 * Returns the type definition or NULL in case of error
8695 */
8696static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008697xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
8698 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008699{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008700 xmlSchemaTypePtr type, subtype, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00008701 xmlNodePtr child = NULL;
8702 xmlChar name[30];
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008703 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00008704
8705 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8706 return (NULL);
8707
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008708 snprintf((char *) name, 30, "#CC%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008709 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00008710 if (type == NULL)
8711 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00008712 type->type = XML_SCHEMA_TYPE_COMPLEX_CONTENT;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008713 type->node = node;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008714 /*
8715 * Check for illegal attributes.
8716 */
8717 attr = node->properties;
8718 while (attr != NULL) {
8719 if (attr->ns == NULL) {
8720 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8721 (!xmlStrEqual(attr->name, BAD_CAST "mixed")))
8722 {
8723 xmlSchemaPIllegalAttrErr(ctxt,
8724 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8725 NULL, NULL, attr);
8726 }
8727 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8728 xmlSchemaPIllegalAttrErr(ctxt,
8729 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8730 NULL, NULL, attr);
8731 }
8732 attr = attr->next;
8733 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008734 type->id = xmlSchemaGetProp(ctxt, node, "id");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008735 /*
8736 * Handle attribute 'mixed'.
8737 */
8738 if (xmlGetBooleanProp(ctxt, NULL, type, node, "mixed", 0)) {
8739 if ((ctxt->ctxtType->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
8740 ctxt->ctxtType->flags |= XML_SCHEMAS_TYPE_MIXED;
8741 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008742 child = node->children;
8743 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008744 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8745 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008746 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008747 oldParentItem = ctxt->parentItem;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008748 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008749 subtype = NULL;
8750 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008751 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00008752 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008753 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008754 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008755 subtype = (xmlSchemaTypePtr)
8756 xmlSchemaParseExtension(ctxt, schema, child);
8757 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008758 }
8759 type->subtypes = subtype;
8760 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008761 xmlSchemaPContentErr(ctxt,
8762 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8763 NULL, NULL, node, child,
8764 NULL, "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +00008765 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008766 ctxt->parentItem = oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00008767 return (type);
8768}
8769
8770/**
8771 * xmlSchemaParseComplexType:
8772 * @ctxt: a schema validation context
8773 * @schema: the schema being built
8774 * @node: a subtree containing XML Schema informations
8775 *
8776 * parse a XML schema Complex Type definition
8777 * *WARNING* this interface is highly subject to change
8778 *
8779 * Returns the type definition or NULL in case of error
8780 */
8781static xmlSchemaTypePtr
8782xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00008783 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00008784{
Daniel Veillard01fa6152004-06-29 17:04:39 +00008785 xmlSchemaTypePtr type, subtype, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00008786 xmlNodePtr child = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008787 const xmlChar *name = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00008788 const xmlChar *oldcontainer;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008789 xmlAttrPtr attr;
8790 const xmlChar *attrValue;
8791 xmlChar *des = NULL; /* The reported designation. */
Daniel Veillard1a380b82004-10-21 16:00:06 +00008792 char buf[40];
8793
Daniel Veillard4255d502002-04-16 15:50:10 +00008794
8795 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8796 return (NULL);
8797
Daniel Veillard01fa6152004-06-29 17:04:39 +00008798 ctxtType = ctxt->ctxtType;
8799
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008800 if (topLevel) {
8801 attr = xmlSchemaGetPropNode(node, "name");
8802 if (attr == NULL) {
8803 xmlSchemaPMissingAttrErr(ctxt,
8804 XML_SCHEMAP_S4S_ATTR_MISSING,
8805 (xmlChar **) &xmlSchemaElemDesCT, NULL, node,
8806 "name", NULL);
8807 return (NULL);
8808 } else if (xmlSchemaPValAttrNode(ctxt,
8809 (xmlChar **) &xmlSchemaElemDesCT, NULL, attr,
8810 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
8811 return (NULL);
8812 }
8813 }
8814
8815 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008816 /*
8817 * Parse as local complex type definition.
8818 */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008819 snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008820 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
8821 if (type == NULL)
8822 return (NULL);
8823 name = (const xmlChar *) buf;
8824 type->node = node;
8825 type->type = XML_SCHEMA_TYPE_COMPLEX;
8826 /*
8827 * TODO: We need the target namespace.
8828 */
8829 } else {
8830 /*
8831 * Parse as global complex type definition.
8832 */
William M. Brack2f2a6632004-08-20 23:09:47 +00008833 type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace, node);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008834 if (type == NULL)
8835 return (NULL);
8836 type->node = node;
8837 type->type = XML_SCHEMA_TYPE_COMPLEX;
8838 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
8839 /*
8840 * Set defaults.
8841 */
8842 type->flags |= XML_SCHEMAS_TYPE_FINAL_DEFAULT;
8843 type->flags |= XML_SCHEMAS_TYPE_BLOCK_DEFAULT;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00008844 }
8845 type->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008846 /*
8847 * Handle attributes.
8848 */
8849 attr = node->properties;
8850 while (attr != NULL) {
8851 if (attr->ns == NULL) {
8852 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
8853 /*
8854 * Attribute "id".
8855 */
8856 type->id = xmlSchemaGetProp(ctxt, node, "id");
8857 } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
8858 /*
8859 * Attribute "mixed".
8860 */
8861 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
8862 (xmlNodePtr) attr))
8863 type->flags |= XML_SCHEMAS_TYPE_MIXED;
8864 } else if (topLevel) {
8865 /*
8866 * Attributes of global complex type definitions.
8867 */
8868 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
8869 /* Pass. */
8870 } else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
8871 /*
8872 * Attribute "abstract".
8873 */
8874 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
8875 (xmlNodePtr) attr))
8876 type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
8877 } else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
8878 /*
8879 * Attribute "final".
8880 */
8881 attrValue = xmlSchemaGetNodeContent(ctxt,
8882 (xmlNodePtr) attr);
8883 if (xmlSchemaPValAttrBlockFinal(attrValue,
8884 &(type->flags),
8885 -1,
8886 XML_SCHEMAS_TYPE_FINAL_EXTENSION,
8887 XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
8888 -1, -1, -1) != 0)
8889 {
8890 xmlSchemaPSimpleTypeErr(ctxt,
8891 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8892 &des, type, (xmlNodePtr) attr,
8893 NULL,
8894 "(#all | List of (extension | restriction))",
8895 attrValue, NULL, NULL, NULL);
8896 }
8897 } else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
8898 /*
8899 * Attribute "block".
8900 */
8901 attrValue = xmlSchemaGetNodeContent(ctxt,
8902 (xmlNodePtr) attr);
8903 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
8904 -1,
8905 XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
8906 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
8907 -1, -1, -1) != 0) {
8908 xmlSchemaPSimpleTypeErr(ctxt,
8909 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8910 &des, type, (xmlNodePtr) attr,
8911 NULL,
8912 "(#all | List of (extension | restriction)) ",
8913 attrValue, NULL, NULL, NULL);
8914 }
8915 } else {
8916 xmlSchemaPIllegalAttrErr(ctxt,
8917 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8918 &des, type, attr);
8919 }
8920 } else {
8921 xmlSchemaPIllegalAttrErr(ctxt,
8922 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8923 &des, type, attr);
8924 }
8925 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8926 xmlSchemaPIllegalAttrErr(ctxt,
8927 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8928 &des, type, attr);
8929 }
8930 attr = attr->next;
8931 }
8932 /*
8933 * Set as default for attribute wildcards.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008934 * This will be only changed if a complex type
8935 * inherits an attribute wildcard from a base type.
8936 */
8937 type->flags |= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008938 /*
8939 * And now for the children...
8940 */
8941 oldcontainer = ctxt->container;
8942 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008943 child = node->children;
8944 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008945 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8946 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008947 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00008948 ctxt->ctxtType = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008949 if (IS_SCHEMA(child, "simpleContent")) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008950 /*
8951 * 3.4.3 : 2.2
8952 * Specifying mixed='true' when the <simpleContent>
8953 * alternative is chosen has no effect
8954 */
William M. Bracke7091952004-05-11 15:09:58 +00008955 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
8956 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008957 type->subtypes = xmlSchemaParseSimpleContent(ctxt, schema, child);
8958 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008959 } else if (IS_SCHEMA(child, "complexContent")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008960 type->subtypes = xmlSchemaParseComplexContent(ctxt, schema, child);
8961 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008962 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008963 subtype = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008964 /*
8965 * Parse model groups.
8966 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008967 if (IS_SCHEMA(child, "all")) {
8968 subtype = xmlSchemaParseAll(ctxt, schema, child);
8969 child = child->next;
8970 } else if (IS_SCHEMA(child, "choice")) {
8971 subtype = xmlSchemaParseChoice(ctxt, schema, child);
8972 child = child->next;
8973 } else if (IS_SCHEMA(child, "sequence")) {
8974 subtype = xmlSchemaParseSequence(ctxt, schema, child);
8975 child = child->next;
8976 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008977 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008978 child = child->next;
8979 }
8980 if (subtype != NULL)
8981 type->subtypes = subtype;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008982 /*
8983 * Parse attribute decls/refs.
8984 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008985 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008986 /*
8987 * Parse attribute wildcard.
8988 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008989 if (IS_SCHEMA(child, "anyAttribute")) {
8990 type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
8991 child = child->next;
8992 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008993 }
8994 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008995 xmlSchemaPContentErr(ctxt,
8996 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8997 &des, type, node, child,
8998 NULL, "(annotation?, (simpleContent | complexContent | "
8999 "((group | all | choice | sequence)?, ((attribute | "
9000 "attributeGroup)*, anyAttribute?))))");
Daniel Veillard4255d502002-04-16 15:50:10 +00009001 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009002 FREE_AND_NULL(des);
Daniel Veillard4255d502002-04-16 15:50:10 +00009003 ctxt->container = oldcontainer;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009004 ctxt->ctxtType = ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00009005 return (type);
9006}
9007
Daniel Veillard4255d502002-04-16 15:50:10 +00009008/**
9009 * xmlSchemaParseSchema:
9010 * @ctxt: a schema validation context
9011 * @node: a subtree containing XML Schema informations
9012 *
9013 * parse a XML schema definition from a node set
9014 * *WARNING* this interface is highly subject to change
9015 *
9016 * Returns the internal XML Schema structure built from the resource or
9017 * NULL in case of error
9018 */
9019static xmlSchemaPtr
9020xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
9021{
9022 xmlSchemaPtr schema = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009023 const xmlChar *val;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00009024 int nberrors;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009025 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00009026
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009027 /*
9028 * This one is called by xmlSchemaParse only and is used if
9029 * the schema to be parsed was specified via the API; i.e. not
9030 * automatically by the validated instance document.
9031 */
Daniel Veillard4255d502002-04-16 15:50:10 +00009032 if ((ctxt == NULL) || (node == NULL))
9033 return (NULL);
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00009034 nberrors = ctxt->nberrors;
9035 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00009036 if (IS_SCHEMA(node, "schema")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009037 xmlSchemaImportPtr import;
9038
Daniel Veillard4255d502002-04-16 15:50:10 +00009039 schema = xmlSchemaNewSchema(ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009040 if (schema == NULL)
9041 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009042 /*
9043 * Disable build of list of items.
9044 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00009045 attr = xmlSchemaGetPropNode(node, "targetNamespace");
9046 if (attr != NULL) {
9047 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
9048 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &val);
9049 /*
9050 * TODO: Should we proceed with an invalid target namespace?
9051 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009052 schema->targetNamespace = xmlDictLookup(ctxt->dict, val, -1);
9053 } else {
9054 schema->targetNamespace = NULL;
9055 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009056 /*
9057 * Add the current ns name and location to the import table;
9058 * this is needed to have a consistent mechanism, regardless
9059 * if all schemata are constructed dynamically fired by the
9060 * instance or if the schema to be used was specified via
9061 * the API.
9062 */
9063 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports),
9064 schema->targetNamespace);
9065 if (import == NULL) {
9066 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT,
9067 NULL, NULL, (xmlNodePtr) ctxt->doc,
9068 "Internal error: xmlSchemaParseSchema, "
9069 "failed to add an import entry", NULL);
9070 xmlSchemaFree(schema);
9071 schema = NULL;
9072 return (NULL);
9073 }
9074 import->schemaLocation = ctxt->URL;
9075 /*
9076 * NOTE: We won't set the doc here, otherwise it will be freed
9077 * if the import struct is freed.
9078 * import->doc = ctxt->doc;
9079 */
9080
Daniel Veillardc0826a72004-08-10 14:17:33 +00009081 /* TODO: Check id. */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009082 schema->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00009083 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
9084 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &(schema->version));
9085
William M. Brack2f2a6632004-08-20 23:09:47 +00009086 xmlSchemaParseSchemaDefaults(ctxt, schema, node);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009087 xmlSchemaParseSchemaTopLevel(ctxt, schema, node->children);
9088 } else {
9089 xmlDocPtr doc;
9090
9091 doc = node->doc;
9092
9093 if ((doc != NULL) && (doc->URL != NULL)) {
9094 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
9095 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009096 "The file \"%s\" is not a XML schema.\n", doc->URL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009097 } else {
9098 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
9099 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009100 "The file is not a XML schema.\n", NULL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009101 }
9102 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009103 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00009104 if (ctxt->nberrors != 0) {
9105 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009106 xmlSchemaFree(schema);
9107 schema = NULL;
9108 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00009109 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009110 if (schema != NULL)
9111 schema->counter = ctxt->counter;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00009112 ctxt->nberrors = nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00009113#ifdef DEBUG
9114 if (schema == NULL)
9115 xmlGenericError(xmlGenericErrorContext,
9116 "xmlSchemaParse() failed\n");
9117#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00009118 return (schema);
9119}
9120
9121/************************************************************************
9122 * *
9123 * Validating using Schemas *
9124 * *
9125 ************************************************************************/
9126
9127/************************************************************************
9128 * *
9129 * Reading/Writing Schemas *
9130 * *
9131 ************************************************************************/
9132
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009133#if 0 /* Will be enabled if it is clear what options are needed. */
9134/**
9135 * xmlSchemaParserCtxtSetOptions:
9136 * @ctxt: a schema parser context
9137 * @options: a combination of xmlSchemaParserOption
9138 *
9139 * Sets the options to be used during the parse.
9140 *
9141 * Returns 0 in case of success, -1 in case of an
9142 * API error.
9143 */
9144static int
9145xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
9146 int options)
9147
9148{
9149 int i;
9150
9151 if (ctxt == NULL)
9152 return (-1);
9153 /*
9154 * WARNING: Change the start value if adding to the
9155 * xmlSchemaParseOption.
9156 */
9157 for (i = 1; i < (int) sizeof(int) * 8; i++) {
9158 if (options & 1<<i) {
9159 return (-1);
9160 }
9161 }
9162 ctxt->options = options;
9163 return (0);
9164}
9165
9166/**
9167 * xmlSchemaValidCtxtGetOptions:
9168 * @ctxt: a schema parser context
9169 *
9170 * Returns the option combination of the parser context.
9171 */
9172static int
9173xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
9174
9175{
9176 if (ctxt == NULL)
9177 return (-1);
9178 else
9179 return (ctxt->options);
9180}
9181
9182 void *curItems; /* used for dynamic addition of schemata */
9183 int nbCurItems; /* used for dynamic addition of schemata */
9184 int sizeCurItems; /* used for dynamic addition of schemata */
9185
9186#endif
9187
Daniel Veillard4255d502002-04-16 15:50:10 +00009188/**
9189 * xmlSchemaNewParserCtxt:
9190 * @URL: the location of the schema
9191 *
9192 * Create an XML Schemas parse context for that file/resource expected
9193 * to contain an XML Schemas file.
9194 *
9195 * Returns the parser context or NULL in case of error
9196 */
9197xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009198xmlSchemaNewParserCtxt(const char *URL)
9199{
Daniel Veillard4255d502002-04-16 15:50:10 +00009200 xmlSchemaParserCtxtPtr ret;
9201
9202 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009203 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009204
9205 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9206 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009207 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009208 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009209 return (NULL);
9210 }
9211 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009212 ret->dict = xmlDictCreate();
9213 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00009214 ret->includes = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00009215 return (ret);
9216}
9217
9218/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009219 * xmlSchemaNewParserCtxtUseDict:
9220 * @URL: the location of the schema
9221 * @dict: the dictionary to be used
9222 *
9223 * Create an XML Schemas parse context for that file/resource expected
9224 * to contain an XML Schemas file.
9225 *
9226 * Returns the parser context or NULL in case of error
9227 */
9228static xmlSchemaParserCtxtPtr
9229xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
9230{
9231 xmlSchemaParserCtxtPtr ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009232 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009233 if (URL == NULL)
9234 return (NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009235 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009236
9237 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9238 if (ret == NULL) {
9239 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
9240 NULL);
9241 return (NULL);
9242 }
9243 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
9244 ret->dict = dict;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009245 xmlDictReference(dict);
9246 if (URL != NULL)
9247 ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009248 ret->includes = 0;
9249 return (ret);
9250}
9251
9252
9253/**
Daniel Veillard6045c902002-10-09 21:13:59 +00009254 * xmlSchemaNewMemParserCtxt:
9255 * @buffer: a pointer to a char array containing the schemas
9256 * @size: the size of the array
9257 *
9258 * Create an XML Schemas parse context for that memory buffer expected
9259 * to contain an XML Schemas file.
9260 *
9261 * Returns the parser context or NULL in case of error
9262 */
9263xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009264xmlSchemaNewMemParserCtxt(const char *buffer, int size)
9265{
Daniel Veillard6045c902002-10-09 21:13:59 +00009266 xmlSchemaParserCtxtPtr ret;
9267
9268 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009269 return (NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00009270
9271 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9272 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009273 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009274 NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00009275 return (NULL);
9276 }
9277 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
9278 ret->buffer = buffer;
9279 ret->size = size;
William M. Brackcf9eadf2003-12-25 13:24:05 +00009280 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +00009281 return (ret);
9282}
9283
9284/**
Daniel Veillard9d751502003-10-29 13:21:47 +00009285 * xmlSchemaNewDocParserCtxt:
9286 * @doc: a preparsed document tree
9287 *
9288 * Create an XML Schemas parse context for that document.
9289 * NB. The document may be modified during the parsing process.
9290 *
9291 * Returns the parser context or NULL in case of error
9292 */
9293xmlSchemaParserCtxtPtr
9294xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
9295{
9296 xmlSchemaParserCtxtPtr ret;
9297
9298 if (doc == NULL)
9299 return (NULL);
9300
9301 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9302 if (ret == NULL) {
9303 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
9304 NULL);
9305 return (NULL);
9306 }
9307 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
9308 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +00009309 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +00009310 /* The application has responsibility for the document */
9311 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +00009312
9313 return (ret);
9314}
9315
9316/**
Daniel Veillard4255d502002-04-16 15:50:10 +00009317 * xmlSchemaFreeParserCtxt:
9318 * @ctxt: the schema parser context
9319 *
9320 * Free the resources associated to the schema parser context
9321 */
9322void
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009323xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
9324{
Daniel Veillard4255d502002-04-16 15:50:10 +00009325 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009326 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +00009327 if (ctxt->doc != NULL && !ctxt->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009328 xmlFreeDoc(ctxt->doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009329 if (ctxt->assemble != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009330 xmlFree((xmlSchemaTypePtr *) ctxt->assemble->items);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009331 xmlFree(ctxt->assemble);
9332 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009333 if (ctxt->vctxt != NULL) {
9334 xmlSchemaFreeValidCtxt(ctxt->vctxt);
9335 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009336 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00009337 xmlFree(ctxt);
9338}
9339
9340/************************************************************************
9341 * *
9342 * Building the content models *
9343 * *
9344 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009345
Daniel Veillard4255d502002-04-16 15:50:10 +00009346/**
9347 * xmlSchemaBuildAContentModel:
9348 * @type: the schema type definition
9349 * @ctxt: the schema parser context
9350 * @name: the element name whose content is being built
9351 *
9352 * Generate the automata sequence needed for that type
9353 */
9354static void
9355xmlSchemaBuildAContentModel(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009356 xmlSchemaParserCtxtPtr ctxt,
9357 const xmlChar * name)
9358{
Daniel Veillard4255d502002-04-16 15:50:10 +00009359 if (type == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009360 xmlGenericError(xmlGenericErrorContext,
9361 "Found unexpected type = NULL in %s content model\n",
9362 name);
9363 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00009364 }
9365 switch (type->type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009366 case XML_SCHEMA_TYPE_ANY: {
9367 xmlAutomataStatePtr start, end;
9368 xmlSchemaWildcardPtr wild;
9369 xmlSchemaWildcardNsPtr ns;
Daniel Veillard32370232002-10-16 14:08:14 +00009370
Daniel Veillardc0826a72004-08-10 14:17:33 +00009371 wild = type->attributeWildcard;
9372
9373 if (wild == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00009374 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009375 "Internal error: xmlSchemaBuildAContentModel, "
9376 "no wildcard on xsd:any.\n", NULL, NULL);
9377 return;
9378 }
9379
9380 start = ctxt->state;
9381 end = xmlAutomataNewState(ctxt->am);
9382
9383 if (type->maxOccurs == 1) {
9384 if (wild->any == 1) {
9385 /*
9386 * We need to add both transitions:
9387 *
9388 * 1. the {"*", "*"} for elements in a namespace.
9389 */
9390 ctxt->state =
9391 xmlAutomataNewTransition2(ctxt->am,
9392 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
9393 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9394 /*
9395 * 2. the {"*"} for elements in no namespace.
9396 */
9397 ctxt->state =
9398 xmlAutomataNewTransition2(ctxt->am,
9399 start, NULL, BAD_CAST "*", NULL, type);
9400 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9401
9402 } else if (wild->nsSet != NULL) {
9403 ns = wild->nsSet;
9404 do {
9405 ctxt->state = start;
9406 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9407 ctxt->state, NULL, BAD_CAST "*", ns->value, type);
9408 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9409 ns = ns->next;
9410 } while (ns != NULL);
9411
9412 } else if (wild->negNsSet != NULL) {
9413 xmlAutomataStatePtr deadEnd;
9414
9415 deadEnd = xmlAutomataNewState(ctxt->am);
9416 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9417 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, type);
9418 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9419 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
9420 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9421 }
9422 } else {
9423 int counter;
9424 xmlAutomataStatePtr hop;
9425 int maxOccurs =
9426 type->maxOccurs == UNBOUNDED ? UNBOUNDED : type->maxOccurs - 1;
9427 int minOccurs =
9428 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
9429
9430 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
9431 hop = xmlAutomataNewState(ctxt->am);
9432 if (wild->any == 1) {
9433 ctxt->state =
9434 xmlAutomataNewTransition2(ctxt->am,
9435 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
9436 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
9437 ctxt->state =
9438 xmlAutomataNewTransition2(ctxt->am,
9439 start, NULL, BAD_CAST "*", NULL, type);
9440 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
9441 } else if (wild->nsSet != NULL) {
9442 ns = wild->nsSet;
9443 do {
9444 ctxt->state =
9445 xmlAutomataNewTransition2(ctxt->am,
9446 start, NULL, BAD_CAST "*", ns->value, type);
9447 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
9448 ns = ns->next;
9449 } while (ns != NULL);
9450
9451 } else if (wild->negNsSet != NULL) {
9452 xmlAutomataStatePtr deadEnd;
9453
9454 deadEnd = xmlAutomataNewState(ctxt->am);
9455 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9456 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, type);
9457 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9458 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
9459 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
9460 }
9461 xmlAutomataNewCountedTrans(ctxt->am, hop, start, counter);
9462 xmlAutomataNewCounterTrans(ctxt->am, hop, end, counter);
9463 }
9464 if (type->minOccurs == 0) {
9465 xmlAutomataNewEpsilon(ctxt->am, start, end);
9466 }
9467 ctxt->state = end;
9468 break;
9469 }
9470 case XML_SCHEMA_TYPE_ELEMENT:{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009471 xmlAutomataStatePtr oldstate;
9472 xmlSchemaElementPtr particle, elemDecl;
Daniel Veillard32370232002-10-16 14:08:14 +00009473
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009474 /*
9475 * IMPORTANT: This puts element declarations
9476 * (and never element decl. references) into the
9477 * automaton. This is crucial and should not be changed,
9478 * since validating functions rely now on it.
9479 */
9480 particle = (xmlSchemaElementPtr) type;
9481 if (particle->ref != NULL) {
9482 if (particle->refDecl == NULL) {
9483 /*
9484 * Skip content model creation if the reference
9485 * did not resolve to a declaration.
9486 */
9487 break;
9488 } else {
9489 /*
9490 * Referenced global element declaration.
9491 */
9492 elemDecl = particle->refDecl;
9493 }
9494 } else {
9495 /*
9496 * Anonymous element declaration.
9497 */
9498 elemDecl = particle;
9499 }
9500
9501 oldstate = ctxt->state;
9502
9503 if (particle->maxOccurs >= UNBOUNDED) {
9504 if (particle->minOccurs > 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009505 xmlAutomataStatePtr tmp;
9506 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00009507
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009508 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009509 oldstate, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009510 oldstate = ctxt->state;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009511 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009512 particle->minOccurs - 1, UNBOUNDED);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00009513 ctxt->state =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009514 xmlAutomataNewTransition2(ctxt->am,
9515 ctxt->state, NULL,
9516 elemDecl->name,
9517 elemDecl->targetNamespace,
9518 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009519 tmp = ctxt->state;
9520 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009521 counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009522 ctxt->state =
9523 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009524 counter);
Daniel Veillard32370232002-10-16 14:08:14 +00009525
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009526 } else {
9527 ctxt->state =
9528 xmlAutomataNewTransition2(ctxt->am,
9529 ctxt->state, NULL,
9530 elemDecl->name,
9531 elemDecl->targetNamespace,
9532 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009533 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
9534 oldstate);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009535 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009536 /* basically an elem* */
9537 xmlAutomataNewEpsilon(ctxt->am, oldstate,
9538 ctxt->state);
9539 }
9540 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009541 } else if ((particle->maxOccurs > 1) || (particle->minOccurs > 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009542 xmlAutomataStatePtr tmp;
9543 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00009544
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009545 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
9546 oldstate, NULL);
9547 oldstate = ctxt->state;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009548 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009549 particle->minOccurs - 1,
9550 particle->maxOccurs - 1);
9551 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9552 ctxt->state,
9553 NULL,
9554 elemDecl->name,
9555 elemDecl->targetNamespace,
9556 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009557 tmp = ctxt->state;
9558 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009559 counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009560 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, tmp,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009561 NULL, counter);
9562 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009563 /* basically an elem? */
9564 xmlAutomataNewEpsilon(ctxt->am, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009565 ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009566 }
Daniel Veillardb39bc392002-10-26 19:29:51 +00009567
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009568 } else {
9569 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9570 ctxt->state,
9571 NULL,
9572 elemDecl->name,
9573 elemDecl->targetNamespace,
9574 (xmlSchemaTypePtr) elemDecl);
9575 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009576 /* basically an elem? */
9577 xmlAutomataNewEpsilon(ctxt->am, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009578 ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009579 }
9580 }
9581 break;
9582 }
9583 case XML_SCHEMA_TYPE_SEQUENCE:{
9584 xmlSchemaTypePtr subtypes;
Daniel Veillardb39bc392002-10-26 19:29:51 +00009585
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009586 /*
9587 * If max and min occurances are default (1) then
9588 * simply iterate over the subtypes
9589 */
9590 if ((type->minOccurs == 1) && (type->maxOccurs == 1)) {
9591 subtypes = type->subtypes;
9592 while (subtypes != NULL) {
9593 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
9594 subtypes = subtypes->next;
9595 }
9596 } else {
9597 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00009598
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009599 if (type->maxOccurs >= UNBOUNDED) {
9600 if (type->minOccurs > 1) {
9601 xmlAutomataStatePtr tmp;
9602 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00009603
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009604 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
9605 oldstate,
9606 NULL);
9607 oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00009608
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009609 counter = xmlAutomataNewCounter(ctxt->am,
9610 type->
9611 minOccurs - 1,
9612 UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +00009613
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009614 subtypes = type->subtypes;
9615 while (subtypes != NULL) {
9616 xmlSchemaBuildAContentModel(subtypes, ctxt,
9617 name);
9618 subtypes = subtypes->next;
9619 }
9620 tmp = ctxt->state;
9621 xmlAutomataNewCountedTrans(ctxt->am, tmp,
9622 oldstate, counter);
9623 ctxt->state =
9624 xmlAutomataNewCounterTrans(ctxt->am, tmp,
9625 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +00009626
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009627 } else {
9628 subtypes = type->subtypes;
9629 while (subtypes != NULL) {
9630 xmlSchemaBuildAContentModel(subtypes, ctxt,
9631 name);
9632 subtypes = subtypes->next;
9633 }
9634 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
9635 oldstate);
9636 if (type->minOccurs == 0) {
9637 xmlAutomataNewEpsilon(ctxt->am, oldstate,
9638 ctxt->state);
9639 }
9640 }
9641 } else if ((type->maxOccurs > 1)
9642 || (type->minOccurs > 1)) {
9643 xmlAutomataStatePtr tmp;
9644 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00009645
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009646 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
9647 oldstate,
9648 NULL);
9649 oldstate = ctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +00009650
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009651 counter = xmlAutomataNewCounter(ctxt->am,
9652 type->minOccurs -
9653 1,
9654 type->maxOccurs -
9655 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00009656
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009657 subtypes = type->subtypes;
9658 while (subtypes != NULL) {
9659 xmlSchemaBuildAContentModel(subtypes, ctxt,
9660 name);
9661 subtypes = subtypes->next;
9662 }
9663 tmp = ctxt->state;
9664 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
9665 counter);
9666 ctxt->state =
9667 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
9668 counter);
9669 if (type->minOccurs == 0) {
9670 xmlAutomataNewEpsilon(ctxt->am, oldstate,
9671 ctxt->state);
9672 }
Daniel Veillardb509f152002-04-17 16:28:10 +00009673
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009674 } else {
9675 subtypes = type->subtypes;
9676 while (subtypes != NULL) {
9677 xmlSchemaBuildAContentModel(subtypes, ctxt,
9678 name);
9679 subtypes = subtypes->next;
9680 }
9681 if (type->minOccurs == 0) {
9682 xmlAutomataNewEpsilon(ctxt->am, oldstate,
9683 ctxt->state);
9684 }
9685 }
9686 }
9687 break;
9688 }
9689 case XML_SCHEMA_TYPE_CHOICE:{
9690 xmlSchemaTypePtr subtypes;
9691 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +00009692
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009693 start = ctxt->state;
9694 end = xmlAutomataNewState(ctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +00009695
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009696 /*
9697 * iterate over the subtypes and remerge the end with an
9698 * epsilon transition
9699 */
9700 if (type->maxOccurs == 1) {
9701 subtypes = type->subtypes;
9702 while (subtypes != NULL) {
9703 ctxt->state = start;
9704 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
9705 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9706 subtypes = subtypes->next;
9707 }
9708 } else {
9709 int counter;
9710 xmlAutomataStatePtr hop;
9711 int maxOccurs = type->maxOccurs == UNBOUNDED ?
9712 UNBOUNDED : type->maxOccurs - 1;
9713 int minOccurs =
9714 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +00009715
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009716 /*
9717 * use a counter to keep track of the number of transtions
9718 * which went through the choice.
9719 */
9720 counter =
9721 xmlAutomataNewCounter(ctxt->am, minOccurs,
9722 maxOccurs);
9723 hop = xmlAutomataNewState(ctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +00009724
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009725 subtypes = type->subtypes;
9726 while (subtypes != NULL) {
9727 ctxt->state = start;
9728 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
9729 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
9730 subtypes = subtypes->next;
9731 }
9732 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
9733 counter);
9734 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
9735 counter);
9736 }
9737 if (type->minOccurs == 0) {
9738 xmlAutomataNewEpsilon(ctxt->am, start, end);
9739 }
9740 ctxt->state = end;
9741 break;
9742 }
9743 case XML_SCHEMA_TYPE_ALL:{
9744 xmlAutomataStatePtr start;
9745 xmlSchemaTypePtr subtypes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009746
Daniel Veillard3646d642004-06-02 19:19:14 +00009747 xmlSchemaElementPtr elem;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009748 int lax;
9749
9750 subtypes = type->subtypes;
9751 if (subtypes == NULL)
9752 break;
9753 start = ctxt->state;
9754 while (subtypes != NULL) {
9755 ctxt->state = start;
William M. Brack9989c7d2004-05-12 14:39:38 +00009756 /*
9757 * the following 'if' was needed to fix bug 139897
9758 * not quite sure why it only needs to be done for
9759 * elements with a 'ref', but it seems to work ok.
9760 */
9761 if (subtypes->ref != NULL)
9762 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009763 elem = (xmlSchemaElementPtr) subtypes;
9764 /*
9765 * NOTE: The {max occurs} of all the particles in the
9766 * {particles} of the group must be 0 or 1.
9767 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009768 if ((elem->minOccurs == 1) && (elem->maxOccurs == 1)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009769 xmlAutomataNewOnceTrans2(ctxt->am, ctxt->state,
9770 ctxt->state,
9771 elem->name,
9772 elem->targetNamespace,
9773 1, 1, subtypes);
9774 } else if ((elem->minOccurs == 0) &&
9775 (elem->maxOccurs == 1)) {
9776
9777 xmlAutomataNewCountTrans2(ctxt->am, ctxt->state,
9778 ctxt->state,
9779 elem->name,
9780 elem->targetNamespace,
9781 0,
9782 1,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009783 subtypes);
9784 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009785 /*
9786 * NOTE: if maxOccurs == 0 then no transition will be
9787 * created.
9788 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009789 subtypes = subtypes->next;
9790 }
9791 lax = type->minOccurs == 0;
9792 ctxt->state =
9793 xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL,
9794 lax);
9795 break;
9796 }
9797 case XML_SCHEMA_TYPE_RESTRICTION:
9798 if (type->subtypes != NULL)
9799 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
9800 break;
9801 case XML_SCHEMA_TYPE_EXTENSION:
9802 if (type->baseType != NULL) {
9803 xmlSchemaTypePtr subtypes;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009804
9805 /*
9806 * TODO: Circular definitions will be checked at the
9807 * constraint level. So remove this when the complex type
9808 * constraints are implemented.
9809 */
Daniel Veillardf7627552004-04-22 07:15:40 +00009810 if (type->recurse) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009811 /* TODO: Change the error code. */
9812 xmlSchemaPCustomErr(ctxt,
9813 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
9814 NULL, type, type->node,
9815 "This item is circular", NULL);
Daniel Veillardf7627552004-04-22 07:15:40 +00009816 return;
9817 }
9818 type->recurse = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009819 xmlSchemaBuildAContentModel(type->baseType, ctxt, name);
Daniel Veillardf7627552004-04-22 07:15:40 +00009820 type->recurse = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009821 subtypes = type->subtypes;
9822 while (subtypes != NULL) {
9823 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
9824 subtypes = subtypes->next;
9825 }
9826 } else if (type->subtypes != NULL)
9827 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
9828 break;
9829 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00009830 /*
9831 * Handle model group definition references.
9832 * NOTE: type->subtypes is the referenced model grop definition;
9833 * and type->subtypes->subtypes is the model group (i.e. <all> or
9834 * <choice> or <sequence>).
9835 */
9836 if ((type->ref != NULL) && (type->subtypes != NULL) &&
9837 (type->subtypes->subtypes != NULL)) {
9838 xmlSchemaTypePtr modelGr;
9839 xmlAutomataStatePtr start, end;
9840
9841 modelGr = type->subtypes->subtypes;
9842 start = ctxt->state;
9843 end = xmlAutomataNewState(ctxt->am);
9844 if (type->maxOccurs == 1) {
9845 ctxt->state = start;
9846 xmlSchemaBuildAContentModel(modelGr, ctxt, name);
9847 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9848 } else {
9849 int counter;
9850 xmlAutomataStatePtr hop;
9851 int maxOccurs = type->maxOccurs == UNBOUNDED ?
9852 UNBOUNDED : type->maxOccurs - 1;
9853 int minOccurs =
9854 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
9855
9856 counter =
9857 xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
9858 hop = xmlAutomataNewState(ctxt->am);
9859 ctxt->state = start;
9860 xmlSchemaBuildAContentModel(modelGr, ctxt, name);
9861 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
9862 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
9863 counter);
9864 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
9865 counter);
9866 }
9867 if (type->minOccurs == 0) {
9868 xmlAutomataNewEpsilon(ctxt->am, start, end);
9869 }
9870 ctxt->state = end;
9871 break;
9872 }
9873 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009874 case XML_SCHEMA_TYPE_COMPLEX:
9875 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
9876 if (type->subtypes != NULL)
9877 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
9878 break;
William M. Brack2f2a6632004-08-20 23:09:47 +00009879 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
9880 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009881 default:
9882 xmlGenericError(xmlGenericErrorContext,
9883 "Found unexpected type %d in %s content model\n",
9884 type->type, name);
9885 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00009886 }
9887}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009888
Daniel Veillard4255d502002-04-16 15:50:10 +00009889/**
9890 * xmlSchemaBuildContentModel:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009891 * @type: the type definition (or reference)
Daniel Veillard4255d502002-04-16 15:50:10 +00009892 * @ctxt: the schema parser context
Daniel Veillarda84c0b32003-06-02 16:58:46 +00009893 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +00009894 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009895 * Builds the content model of the complex type.
Daniel Veillard4255d502002-04-16 15:50:10 +00009896 */
9897static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009898xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009899 xmlSchemaParserCtxtPtr ctxt,
9900 const xmlChar * name)
9901{
Daniel Veillard4255d502002-04-16 15:50:10 +00009902 xmlAutomataStatePtr start;
9903
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009904 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) || (type->ref != NULL) ||
9905 (type->contentType == XML_SCHEMA_CONTENT_BASIC) ||
9906 (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
9907 (type->contModel != NULL))
9908 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +00009909
9910#ifdef DEBUG_CONTENT
9911 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009912 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00009913#endif
9914
Daniel Veillard4255d502002-04-16 15:50:10 +00009915 ctxt->am = xmlNewAutomata();
9916 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009917 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009918 "Cannot create automata for complex tpye %s\n", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009919 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00009920 }
9921 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009922 xmlSchemaBuildAContentModel(type, ctxt, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00009923 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009924 type->contModel = xmlAutomataCompile(ctxt->am);
9925 if (type->contModel == NULL) {
9926 xmlSchemaPCustomErr(ctxt,
9927 XML_SCHEMAP_INTERNAL,
9928 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009929 "Failed to compile the content model", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009930 } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00009931 xmlSchemaPCustomErr(ctxt,
9932 XML_SCHEMAP_NOT_DETERMINISTIC,
9933 /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009934 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009935 "The content model is not determinist", NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +00009936 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +00009937#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009938 xmlGenericError(xmlGenericErrorContext,
9939 "Content model of %s:\n", name);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009940 xmlRegexpPrint(stderr, type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00009941#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +00009942 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00009943 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00009944 xmlFreeAutomata(ctxt->am);
9945 ctxt->am = NULL;
9946}
9947
9948/**
9949 * xmlSchemaRefFixupCallback:
9950 * @elem: the schema element context
9951 * @ctxt: the schema parser context
9952 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00009953 * Resolves the references of an element declaration
9954 * or particle, which has an element declaration as it's
9955 * term.
Daniel Veillard4255d502002-04-16 15:50:10 +00009956 */
9957static void
9958xmlSchemaRefFixupCallback(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009959 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009960 const xmlChar * name ATTRIBUTE_UNUSED,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009961 const xmlChar * context ATTRIBUTE_UNUSED,
9962 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00009963{
Daniel Veillardc0826a72004-08-10 14:17:33 +00009964 if ((ctxt == NULL) || (elem == NULL) ||
9965 ((elem != NULL) && (elem->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009966 return;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009967 elem->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
Daniel Veillard4255d502002-04-16 15:50:10 +00009968 if (elem->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009969 xmlSchemaElementPtr elemDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00009970
Daniel Veillardc0826a72004-08-10 14:17:33 +00009971 /*
9972 * TODO: Evaluate, what errors could occur if the declaration is not
9973 * found. It might be possible that the "typefixup" might crash if
9974 * no ref declaration was found.
9975 */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00009976 elemDecl = xmlSchemaGetElem(ctxt->schema, elem->ref, elem->refNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009977 if (elemDecl == NULL) {
9978 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009979 XML_SCHEMAP_SRC_RESOLVE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009980 NULL, (xmlSchemaTypePtr) elem, elem->node,
9981 "ref", elem->ref, elem->refNs,
9982 XML_SCHEMA_TYPE_ELEMENT, NULL);
9983 } else
9984 elem->refDecl = elemDecl;
9985 } else {
9986 if ((elem->subtypes == NULL) && (elem->namedType != NULL)) {
9987 xmlSchemaTypePtr type;
9988
9989 /* (type definition) ... otherwise the type definition ·resolved·
9990 * to by the ·actual value· of the type [attribute] ...
9991 */
9992 type = xmlSchemaGetType(ctxt->schema, elem->namedType,
9993 elem->namedTypeNs);
9994 if (type == NULL) {
9995 xmlSchemaPResCompAttrErr(ctxt,
9996 XML_SCHEMAP_SRC_RESOLVE,
9997 NULL, (xmlSchemaTypePtr) elem, elem->node,
9998 "type", elem->namedType, elem->namedTypeNs,
9999 XML_SCHEMA_TYPE_BASIC, "type definition");
10000 } else
10001 elem->subtypes = type;
10002 }
10003 if (elem->substGroup != NULL) {
10004 xmlSchemaElementPtr substHead;
10005
10006 /*
10007 * FIXME TODO: Do we need a new field in _xmlSchemaElement for
10008 * substitutionGroup?
10009 */
10010 substHead = xmlSchemaGetElem(ctxt->schema, elem->substGroup,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010011 elem->substGroupNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +000010012 if (substHead == NULL) {
10013 xmlSchemaPResCompAttrErr(ctxt,
10014 XML_SCHEMAP_SRC_RESOLVE,
10015 NULL, (xmlSchemaTypePtr) elem, NULL,
10016 "substitutionGroup", elem->substGroup, elem->substGroupNs,
10017 XML_SCHEMA_TYPE_ELEMENT, NULL);
10018 } else {
10019 xmlSchemaRefFixupCallback(substHead, ctxt, NULL, NULL, NULL);
10020 /*
10021 * (type definition)...otherwise the {type definition} of the
10022 * element declaration ·resolved· to by the ·actual value· of
10023 * the substitutionGroup [attribute], if present
10024 */
10025 if (elem->subtypes == NULL)
10026 elem->subtypes = substHead->subtypes;
10027 }
10028 }
10029 if ((elem->subtypes == NULL) && (elem->namedType == NULL) &&
10030 (elem->substGroup == NULL))
10031 elem->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
10032 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010033}
10034
William M. Bracke7091952004-05-11 15:09:58 +000010035/**
10036 * xmlSchemaParseListRefFixup:
10037 * @type: the schema type definition
10038 * @ctxt: the schema parser context
10039 *
10040 * Fixup of the itemType reference of the list type.
10041 */
Daniel Veillard377e1a92004-04-16 16:30:05 +000010042static void
William M. Bracke7091952004-05-11 15:09:58 +000010043xmlSchemaParseListRefFixup(xmlSchemaTypePtr type, xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010044{
Daniel Veillardc0826a72004-08-10 14:17:33 +000010045
Daniel Veillard01fa6152004-06-29 17:04:39 +000010046 if (((type->base == NULL) &&
10047 (type->subtypes == NULL)) ||
10048 ((type->base != NULL) &&
10049 (type->subtypes != NULL))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010050 /*
10051 * src-list-itemType-or-simpleType
10052 * Either the itemType [attribute] or the <simpleType> [child] of
10053 * the <list> element must be present, but not both.
Daniel Veillard01fa6152004-06-29 17:04:39 +000010054 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000010055 /*
10056 * TODO: Move this to the parse function.
10057 */
10058 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010059 XML_SCHEMAP_SRC_LIST_ITEMTYPE_OR_SIMPLETYPE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010060 NULL, type, type->node,
10061 "The attribute 'itemType' and the <simpleType> child "
10062 "are mutually exclusive", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010063 } else if (type->base!= NULL) {
10064 type->subtypes = xmlSchemaGetType(ctxt->schema, type->base, type->baseNs);
10065 if (type->subtypes == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010066 xmlSchemaPResCompAttrErr(ctxt,
10067 XML_SCHEMAP_SRC_RESOLVE,
10068 NULL, type, type->node,
10069 "itemType", type->base, type->baseNs,
10070 XML_SCHEMA_TYPE_SIMPLE, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010071 }
10072 }
10073 if ((type->subtypes != NULL) &&
10074 (type->subtypes->contentType == XML_SCHEMA_CONTENT_UNKNOWN))
10075 xmlSchemaTypeFixup(type->subtypes, ctxt, NULL);
William M. Bracke7091952004-05-11 15:09:58 +000010076}
10077
10078/**
10079 * xmlSchemaParseUnionRefCheck:
10080 * @typeDecl: the schema type definition
10081 * @ctxt: the schema parser context
10082 *
Daniel Veillard01fa6152004-06-29 17:04:39 +000010083 * Checks and builds the memberTypes of the union type.
10084 * Returns -1 in case of an internal error, 0 otherwise.
William M. Bracke7091952004-05-11 15:09:58 +000010085 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010086static int
William M. Bracke7091952004-05-11 15:09:58 +000010087xmlSchemaParseUnionRefCheck(xmlSchemaTypePtr type,
Daniel Veillard377e1a92004-04-16 16:30:05 +000010088 xmlSchemaParserCtxtPtr ctxt)
10089{
Daniel Veillardc0826a72004-08-10 14:17:33 +000010090
Daniel Veillard01fa6152004-06-29 17:04:39 +000010091 xmlSchemaTypeLinkPtr link, lastLink = NULL, prevLink, subLink, newLink;
10092 xmlSchemaTypePtr memberType, ctxtType;
Daniel Veillard377e1a92004-04-16 16:30:05 +000010093
Daniel Veillard01fa6152004-06-29 17:04:39 +000010094 /* 1 If the <union> alternative is chosen, then [Definition:]
10095 * define the explicit members as the type definitions ·resolved·
10096 * to by the items in the ·actual value· of the memberTypes [attribute],
10097 * if any, followed by the type definitions corresponding to the
10098 * <simpleType>s among the [children] of <union>, if any.
10099 */
Daniel Veillard377e1a92004-04-16 16:30:05 +000010100
Daniel Veillard01fa6152004-06-29 17:04:39 +000010101 if (type->type != XML_SCHEMA_TYPE_UNION)
10102 return (-1);
10103 if (ctxt->ctxtType == NULL) {
10104 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010105 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010106 "Internal error: xmlSchemaParseUnionRefCheck, no parent type "
10107 "available", NULL, NULL);
10108 return (-1);
10109 }
10110 /*
10111 * src-union-memberTypes-or-simpleTypes
10112 * Either the memberTypes [attribute] of the <union> element must
10113 * be non-empty or there must be at least one simpleType [child].
10114 */
10115 if ((type->base == NULL) &&
10116 (type->subtypes == NULL)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010117 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010118 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010119 NULL, NULL, type->node,
10120 "Either the attribute 'memberTypes' must be non-empty "
10121 "or there must be at least one <simpleType> child", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010122 }
10123
10124 ctxtType = ctxt->ctxtType;
10125 if (type->base != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010126 xmlAttrPtr attr;
10127 const xmlChar *cur, *end;
10128 xmlChar *tmp;
10129 const xmlChar *localName, *uri;
10130
10131 attr = xmlSchemaGetPropNode(type->node, "memberTypes");
Daniel Veillard01fa6152004-06-29 17:04:39 +000010132 cur = type->base;
10133 do {
10134 while (IS_BLANK_CH(*cur))
10135 cur++;
10136 end = cur;
10137 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
10138 end++;
10139 if (end == cur)
10140 break;
10141 tmp = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +000010142 xmlSchemaPValAttrNodeQNameValue(ctxt, ctxt->schema, NULL,
10143 NULL, attr, BAD_CAST tmp, &uri, NULL, &localName);
10144 memberType = xmlSchemaGetType(ctxt->schema, localName, uri);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010145 if (memberType == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010146 xmlSchemaPResCompAttrErr(ctxt,
10147 XML_SCHEMAP_UNKNOWN_MEMBER_TYPE,
10148 NULL, NULL, type->node, "memberTypes", localName, uri,
10149 XML_SCHEMA_TYPE_SIMPLE, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010150 } else {
10151 if (memberType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
10152 xmlSchemaTypeFixup(memberType, ctxt, NULL);
10153 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
10154 if (link == NULL) {
10155 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
10156 return (-1);
10157 }
10158 link->type = memberType;
10159 link->next = NULL;
10160 if (lastLink == NULL)
10161 ctxtType->memberTypes = link;
10162 else
10163 lastLink->next = link;
10164 lastLink = link;
10165 }
10166 xmlFree(tmp);
10167 cur = end;
10168 } while (*cur != 0);
10169 }
10170 /*
10171 * Add local simple types,
10172 */
10173 memberType = type->subtypes;
10174 while (memberType != NULL) {
10175 if (memberType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
10176 xmlSchemaTypeFixup(memberType, ctxt, NULL);
10177 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
10178 if (link == NULL) {
10179 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
10180 return (-1);
10181 }
10182 link->type = memberType;
10183 link->next = NULL;
10184 if (lastLink == NULL)
10185 ctxtType->memberTypes = link;
10186 else
10187 lastLink->next = link;
10188 lastLink = link;
10189 memberType = memberType->next;
10190 }
10191 /*
10192 * The actual value is then formed by replacing any union type
10193 * definition in the ·explicit members· with the members of their
10194 * {member type definitions}, in order.
10195 */
10196 link = ctxtType->memberTypes;
10197 while (link != NULL) {
10198 if (link->type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
10199 subLink = link->type->memberTypes;
10200 if (subLink != NULL) {
10201 link->type = subLink->type;
10202 if (subLink->next != NULL) {
10203 lastLink = link->next;
10204 subLink = subLink->next;
10205 prevLink = link;
10206 while (subLink != NULL) {
10207 newLink = (xmlSchemaTypeLinkPtr)
10208 xmlMalloc(sizeof(xmlSchemaTypeLink));
10209 if (newLink == NULL) {
10210 xmlSchemaPErrMemory(ctxt, "allocating a type link",
10211 NULL);
10212 return (-1);
10213 }
10214 newLink->type = memberType;
10215 prevLink->next = newLink;
10216 prevLink = newLink;
10217 newLink->next = lastLink;
10218
10219 subLink = subLink->next;
10220 }
10221 }
10222 }
10223 }
10224 link = link->next;
10225 }
10226
10227 return (0);
Daniel Veillard377e1a92004-04-16 16:30:05 +000010228}
10229
Daniel Veillard4255d502002-04-16 15:50:10 +000010230/**
Daniel Veillard3646d642004-06-02 19:19:14 +000010231 * xmlSchemaIsDerivedFromBuiltInType:
10232 * @ctxt: the schema parser context
10233 * @type: the type definition
10234 * @valType: the value type
10235 *
10236 *
10237 * Returns 1 if the type has the given value type, or
10238 * is derived from such a type.
10239 */
William M. Brack803812b2004-06-03 02:11:24 +000010240static int
Daniel Veillard3646d642004-06-02 19:19:14 +000010241xmlSchemaIsDerivedFromBuiltInType(xmlSchemaParserCtxtPtr ctxt,
10242 xmlSchemaTypePtr type, int valType)
10243{
10244 /* TODO: Check if this works in every case. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010245 if ((type->type == XML_SCHEMA_TYPE_BASIC) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000010246 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000010247 if (type->builtInType == valType)
Daniel Veillard3646d642004-06-02 19:19:14 +000010248 return(1);
10249 } else if (type->type == XML_SCHEMA_TYPE_ATTRIBUTE) {
10250 if (((xmlSchemaAttributePtr) type)->subtypes != NULL)
10251 return(xmlSchemaIsDerivedFromBuiltInType(ctxt,
10252 ((xmlSchemaAttributePtr) type)->subtypes, valType));
10253 } else if ((type->type == XML_SCHEMA_TYPE_RESTRICTION) ||
10254 (type->type == XML_SCHEMA_TYPE_EXTENSION)) {
10255 if (type->baseType != NULL)
10256 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->baseType,
10257 valType));
10258 } else if ((type->subtypes != NULL) &&
10259 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX) ||
10260 (type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
10261 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE) ||
10262 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
10263 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->subtypes,
10264 valType));
10265 }
10266
10267 return (0);
10268}
10269
10270/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000010271 * xmlSchemaIsDerivedFromBuiltInType:
10272 * @type: the simpleType definition
10273 *
10274 * Returns the primitive type of the given type or
10275 * NULL in case of error.
10276 */
10277static xmlSchemaTypePtr
10278xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
10279{
10280 while (type != NULL) {
10281 if (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE)
10282 return (type);
10283 type = type->baseType;
10284 }
10285
10286 return (NULL);
10287}
10288
10289
10290/**
Daniel Veillard3646d642004-06-02 19:19:14 +000010291 * xmlSchemaBuildAttributeUsesOwned:
10292 * @ctxt: the schema parser context
10293 * @type: the complex type definition
10294 * @cur: the attribute declaration list
10295 * @lastUse: the top of the attribute use list
10296 *
10297 * Builds the attribute uses list on the given complex type.
10298 * This one is supposed to be called by
10299 * xmlSchemaBuildAttributeValidation only.
10300 */
10301static int
10302xmlSchemaBuildAttributeUsesOwned(xmlSchemaParserCtxtPtr ctxt,
10303 xmlSchemaAttributePtr cur,
10304 xmlSchemaAttributeLinkPtr *uses,
10305 xmlSchemaAttributeLinkPtr *lastUse)
10306{
10307 xmlSchemaAttributeLinkPtr tmp;
10308 while (cur != NULL) {
10309 if (cur->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
10310 /*
10311 * W3C: "2 The {attribute uses} of the attribute groups ·resolved·
10312 * to by the ·actual value·s of the ref [attribute] of the
10313 * <attributeGroup> [children], if any."
10314 */
10315 if (xmlSchemaBuildAttributeUsesOwned(ctxt,
10316 ((xmlSchemaAttributeGroupPtr) cur)->attributes, uses,
10317 lastUse) == -1) {
10318 return (-1);
10319 }
10320 } else {
10321 /* W3C: "1 The set of attribute uses corresponding to the
10322 * <attribute> [children], if any."
10323 */
10324 tmp = (xmlSchemaAttributeLinkPtr)
10325 xmlMalloc(sizeof(xmlSchemaAttributeLink));
10326 if (tmp == NULL) {
10327 xmlSchemaPErrMemory(ctxt, "building attribute uses", NULL);
10328 return (-1);
10329 }
10330 tmp->attr = cur;
10331 tmp->next = NULL;
10332 if (*uses == NULL)
10333 *uses = tmp;
10334 else
10335 (*lastUse)->next = tmp;
10336 *lastUse = tmp;
10337 }
10338 cur = cur->next;
10339 }
10340 return (0);
10341}
10342
Daniel Veillard50355f02004-06-08 17:52:16 +000010343/**
10344 * xmlSchemaCloneWildcardNsConstraints:
10345 * @ctxt: the schema parser context
10346 * @dest: the destination wildcard
10347 * @source: the source wildcard
10348 *
10349 * Clones the namespace constraints of source
10350 * and assignes them to dest.
10351 * Returns -1 on internal error, 0 otherwise.
10352 */
Daniel Veillard3646d642004-06-02 19:19:14 +000010353static int
10354xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
10355 xmlSchemaWildcardPtr *dest,
10356 xmlSchemaWildcardPtr source)
10357{
10358 xmlSchemaWildcardNsPtr cur, tmp, last;
10359
10360 if ((source == NULL) || (*dest == NULL))
10361 return(-1);
10362 (*dest)->any = source->any;
10363 cur = source->nsSet;
10364 last = NULL;
10365 while (cur != NULL) {
10366 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
10367 if (tmp == NULL)
10368 return(-1);
10369 tmp->value = cur->value;
10370 if (last == NULL)
10371 (*dest)->nsSet = tmp;
10372 else
10373 last->next = tmp;
10374 last = tmp;
10375 cur = cur->next;
10376 }
10377 if ((*dest)->negNsSet != NULL)
10378 xmlSchemaFreeWildcardNsSet((*dest)->negNsSet);
10379 if (source->negNsSet != NULL) {
10380 (*dest)->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
10381 if ((*dest)->negNsSet == NULL)
10382 return(-1);
10383 (*dest)->negNsSet->value = source->negNsSet->value;
10384 } else
10385 (*dest)->negNsSet = NULL;
10386 return(0);
10387}
10388
Daniel Veillard50355f02004-06-08 17:52:16 +000010389/**
10390 * xmlSchemaUnionWildcards:
10391 * @ctxt: the schema parser context
10392 * @completeWild: the first wildcard
10393 * @curWild: the second wildcard
10394 *
10395 * Unions the namespace constraints of the given wildcards.
10396 * @completeWild will hold the resulting union.
10397 * Returns a positive error code on failure, -1 in case of an
10398 * internal error, 0 otherwise.
10399 */
Daniel Veillard3646d642004-06-02 19:19:14 +000010400static int
10401xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
10402 xmlSchemaWildcardPtr completeWild,
10403 xmlSchemaWildcardPtr curWild)
10404{
10405 xmlSchemaWildcardNsPtr cur, curB, tmp;
10406
10407 /*
10408 * 1 If O1 and O2 are the same value, then that value must be the
10409 * value.
10410 */
10411 if ((completeWild->any == curWild->any) &&
10412 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
10413 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
10414
10415 if ((completeWild->negNsSet == NULL) ||
10416 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
10417
10418 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000010419 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000010420
10421 /*
10422 * Check equality of sets.
10423 */
10424 cur = completeWild->nsSet;
10425 while (cur != NULL) {
10426 found = 0;
10427 curB = curWild->nsSet;
10428 while (curB != NULL) {
10429 if (cur->value == curB->value) {
10430 found = 1;
10431 break;
10432 }
10433 curB = curB->next;
10434 }
10435 if (!found)
10436 break;
10437 cur = cur->next;
10438 }
10439 if (found)
10440 return(0);
10441 } else
10442 return(0);
10443 }
10444 }
10445 /*
10446 * 2 If either O1 or O2 is any, then any must be the value
10447 */
Daniel Veillard50355f02004-06-08 17:52:16 +000010448 if (completeWild->any != curWild->any) {
Daniel Veillard3646d642004-06-02 19:19:14 +000010449 if (completeWild->any == 0) {
10450 completeWild->any = 1;
10451 if (completeWild->nsSet != NULL) {
10452 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
10453 completeWild->nsSet = NULL;
10454 }
10455 if (completeWild->negNsSet != NULL) {
10456 xmlFree(completeWild->negNsSet);
10457 completeWild->negNsSet = NULL;
10458 }
10459 }
Daniel Veillard50355f02004-06-08 17:52:16 +000010460 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000010461 }
10462 /*
10463 * 3 If both O1 and O2 are sets of (namespace names or ·absent·),
10464 * then the union of those sets must be the value.
10465 */
10466 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
10467 int found;
10468 xmlSchemaWildcardNsPtr start;
10469
10470 cur = curWild->nsSet;
10471 start = completeWild->nsSet;
10472 while (cur != NULL) {
10473 found = 0;
10474 curB = start;
10475 while (curB != NULL) {
10476 if (cur->value == curB->value) {
10477 found = 1;
10478 break;
10479 }
10480 curB = curB->next;
10481 }
10482 if (!found) {
10483 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
10484 if (tmp == NULL)
10485 return (-1);
10486 tmp->value = cur->value;
10487 tmp->next = completeWild->nsSet;
10488 completeWild->nsSet = tmp;
10489 }
10490 cur = cur->next;
10491 }
10492
10493 return(0);
10494 }
10495 /*
10496 * 4 If the two are negations of different values (namespace names
10497 * or ·absent·), then a pair of not and ·absent· must be the value.
10498 */
10499 if ((completeWild->negNsSet != NULL) &&
10500 (curWild->negNsSet != NULL) &&
10501 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
10502 completeWild->negNsSet->value = NULL;
Daniel Veillard50355f02004-06-08 17:52:16 +000010503
10504 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +000010505 }
10506 /*
10507 * 5.
10508 */
10509 if (((completeWild->negNsSet != NULL) &&
10510 (completeWild->negNsSet->value != NULL) &&
10511 (curWild->nsSet != NULL)) ||
10512 ((curWild->negNsSet != NULL) &&
10513 (curWild->negNsSet->value != NULL) &&
10514 (completeWild->nsSet != NULL))) {
10515
10516 int nsFound, absentFound = 0;
10517
10518 if (completeWild->nsSet != NULL) {
10519 cur = completeWild->nsSet;
10520 curB = curWild->negNsSet;
10521 } else {
10522 cur = curWild->nsSet;
10523 curB = completeWild->negNsSet;
10524 }
10525 nsFound = 0;
10526 while (cur != NULL) {
10527 if (cur->value == NULL)
10528 absentFound = 1;
10529 else if (cur->value == curB->value)
10530 nsFound = 1;
10531 if (nsFound && absentFound)
10532 break;
10533 cur = cur->next;
10534 }
10535
10536 if (nsFound && absentFound) {
10537 /*
10538 * 5.1 If the set S includes both the negated namespace
10539 * name and ·absent·, then any must be the value.
10540 */
10541 completeWild->any = 1;
10542 if (completeWild->nsSet != NULL) {
10543 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
10544 completeWild->nsSet = NULL;
10545 }
10546 if (completeWild->negNsSet != NULL) {
10547 xmlFree(completeWild->negNsSet);
10548 completeWild->negNsSet = NULL;
10549 }
10550 } else if (nsFound && (!absentFound)) {
10551 /*
10552 * 5.2 If the set S includes the negated namespace name
10553 * but not ·absent·, then a pair of not and ·absent· must
10554 * be the value.
10555 */
10556 if (completeWild->nsSet != NULL) {
10557 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
10558 completeWild->nsSet = NULL;
10559 }
10560 if (completeWild->negNsSet == NULL) {
10561 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
10562 if (completeWild->negNsSet == NULL)
10563 return (-1);
10564 }
10565 completeWild->negNsSet->value = NULL;
10566 } else if ((!nsFound) && absentFound) {
10567 /*
10568 * 5.3 If the set S includes ·absent· but not the negated
10569 * namespace name, then the union is not expressible.
10570 */
10571 xmlSchemaPErr(ctxt, completeWild->node,
10572 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010573 "The union of the wilcard is not expressible.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +000010574 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000010575 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +000010576 } else if ((!nsFound) && (!absentFound)) {
10577 /*
10578 * 5.4 If the set S does not include either the negated namespace
10579 * name or ·absent·, then whichever of O1 or O2 is a pair of not
10580 * and a namespace name must be the value.
10581 */
10582 if (completeWild->negNsSet == NULL) {
10583 if (completeWild->nsSet != NULL) {
10584 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
10585 completeWild->nsSet = NULL;
10586 }
10587 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
10588 if (completeWild->negNsSet == NULL)
10589 return (-1);
10590 completeWild->negNsSet->value = curWild->negNsSet->value;
10591 }
10592 }
10593 return (0);
10594 }
10595 /*
10596 * 6.
10597 */
10598 if (((completeWild->negNsSet != NULL) &&
10599 (completeWild->negNsSet->value == NULL) &&
10600 (curWild->nsSet != NULL)) ||
10601 ((curWild->negNsSet != NULL) &&
10602 (curWild->negNsSet->value == NULL) &&
10603 (completeWild->nsSet != NULL))) {
10604
10605 if (completeWild->nsSet != NULL) {
10606 cur = completeWild->nsSet;
10607 } else {
10608 cur = curWild->nsSet;
10609 }
10610 while (cur != NULL) {
10611 if (cur->value == NULL) {
10612 /*
10613 * 6.1 If the set S includes ·absent·, then any must be the
10614 * value.
10615 */
10616 completeWild->any = 1;
10617 if (completeWild->nsSet != NULL) {
10618 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
10619 completeWild->nsSet = NULL;
10620 }
10621 if (completeWild->negNsSet != NULL) {
10622 xmlFree(completeWild->negNsSet);
10623 completeWild->negNsSet = NULL;
10624 }
10625 return (0);
10626 }
10627 cur = cur->next;
10628 }
10629 if (completeWild->negNsSet == NULL) {
10630 /*
10631 * 6.2 If the set S does not include ·absent·, then a pair of not
10632 * and ·absent· must be the value.
10633 */
10634 if (completeWild->nsSet != NULL) {
10635 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
10636 completeWild->nsSet = NULL;
10637 }
10638 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
10639 if (completeWild->negNsSet == NULL)
10640 return (-1);
10641 completeWild->negNsSet->value = NULL;
10642 }
10643 return (0);
10644 }
10645 return (0);
10646
10647}
10648
Daniel Veillard50355f02004-06-08 17:52:16 +000010649/**
10650 * xmlSchemaIntersectWildcards:
10651 * @ctxt: the schema parser context
10652 * @completeWild: the first wildcard
10653 * @curWild: the second wildcard
10654 *
10655 * Intersects the namespace constraints of the given wildcards.
10656 * @completeWild will hold the resulting intersection.
10657 * Returns a positive error code on failure, -1 in case of an
10658 * internal error, 0 otherwise.
10659 */
Daniel Veillard3646d642004-06-02 19:19:14 +000010660static int
10661xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
10662 xmlSchemaWildcardPtr completeWild,
10663 xmlSchemaWildcardPtr curWild)
10664{
William M. Brack803812b2004-06-03 02:11:24 +000010665 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000010666
10667 /*
10668 * 1 If O1 and O2 are the same value, then that value must be the
10669 * value.
10670 */
10671 if ((completeWild->any == curWild->any) &&
10672 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
10673 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
10674
10675 if ((completeWild->negNsSet == NULL) ||
10676 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
10677
10678 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000010679 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000010680
10681 /*
10682 * Check equality of sets.
10683 */
10684 cur = completeWild->nsSet;
10685 while (cur != NULL) {
10686 found = 0;
10687 curB = curWild->nsSet;
10688 while (curB != NULL) {
10689 if (cur->value == curB->value) {
10690 found = 1;
10691 break;
10692 }
10693 curB = curB->next;
10694 }
10695 if (!found)
10696 break;
10697 cur = cur->next;
10698 }
10699 if (found)
10700 return(0);
10701 } else
10702 return(0);
10703 }
10704 }
10705 /*
10706 * 2 If either O1 or O2 is any, then the other must be the value.
10707 */
10708 if ((completeWild->any != curWild->any) && (completeWild->any)) {
10709 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
10710 return(-1);
10711 return(0);
10712 }
10713 /*
10714 * 3 If either O1 or O2 is a pair of not and a value (a namespace
10715 * name or ·absent·) and the other is a set of (namespace names or
10716 * ·absent·), then that set, minus the negated value if it was in
10717 * the set, minus ·absent· if it was in the set, must be the value.
10718 */
10719 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
10720 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
10721 const xmlChar *neg;
10722
10723 if (completeWild->nsSet == NULL) {
10724 neg = completeWild->negNsSet->value;
10725 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
10726 return(-1);
10727 } else
10728 neg = curWild->negNsSet->value;
10729 /*
10730 * Remove absent and negated.
10731 */
10732 prev = NULL;
10733 cur = completeWild->nsSet;
10734 while (cur != NULL) {
10735 if (cur->value == NULL) {
10736 if (prev == NULL)
10737 completeWild->nsSet = cur->next;
10738 else
10739 prev->next = cur->next;
10740 xmlFree(cur);
10741 break;
10742 }
10743 prev = cur;
10744 cur = cur->next;
10745 }
10746 if (neg != NULL) {
10747 prev = NULL;
10748 cur = completeWild->nsSet;
10749 while (cur != NULL) {
10750 if (cur->value == neg) {
10751 if (prev == NULL)
10752 completeWild->nsSet = cur->next;
10753 else
10754 prev->next = cur->next;
10755 xmlFree(cur);
10756 break;
10757 }
10758 prev = cur;
10759 cur = cur->next;
10760 }
10761 }
10762
10763 return(0);
10764 }
10765 /*
10766 * 4 If both O1 and O2 are sets of (namespace names or ·absent·),
10767 * then the intersection of those sets must be the value.
10768 */
10769 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
10770 int found;
10771
10772 cur = completeWild->nsSet;
10773 prev = NULL;
10774 while (cur != NULL) {
10775 found = 0;
10776 curB = curWild->nsSet;
10777 while (curB != NULL) {
10778 if (cur->value == curB->value) {
10779 found = 1;
10780 break;
10781 }
10782 curB = curB->next;
10783 }
10784 if (!found) {
10785 if (prev == NULL)
10786 completeWild->nsSet = cur->next;
10787 else
10788 prev->next = cur->next;
10789 tmp = cur->next;
10790 xmlFree(cur);
10791 cur = tmp;
10792 continue;
10793 }
10794 prev = cur;
10795 cur = cur->next;
10796 }
10797
10798 return(0);
10799 }
10800 /* 5 If the two are negations of different namespace names,
10801 * then the intersection is not expressible
10802 */
10803 if ((completeWild->negNsSet != NULL) &&
10804 (curWild->negNsSet != NULL) &&
10805 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
10806 (completeWild->negNsSet->value != NULL) &&
10807 (curWild->negNsSet->value != NULL)) {
10808
10809 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010810 "The intersection of the wilcard is not expressible.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +000010811 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000010812 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +000010813 }
10814 /*
10815 * 6 If the one is a negation of a namespace name and the other
10816 * is a negation of ·absent·, then the one which is the negation
10817 * of a namespace name must be the value.
10818 */
10819 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
10820 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
10821 (completeWild->negNsSet->value == NULL)) {
10822 completeWild->negNsSet->value = curWild->negNsSet->value;
10823 }
10824 return(0);
10825}
10826
Daniel Veillard50355f02004-06-08 17:52:16 +000010827/**
10828 * xmlSchemaIsWildcardNsConstraintSubset:
10829 * @ctxt: the schema parser context
10830 * @wildA: the first wildcard
10831 * @wildB: the second wildcard
10832 *
10833 * Returns 1 if the namespace constraint of @wildA is an intensional
10834 * subset of @wildB, 0 otherwise.
10835 */
10836static int
Daniel Veillardc0826a72004-08-10 14:17:33 +000010837xmlSchemaIsWildcardNsConstraintSubset(xmlSchemaWildcardPtr wildA,
10838 xmlSchemaWildcardPtr wildB)
Daniel Veillard50355f02004-06-08 17:52:16 +000010839{
Daniel Veillard3646d642004-06-02 19:19:14 +000010840
Daniel Veillard50355f02004-06-08 17:52:16 +000010841 /*
10842 * Schema Component Constraint: Wildcard Subset
10843 */
10844 /*
10845 * 1 super must be any.
10846 */
10847 if (wildB->any)
10848 return (1);
10849 /*
10850 * 2.1 sub must be a pair of not and a namespace name or ·absent·.
10851 * 2.2 super must be a pair of not and the same value.
10852 */
10853 if ((wildA->negNsSet != NULL) &&
10854 (wildB->negNsSet != NULL) &&
10855 (wildA->negNsSet->value == wildA->negNsSet->value))
10856 return (1);
10857 /*
10858 * 3.1 sub must be a set whose members are either namespace names or ·absent·.
10859 */
10860 if (wildA->nsSet != NULL) {
10861 /*
10862 * 3.2.1 super must be the same set or a superset thereof.
10863 */
10864 if (wildB->nsSet != NULL) {
10865 xmlSchemaWildcardNsPtr cur, curB;
10866 int found = 0;
10867
10868 cur = wildA->nsSet;
10869 while (cur != NULL) {
10870 found = 0;
10871 curB = wildB->nsSet;
10872 while (curB != NULL) {
10873 if (cur->value == curB->value) {
10874 found = 1;
10875 break;
10876 }
10877 curB = curB->next;
10878 }
10879 if (!found)
10880 return (0);
10881 cur = cur->next;
10882 }
10883 if (found)
10884 return (1);
10885 } else if (wildB->negNsSet != NULL) {
10886 xmlSchemaWildcardNsPtr cur;
10887 /*
10888 * 3.2.2 super must be a pair of not and a namespace name or
10889 * ·absent· and that value must not be in sub's set.
10890 */
10891 cur = wildA->nsSet;
10892 while (cur != NULL) {
10893 if (cur->value == wildB->negNsSet->value)
10894 return (0);
10895 cur = cur->next;
10896 }
10897 return (1);
10898 }
10899 }
10900 return (0);
10901}
10902
10903/**
10904 * xmlSchemaBuildCompleteAttributeWildcard:
10905 * @ctxt: the schema parser context
10906 * @attrs: the attribute list
10907 * @completeWild: the resulting complete wildcard
10908 *
10909 * Returns -1 in case of an internal error, 0 otherwise.
10910 */
10911static int
10912xmlSchemaBuildCompleteAttributeWildcard(xmlSchemaParserCtxtPtr ctxt,
10913 xmlSchemaAttributePtr attrs,
10914 xmlSchemaWildcardPtr *completeWild)
Daniel Veillard3646d642004-06-02 19:19:14 +000010915{
10916 while (attrs != NULL) {
10917 if (attrs->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
10918 xmlSchemaAttributeGroupPtr group;
10919
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010920 group = (xmlSchemaAttributeGroupPtr) attrs;
10921 /*
10922 * Handle attribute group references.
10923 */
10924 if (group->ref != NULL) {
10925 if (group->refItem == NULL) {
10926 /*
10927 * TODO: Should we raise a warning here?
10928 */
10929 /*
10930 * The referenced attribute group definition could not
10931 * be resolved beforehand, so skip.
10932 */
10933 attrs = attrs->next;
10934 continue;
10935 } else
10936 group = group->refItem;
10937 }
10938 /*
10939 * For every attribute group definition, an intersected wildcard
10940 * will be created (assumed that a wildcard exists on the
10941 * particular attr. gr. def. or on any contained attr. gr. def
10942 * at all).
10943 * The flag XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED ensures
10944 * that the intersection will be performed only once.
10945 */
Daniel Veillard3646d642004-06-02 19:19:14 +000010946 if ((group->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
10947 if (group->attributes != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000010948 if (xmlSchemaBuildCompleteAttributeWildcard(ctxt,
10949 group->attributes, &group->attributeWildcard) == -1)
10950 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000010951 }
10952 group->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
10953 }
10954 if (group->attributeWildcard != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000010955 if (*completeWild == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000010956 /*
10957 * Copy the first encountered wildcard as context, except for the annotation.
10958 */
Daniel Veillard50355f02004-06-08 17:52:16 +000010959 *completeWild = xmlSchemaAddWildcard(ctxt);
10960 (*completeWild)->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
10961 if (xmlSchemaCloneWildcardNsConstraints(ctxt,
10962 completeWild, group->attributeWildcard) == -1)
10963 return (-1);
10964 (*completeWild)->processContents = group->attributeWildcard->processContents;
Daniel Veillard3646d642004-06-02 19:19:14 +000010965 /*
10966 * Although the complete wildcard might not correspond to any
10967 * node in the schema, we will save this context node.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010968 * TODO: Hmm, is this sane?
Daniel Veillard3646d642004-06-02 19:19:14 +000010969 */
Daniel Veillard50355f02004-06-08 17:52:16 +000010970 (*completeWild)->node = group->attributeWildcard->node;
10971
10972 } else if (xmlSchemaIntersectWildcards(ctxt, *completeWild, group->attributeWildcard) == -1) {
10973 xmlSchemaFreeWildcard(*completeWild);
10974 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000010975 }
10976 }
10977 }
10978 attrs = attrs->next;
10979 }
10980
Daniel Veillard50355f02004-06-08 17:52:16 +000010981 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000010982}
10983
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010984static int
10985xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributePtr item,
10986 int *fixed,
10987 const xmlChar **value,
10988 xmlSchemaValPtr *val)
10989{
10990 *fixed = 0;
10991 *value = NULL;
10992 if (val != 0)
10993 *val = NULL;
10994
10995 if (item->defValue == NULL)
10996 item = item->refDecl;
10997
10998 if (item == NULL)
10999 return (0);
11000
11001 if (item->defValue != NULL) {
11002 *value = item->defValue;
11003 if (val != 0)
11004 *val = item->defVal;
11005 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
11006 *fixed = 1;
11007 return (1);
11008 }
11009 return (0);
11010}
Daniel Veillard3646d642004-06-02 19:19:14 +000011011/**
11012 * xmlSchemaMatchesWildcardNs:
11013 * @wild: the wildcard
11014 * @ns: the namespace
11015 *
11016 *
11017 * Returns 1 if the given namespace matches the wildcard,
11018 * 0 otherwise.
11019 */
11020static int
11021xmlSchemaMatchesWildcardNs(xmlSchemaWildcardPtr wild, const xmlChar* ns)
11022{
11023 if (wild == NULL)
11024 return(0);
11025
11026 if (wild->any)
11027 return(1);
11028 else if (wild->nsSet != NULL) {
11029 xmlSchemaWildcardNsPtr cur;
11030
11031 cur = wild->nsSet;
11032 while (cur != NULL) {
11033 if (xmlStrEqual(cur->value, ns))
11034 return(1);
11035 cur = cur->next;
11036 }
11037 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
11038 (!xmlStrEqual(wild->negNsSet->value, ns)))
11039 return(1);
11040
11041 return(0);
11042}
11043
11044/**
11045 * xmlSchemaBuildAttributeValidation:
11046 * @ctxt: the schema parser context
11047 * @type: the complex type definition
11048 *
11049 *
11050 * Builds the wildcard and the attribute uses on the given complex type.
11051 * Returns -1 if an internal error occurs, 0 otherwise.
11052 */
11053static int
11054xmlSchemaBuildAttributeValidation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaTypePtr type)
11055{
11056 xmlSchemaTypePtr baseType = NULL;
11057 xmlSchemaAttributeLinkPtr cur, base, tmp, id = NULL, prev = NULL, uses = NULL,
William M. Brack803812b2004-06-03 02:11:24 +000011058 lastUse = NULL, lastBaseUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000011059 xmlSchemaAttributePtr attrs;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011060 xmlSchemaTypePtr anyType;
Daniel Veillard50355f02004-06-08 17:52:16 +000011061 int baseIsAnyType = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011062 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000011063 int err = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000011064
Daniel Veillard01fa6152004-06-29 17:04:39 +000011065 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Daniel Veillard3646d642004-06-02 19:19:14 +000011066 /*
11067 * Complex Type Definition with complex content Schema Component.
11068 *
11069 * Attribute uses.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011070 * TODO: Add checks for absent referenced attribute declarations and
11071 * simple types.
Daniel Veillard3646d642004-06-02 19:19:14 +000011072 */
11073 if (type->attributeUses != NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011074 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011075 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillard3646d642004-06-02 19:19:14 +000011076 "attribute uses already builded.\n",
11077 NULL, NULL);
11078 return (-1);
11079 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011080 if (type->baseType == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011081 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011082 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011083 "complex type '%s' has no base type.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011084 type->name, NULL);
11085 return (-1);
11086 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011087 baseType = type->baseType;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011088 if (baseType == anyType)
11089 baseIsAnyType = 1;
11090 /*
11091 * Inherit the attribute uses of the base type.
11092 */
11093 /*
11094 * NOTE: It is allowed to "extend" the anyType complex type.
11095 */
11096 if (!baseIsAnyType) {
11097 if (baseType != NULL) {
11098 for (cur = baseType->attributeUses; cur != NULL; cur = cur->next) {
11099 tmp = (xmlSchemaAttributeLinkPtr)
11100 xmlMalloc(sizeof(xmlSchemaAttributeLink));
11101 if (tmp == NULL) {
11102 xmlSchemaPErrMemory(ctxt,
11103 "building attribute uses of complexType", NULL);
11104 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000011105 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011106 tmp->attr = cur->attr;
11107 tmp->next = NULL;
11108 if (type->attributeUses == NULL) {
11109 type->attributeUses = tmp;
11110 } else
11111 lastBaseUse->next = tmp;
11112 lastBaseUse = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000011113 }
11114 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011115 }
11116 if ((type->subtypes != NULL) &&
11117 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
11118 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011119 /*
11120 * type --> (<simpleContent>|<complexContent>)
11121 * --> (<restriction>|<extension>) --> attributes
11122 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011123 attrs = type->subtypes->subtypes->attributes;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011124 } else {
11125 /* Short hand form of the complexType. */
11126 attrs = type->attributes;
11127 }
11128 /*
11129 * Handle attribute wildcards.
11130 */
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000011131 err = xmlSchemaBuildCompleteAttributeWildcard(ctxt,
11132 attrs, &type->attributeWildcard);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011133 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011134 * NOTE: During the parse time, the wildcard is created on the complexType
11135 * directly, if encountered in a <restriction> or <extension> element.
Daniel Veillard01fa6152004-06-29 17:04:39 +000011136 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011137 if (err == -1) {
11138 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
11139 "Internal error: xmlSchemaBuildAttributeValidation: "
11140 "failed to build an intersected attribute wildcard.\n",
11141 NULL, NULL);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000011142 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011143 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011144
11145 if ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
11146 ((baseIsAnyType) ||
11147 ((baseType != NULL) &&
11148 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
11149 (baseType->attributeWildcard != NULL)))) {
11150 if (type->attributeWildcard != NULL) {
11151 /*
11152 * Union the complete wildcard with the base wildcard.
11153 */
11154 if (xmlSchemaUnionWildcards(ctxt, type->attributeWildcard,
11155 baseType->attributeWildcard) == -1)
11156 return (-1);
11157 } else {
11158 /*
11159 * Just inherit the wildcard.
11160 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011161 /*
11162 * NOTE: This is the only case where an attribute
11163 * wildcard is shared.
11164 */
11165 if (type->flags & XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD)
11166 type->flags ^= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011167 type->attributeWildcard = baseType->attributeWildcard;
Daniel Veillard50355f02004-06-08 17:52:16 +000011168 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011169 }
11170
11171 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
11172 if (type->attributeWildcard != NULL) {
11173 /*
11174 * Derivation Valid (Restriction, Complex)
11175 * 4.1 The {base type definition} must also have one.
11176 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011177 if (baseType->attributeWildcard == NULL) {
11178 xmlSchemaPCustomErr(ctxt,
11179 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
11180 NULL, type, NULL,
11181 "The type has an attribute wildcard, "
11182 "but the base type %s does not have one",
11183 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11184 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011185 return (1);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011186 } else if (xmlSchemaIsWildcardNsConstraintSubset(
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011187 type->attributeWildcard, baseType->attributeWildcard) == 0) {
11188 /* 4.2 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011189 xmlSchemaPCustomErr(ctxt,
11190 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
11191 NULL, type, NULL,
11192 "The attribute wildcard is not a valid "
11193 "subset of the wildcard in the base type %s",
11194 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11195 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011196 return (1);
11197 }
11198 /* 4.3 Unless the {base type definition} is the ·ur-type
11199 * definition·, the complex type definition's {attribute
11200 * wildcard}'s {process contents} must be identical to or
11201 * stronger than the {base type definition}'s {attribute
11202 * wildcard}'s {process contents}, where strict is stronger
11203 * than lax is stronger than skip.
11204 */
11205 if ((type->baseType != anyType) &&
11206 (type->attributeWildcard->processContents <
11207 baseType->attributeWildcard->processContents)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011208 xmlSchemaPCustomErr(ctxt,
11209 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
11210 NULL, type, NULL,
11211 "The 'process contents' of the attribute wildcard is weaker than "
11212 "the one in the base type %s",
11213 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11214 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011215 return (1);
11216 }
11217 }
11218 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
11219 /*
11220 * Derivation Valid (Extension)
11221 * At this point the type and the base have both, either
11222 * no wildcard or a wildcard.
11223 */
11224 if ((baseType->attributeWildcard != NULL) &&
11225 (baseType->attributeWildcard != type->attributeWildcard)) {
11226 /* 1.3 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011227 if (xmlSchemaIsWildcardNsConstraintSubset(
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011228 baseType->attributeWildcard, type->attributeWildcard) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011229 xmlSchemaPCustomErr(ctxt,
11230 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
11231 NULL, type, NULL,
11232 "The attribute wildcard is not a valid "
11233 "superset of the one in the base type %s",
11234 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11235 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011236 return (1);
11237 }
11238 }
11239 }
11240
Daniel Veillard3646d642004-06-02 19:19:14 +000011241 /*
11242 * Gather attribute uses defined by this type.
11243 */
11244 if (attrs != NULL) {
11245 if (xmlSchemaBuildAttributeUsesOwned(ctxt, attrs,
11246 &uses, &lastUse) == -1) {
11247 return (-1);
11248 }
11249 }
11250 /* 3.4.6 -> Complex Type Definition Properties Correct 4.
11251 * "Two distinct attribute declarations in the {attribute uses} must
11252 * not have identical {name}s and {target namespace}s."
11253 *
11254 * For "extension" this is done further down.
11255 */
11256 if ((uses != NULL) && ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
11257 cur = uses;
11258 while (cur != NULL) {
11259 tmp = cur->next;
11260 while (tmp != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011261 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
11262 xmlSchemaGetAttrName(tmp->attr))) &&
11263 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
11264 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
11265
11266 xmlSchemaPAttrUseErr(ctxt,
11267 XML_SCHEMAP_CT_PROPS_CORRECT_4,
11268 NULL, type, NULL, cur->attr,
11269 "Duplicate attribute use %s specified",
11270 xmlSchemaFormatNsUriLocal(&str,
11271 xmlSchemaGetAttrTargetNsURI(tmp->attr),
11272 xmlSchemaGetAttrName(tmp->attr))
11273 );
11274 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000011275 break;
11276 }
11277 tmp = tmp->next;
11278 }
11279 cur = cur->next;
11280 }
11281 }
11282 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
11283 /*
11284 * Derive by restriction.
11285 */
11286 if (baseIsAnyType) {
11287 type->attributeUses = uses;
11288 } else {
11289 int found;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011290 const xmlChar *bEffValue;
11291 int effFixed;
Daniel Veillard3646d642004-06-02 19:19:14 +000011292
11293 cur = uses;
11294 while (cur != NULL) {
11295 found = 0;
11296 base = type->attributeUses;
11297 while (base != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011298 if (xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
11299 xmlSchemaGetAttrName(base->attr)) &&
11300 xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
11301 xmlSchemaGetAttrTargetNsURI(base->attr))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011302
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011303 found = 1;
11304
Daniel Veillard3646d642004-06-02 19:19:14 +000011305 if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
11306 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
11307 /*
11308 * derivation-ok-restriction 2.1.1
Daniel Veillardc0826a72004-08-10 14:17:33 +000011309 */
11310 xmlSchemaPAttrUseErr(ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000011311 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011312 NULL, type, NULL, cur->attr,
11313 "The 'optional' use is inconsistent with a matching "
11314 "'required' use of the base type", NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000011315 } else if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
11316 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
11317 /*
11318 * derivation-ok-restriction 3
11319 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011320 xmlSchemaPCustomErr(ctxt,
11321 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
11322 NULL, type, NULL,
11323 "A matching attribute use for the 'required' "
11324 "attribute use %s of the base type is missing",
11325 xmlSchemaFormatNsUriLocal(&str,
11326 xmlSchemaGetAttrTargetNsURI(base->attr),
11327 xmlSchemaGetAttrName(base->attr)));
11328 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000011329 } else {
11330 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011331 * 2.1.3 [Definition:] Let the effective value
11332 * constraint of an attribute use be its {value
11333 * constraint}, if present, otherwise its {attribute
11334 * declaration}'s {value constraint} .
11335 */
11336 xmlSchemaGetEffectiveValueConstraint(base->attr, &effFixed,
11337 &bEffValue, 0);
11338 /*
11339 * 2.1.3 ... one of the following must be true
11340 *
11341 * 2.1.3.1 B's ·effective value constraint· is
11342 * ·absent· or default.
11343 */
11344 if ((bEffValue != NULL) &&
11345 (effFixed == 1)) {
11346 const xmlChar *rEffValue = NULL;
11347
11348 xmlSchemaGetEffectiveValueConstraint(base->attr, &effFixed,
11349 &rEffValue, 0);
11350 /*
11351 * 2.1.3.2 R's ·effective value constraint· is
11352 * fixed with the same string as B's.
11353 */
11354 if ((effFixed == 0) ||
11355 (! xmlStrEqual(rEffValue, bEffValue))) {
11356 xmlSchemaPAttrUseErr(ctxt,
11357 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
11358 NULL, type, NULL, cur->attr,
11359 "The effective value constraint of the "
11360 "attribute use is inconsistent with "
11361 "its correspondent of the base type",
11362 NULL);
11363 }
11364 }
11365 /*
11366 * TODO: derivation-ok-restriction 2.1.2 ({type definition} must be validly derived)
11367 */
11368 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000011369 * Override the attribute use.
11370 */
11371 base->attr = cur->attr;
11372 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011373
Daniel Veillard3646d642004-06-02 19:19:14 +000011374 break;
11375 }
11376 base = base->next;
11377 }
11378
11379 if (!found) {
11380 if (cur->attr->occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
11381 /*
11382 * derivation-ok-restriction 2.2
11383 */
11384 if ((type->attributeWildcard != NULL) &&
11385 xmlSchemaMatchesWildcardNs(type->attributeWildcard,
11386 cur->attr->targetNamespace))
11387 found = 1;
11388
11389 if (!found) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011390 xmlSchemaPAttrUseErr(ctxt,
11391 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
11392 NULL, type, NULL, cur->attr,
11393 "Neither a matching attribute use, "
11394 "nor a matching wildcard in the base type does exist",
11395 NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000011396 } else {
11397 /*
11398 * Add the attribute use.
11399 *
11400 * Note that this may lead to funny derivation error reports, if
11401 * multiple equal attribute uses exist; but this is not
11402 * allowed anyway, and it will be reported beforehand.
11403 */
11404 tmp = cur;
11405 if (prev != NULL)
11406 prev->next = cur->next;
11407 else
11408 uses = cur->next;
11409 cur = cur->next;
11410 if (type->attributeUses == NULL) {
11411 type->attributeUses = tmp;
11412 } else
11413 lastBaseUse->next = tmp;
11414 lastBaseUse = tmp;
11415
11416 continue;
11417 }
11418 }
11419 }
11420 prev = cur;
11421 cur = cur->next;
11422 }
11423 if (uses != NULL)
11424 xmlSchemaFreeAttributeUseList(uses);
11425 }
11426 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
11427 /*
11428 * The spec allows only appending, and not other kinds of extensions.
11429 *
11430 * This ensures: Schema Component Constraint: Derivation Valid (Extension) : 1.2
11431 */
11432 if (uses != NULL) {
11433 if (type->attributeUses == NULL) {
11434 type->attributeUses = uses;
11435 } else
11436 lastBaseUse->next = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000011437 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011438 } else {
11439 /*
Daniel Veillard50355f02004-06-08 17:52:16 +000011440 * Derive implicitely from the ur-type.
11441 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011442 type->attributeUses = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000011443 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011444 /*
11445 * 3.4.6 -> Complex Type Definition Properties Correct
11446 */
11447 if (type->attributeUses != NULL) {
11448 cur = type->attributeUses;
11449 prev = NULL;
11450 while (cur != NULL) {
11451 /*
11452 * 4. Two distinct attribute declarations in the {attribute uses} must
11453 * not have identical {name}s and {target namespace}s.
Daniel Veillard50355f02004-06-08 17:52:16 +000011454 *
Daniel Veillard3646d642004-06-02 19:19:14 +000011455 * Note that this was already done for "restriction" and types derived from
11456 * the ur-type.
Daniel Veillard50355f02004-06-08 17:52:16 +000011457 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011458 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
11459 tmp = cur->next;
11460 while (tmp != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011461 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
11462 xmlSchemaGetAttrName(tmp->attr))) &&
11463 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
11464 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011465
Daniel Veillardc0826a72004-08-10 14:17:33 +000011466 xmlSchemaPAttrUseErr(ctxt,
11467 XML_SCHEMAP_CT_PROPS_CORRECT_4,
11468 NULL, type, NULL, tmp->attr,
11469 "Duplicate attribute use specified", NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000011470 break;
11471 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011472 tmp = tmp->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000011473 }
11474 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011475 /*
11476 * 5. Two distinct attribute declarations in the {attribute uses} must
11477 * not have {type definition}s which are or are derived from ID.
11478 */
11479 if ((cur->attr->subtypes != NULL) &&
Daniel Veillard01fa6152004-06-29 17:04:39 +000011480 (xmlSchemaIsDerivedFromBuiltInType(ctxt, (xmlSchemaTypePtr) cur->attr, XML_SCHEMAS_ID))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011481 if (id != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011482 xmlSchemaPAttrUseErr(ctxt,
11483 XML_SCHEMAP_CT_PROPS_CORRECT_5,
11484 NULL, type, NULL, cur->attr,
11485 "There must not exist more than one attribute use, "
11486 "declared of type 'ID' or derived from it",
11487 NULL);
11488 FREE_AND_NULL(str)
Daniel Veillard50355f02004-06-08 17:52:16 +000011489 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011490 id = cur;
11491 }
11492 /*
11493 * Remove "prohibited" attribute uses. The reason this is done at this late
11494 * stage is to be able to catch dublicate attribute uses. So we had to keep
11495 * prohibited uses in the list as well.
11496 */
11497 if (cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
11498 tmp = cur;
11499 if (prev == NULL)
11500 type->attributeUses = cur->next;
11501 else
11502 prev->next = cur->next;
11503 cur = cur->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000011504 xmlFree(tmp);
Daniel Veillard3646d642004-06-02 19:19:14 +000011505 } else {
11506 prev = cur;
11507 cur = cur->next;
11508 }
11509 }
11510 }
11511 /*
11512 * TODO: This check should be removed if we are 100% sure of
11513 * the base type attribute uses already being built.
11514 */
11515 if ((baseType != NULL) && (!baseIsAnyType) &&
11516 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
11517 (baseType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011518 xmlSchemaPErr(ctxt, baseType->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011519 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011520 "attribute uses not builded on base type '%s'.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +000011521 baseType->name, NULL);
11522 }
11523 return (0);
11524}
11525
11526/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000011527 * xmlSchemaTypeFinalContains:
11528 * @schema: the schema
11529 * @type: the type definition
11530 * @final: the final
11531 *
11532 * Evaluates if a type definition contains the given "final".
11533 * This does take "finalDefault" into account as well.
11534 *
11535 * Returns 1 if the type does containt the given "final",
11536 * 0 otherwise.
11537 */
11538static int
11539xmlSchemaTypeFinalContains(xmlSchemaPtr schema, xmlSchemaTypePtr type, int final)
11540{
11541 int tfinal = final, tflags = type->flags;
11542
11543 if (type == NULL)
11544 return (0);
11545 if (type->flags & XML_SCHEMAS_TYPE_FINAL_DEFAULT) {
11546 switch (final) {
11547 case XML_SCHEMAS_TYPE_FINAL_RESTRICTION:
11548 tfinal = XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
11549 break;
11550 case XML_SCHEMAS_TYPE_FINAL_EXTENSION:
11551 tfinal = XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
11552 break;
11553 case XML_SCHEMAS_TYPE_FINAL_LIST:
11554 tfinal = XML_SCHEMAS_FINAL_DEFAULT_LIST;
11555 break;
11556 case XML_SCHEMAS_TYPE_FINAL_UNION:
11557 tfinal = XML_SCHEMAS_FINAL_DEFAULT_UNION;
11558 break;
11559 }
11560 tflags = schema->flags;
11561 }
11562 if (tflags & tfinal)
11563 return (1);
11564 else
11565 return (0);
11566
11567}
11568
11569/**
11570 * xmlSchemaGetUnionSimpleTypeMemberTypes:
11571 * @type: the Union Simple Type
11572 *
11573 * Returns a list of member types of @type if existing,
11574 * returns NULL otherwise.
11575 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011576static xmlSchemaTypeLinkPtr
Daniel Veillard01fa6152004-06-29 17:04:39 +000011577xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
11578{
11579 while (type != NULL) {
11580 if (type->memberTypes != NULL)
11581 return (type->memberTypes);
11582 else
11583 type = type->baseType;
11584 }
11585 return (NULL);
11586}
11587
11588/**
11589 * xmlSchemaGetListSimpleTypeItemType:
11590 * @type: the simple type definition
11591 *
11592 * Returns the item type definition of the list simple type.
11593 */
11594static xmlSchemaTypePtr
11595xmlSchemaGetListSimpleTypeItemType(xmlSchemaTypePtr type)
11596{
11597 if ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)
11598 return (NULL);
11599 /*
11600 * Note: In libxml2, the built-in types do not reflect
11601 * the datatype hierarchy (yet?) - we have to treat them
11602 * in a special way.
11603 */
11604 if (type->type == XML_SCHEMA_TYPE_BASIC)
11605 return (xmlSchemaGetBuiltInListSimpleTypeItemType(type));
11606 if (type->subtypes->type == XML_SCHEMA_TYPE_LIST)
11607 /* 1 If the <list> alternative is chosen, then the type
11608 * definition ·resolved· to by the ·actual value· of the
11609 * itemType [attribute] of <list>, if present, otherwise
11610 * the type definition corresponding to the <simpleType>
11611 * among the [children] of <list>.
11612 */
11613 return (type->subtypes->subtypes);
11614 else {
11615 /* 2 If the <restriction> option is chosen, then the
11616 * {item type definition} of the {base type definition}.
11617 */
11618 return (xmlSchemaGetListSimpleTypeItemType(type->baseType));
11619 }
11620}
11621
11622/**
11623 * xmlSchemaCheckCOSSTDerivedOK:
11624 * @type: the derived simple type definition
11625 * @baseType: the base type definition
11626 *
11627 * Checks wheter @type can be validly
11628 * derived from @baseType.
11629 *
11630 * Returns 0 on success, an positive error code otherwise.
11631 */
11632static int
11633xmlSchemaCheckCOSSTDerivedOK(xmlSchemaPtr schema,
11634 xmlSchemaTypePtr type,
11635 xmlSchemaTypePtr baseType,
11636 int subset)
11637{
11638 /*
11639 * Schema Component Constraint: Type Derivation OK (Simple)
11640 *
11641 *
11642 * 1 They are the same type definition.
11643 * TODO: The identy check might have to be more complex than this.
11644 */
11645 if (type == baseType)
11646 return (0);
11647 /*
11648 * 2.1 restriction is not in the subset, or in the {final}
11649 * of its own {base type definition};
11650 */
11651 if ((subset & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) ||
11652 (xmlSchemaTypeFinalContains(schema,
11653 type->baseType, XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
11654 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
11655 }
11656 /* 2.2 */
11657 if (type->baseType == baseType) {
11658 /*
11659 * 2.2.1 D's ·base type definition· is B.
11660 */
11661 return (0);
11662 }
11663 /*
11664 * 2.2.2 D's ·base type definition· is not the ·ur-type definition·
11665 * and is validly derived from B given the subset, as defined by this
11666 * constraint.
11667 */
11668 if ((type->baseType != xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE)) &&
11669 (xmlSchemaCheckCOSSTDerivedOK(schema, type->baseType, baseType, subset) == 0)) {
11670 return (0);
11671 }
11672 /*
11673 * 2.2.3 D's {variety} is list or union and B is the ·simple ur-type
11674 * definition·.
11675 */
11676 if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
11677 (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)) &&
11678 (baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE))) {
11679 return (0);
11680 }
11681 /*
11682 * 2.2.4 B's {variety} is union and D is validly derived from a type
11683 * definition in B's {member type definitions} given the subset, as
11684 * defined by this constraint.
11685 *
11686 * NOTE: This seems not to involve built-in types, since there is no
11687 * built-in Union Simple Type.
11688 */
11689 if (baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
11690 xmlSchemaTypeLinkPtr cur;
11691
11692 cur = baseType->memberTypes;
11693 while (cur != NULL) {
11694 if (xmlSchemaCheckCOSSTDerivedOK(schema, type,
11695 cur->type, subset) == 0)
11696 return (0);
11697 cur = cur->next;
11698 }
11699 }
11700
11701 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
11702}
11703
11704
11705/**
11706 * xmlSchemaCheckSTPropsCorrect:
11707 * @ctxt: the schema parser context
11708 * @type: the simple type definition
11709 *
11710 * Checks st-props-correct.
11711 *
11712 * Returns 0 if the properties are correct,
11713 * if not, a positive error code and -1 on internal
11714 * errors.
11715 */
11716static int
11717xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
11718 xmlSchemaTypePtr type)
11719{
11720 xmlSchemaTypePtr baseType = type->baseType, anySimpleType,
11721 anyType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011722 xmlChar *str = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011723
Daniel Veillardc0826a72004-08-10 14:17:33 +000011724 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011725 /*
11726 * Schema Component Constraint: Simple Type Definition Properties Correct
11727 *
11728 * NOTE: This is somehow redundant, since we actually built a simple type
11729 * to have all the needed information; this acts as an self test.
11730 */
11731 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
11732 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
11733 /*
11734 * TODO: 1 The values of the properties of a simple type definition must be as
11735 * described in the property tableau in Datatype definition, modulo the
11736 * impact of Missing Sub-components (§5.3).
11737 */
11738 /* Base type: If the datatype has been ·derived· by ·restriction·
11739 * then the Simple Type Definition component from which it is ·derived·,
11740 * otherwise the Simple Type Definition for anySimpleType (§4.1.6).
11741 */
11742 if (baseType == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011743 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011744 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011745 NULL, type, NULL,
11746 "No base type existent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011747 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
11748 }
11749 if ((baseType->type != XML_SCHEMA_TYPE_SIMPLE) &&
11750 ((baseType->type != XML_SCHEMA_TYPE_BASIC) ||
11751 (baseType == anyType))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011752 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011753 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011754 NULL, type, NULL,
11755 "The base type %s is not a simple type",
11756 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11757 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011758 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
11759 }
11760 if ((baseType != anySimpleType) &&
11761 (type->subtypes->type != XML_SCHEMA_TYPE_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011762 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011763 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011764 NULL, type, NULL,
11765 "A type, derived by list or union, must have"
11766 "the simple ur-type definition as base type, not %s",
11767 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11768 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011769 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
11770 }
11771 /*
11772 * Variety: One of {atomic, list, union}.
11773 */
11774 if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
11775 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) &&
11776 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011777 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011778 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011779 NULL, type, NULL,
11780 "The variety is absent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011781 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
11782 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000011783 /* TODO: Finish this. Hmm, is this finished? */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011784
11785 /*
11786 * 2 All simple type definitions must be derived ultimately from the ·simple
11787 * ur-type definition (so· circular definitions are disallowed). That is, it
11788 * must be possible to reach a built-in primitive datatype or the ·simple
11789 * ur-type definition· by repeatedly following the {base type definition}.
11790 */
11791 baseType = type->baseType;
11792 while ((baseType != NULL) && (baseType->type != XML_SCHEMA_TYPE_BASIC)) {
11793 if (baseType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
11794 xmlSchemaTypeFixup(baseType, ctxt, NULL);
11795 if (baseType == anySimpleType)
11796 break;
11797 else if (baseType == type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011798 xmlSchemaPCustomErr(ctxt,
11799 XML_SCHEMAP_ST_PROPS_CORRECT_2,
11800 NULL, type, NULL,
11801 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011802 return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
11803 }
11804 baseType = baseType->baseType;
11805 }
11806 /*
11807 * 3 The {final} of the {base type definition} must not contain restriction.
11808 */
11809 if (xmlSchemaTypeFinalContains(ctxt->schema, baseType,
11810 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011811 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011812 XML_SCHEMAP_ST_PROPS_CORRECT_3,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011813 NULL, type, NULL,
11814 "The 'final' of its base type %s must not contain "
11815 "'restriction'",
11816 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11817 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011818 return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
11819 }
11820 return (0);
11821}
11822
11823/**
11824 * xmlSchemaCheckDerivationValidSimpleRestriction:
11825 * @ctxt: the schema parser context
11826 * @type: the simple type definition
11827 *
11828 * Checks if the given @type (simpleType) is derived
11829 * validly by restriction.
11830 *
11831 * Returns -1 on internal errors, 0 if the type is validly derived,
11832 * a positive error code otherwise.
11833 */
11834static int
11835xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011836 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011837{
Daniel Veillardc0826a72004-08-10 14:17:33 +000011838 xmlChar *str = NULL;
11839
11840 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011841
11842 if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
11843 xmlSchemaPErr(ctxt, type->node,
11844 XML_ERR_INTERNAL_ERROR,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011845 "xmlSchemaCheckDerivationValidSimpleRestriction: The given "
11846 "type '%s' is not a user-derived simpleType.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011847 type->name, NULL);
11848 return (-1);
11849 }
11850
11851 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
11852 xmlSchemaTypePtr primitive;
11853 /*
11854 * 1.1 The {base type definition} must be an atomic simple
11855 * type definition or a built-in primitive datatype.
11856 */
11857 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011858 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011859 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011860 NULL, type, NULL,
11861 "The base type %s is not an atomic simple type",
11862 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
11863 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011864 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
11865 }
11866 /* 1.2 The {final} of the {base type definition} must not contain
11867 * restriction.
11868 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011869 /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011870 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
11871 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011872 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011873 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011874 NULL, type, NULL,
11875 "The final of its base type %s must not contain 'restriction'",
11876 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
11877 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011878 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
11879 }
11880
11881 /*
11882 * 1.3.1 DF must be an allowed constraining facet for the {primitive
11883 * type definition}, as specified in the appropriate subsection of 3.2
11884 * Primitive datatypes.
11885 */
11886 if (type->facets != NULL) {
11887 xmlSchemaFacetPtr facet;
11888 int ok = 1;
11889
11890 primitive = xmlSchemaGetPrimitiveType(type);
11891 if (primitive == NULL) {
11892 xmlSchemaPErr(ctxt, type->node,
11893 XML_ERR_INTERNAL_ERROR,
11894 "xmlSchemaCheckDerivationValidSimpleRestriction: failed "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011895 "to get primitive type of type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011896 type->name, NULL);
11897 return (-1);
11898 }
11899 facet = type->facets;
11900 do {
11901 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011902 ok = 0;
11903 xmlSchemaPIllegalFacetAtomicErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011904 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011905 NULL, type, primitive, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011906 }
11907 facet = facet->next;
11908 } while (facet != NULL);
11909 if (ok == 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +000011910 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011911 }
11912 /*
11913 * TODO: 1.3.2 (facet derivation)
11914 */
11915 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
11916 xmlSchemaTypePtr itemType = NULL;
11917
11918 itemType = xmlSchemaGetListSimpleTypeItemType(type);
11919 if (itemType == NULL) {
11920 xmlSchemaPErr(ctxt, type->node,
11921 XML_ERR_INTERNAL_ERROR,
11922 "Internal error: xmlSchemaCheckDerivationValidSimpleRestriction: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011923 "failed to evaluate the item type of type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011924 type->name, NULL);
11925 return (-1);
11926 }
11927 /*
11928 * 2.1 The {item type definition} must have a {variety} of atomic or
11929 * union (in which case all the {member type definitions}
11930 * must be atomic).
11931 */
11932 if (((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
11933 ((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011934 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011935 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011936 NULL, type, NULL,
11937 "The item type %s must have a variety of atomic or union",
11938 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1));
11939 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011940 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
11941 } else if (itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
11942 xmlSchemaTypeLinkPtr member;
11943
11944 member = itemType->memberTypes;
11945 while (member != NULL) {
11946 if ((member->type->flags &
11947 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011948 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011949 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011950 NULL, type, NULL,
11951 "The item type is a union type, but the "
11952 "member type %s of this item type is not atomic",
11953 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
11954 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011955 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
11956 }
11957 member = member->next;
11958 }
11959 }
11960
11961 if (type->baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE)) {
11962 xmlSchemaFacetPtr facet;
11963 /*
11964 * This is the case if we have: <simpleType><list ..
11965 */
11966 /*
11967 * 2.3.1
11968 * 2.3.1.1 The {final} of the {item type definition} must not
11969 * contain list.
11970 */
11971 if (xmlSchemaTypeFinalContains(ctxt->schema,
11972 itemType, XML_SCHEMAS_TYPE_FINAL_LIST)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011973 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011974 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011975 NULL, type, NULL,
11976 "The final of its item type %s must not contain 'list'",
11977 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1));
11978 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011979 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
11980 }
11981 /*
11982 * 2.3.1.2 The {facets} must only contain the whiteSpace
11983 * facet component.
11984 */
11985 if (type->facets != NULL) {
11986 facet = type->facets;
11987 do {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011988 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
11989 xmlSchemaPIllegalFacetListUnionErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011990 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011991 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011992 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
11993 }
11994 facet = facet->next;
11995 } while (facet != NULL);
11996 }
11997 /*
11998 * TODO: Datatypes states:
11999 * A ·list· datatype can be ·derived· from an ·atomic· datatype
12000 * whose ·lexical space· allows space (such as string or anyURI)or
12001 * a ·union· datatype any of whose {member type definitions}'s
12002 * ·lexical space· allows space.
12003 */
12004 } else {
12005 /*
12006 * This is the case if we have: <simpleType><restriction ...
12007 */
12008 /*
12009 * 2.3.2
12010 * 2.3.2.1 The {base type definition} must have a {variety} of list.
12011 */
12012 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012013 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012014 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012015 NULL, type, NULL,
12016 "The base type %s must be a list type",
12017 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
12018 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012019 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
12020 }
12021 /*
12022 * 2.3.2.2 The {final} of the {base type definition} must not
12023 * contain restriction.
12024 */
12025 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
12026 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012027 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012028 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012029 NULL, type, NULL,
12030 "The final of the base type %s must not contain 'restriction'",
12031 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
12032 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012033 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
12034 }
12035 /*
12036 * 2.3.2.3 The {item type definition} must be validly derived
12037 * from the {base type definition}'s {item type definition} given
12038 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6).
12039 */
12040 {
12041 xmlSchemaTypePtr baseItemType;
12042
12043 baseItemType = xmlSchemaGetListSimpleTypeItemType(type->baseType);
12044 if (baseItemType == NULL) {
12045 xmlSchemaPErr(ctxt, type->node,
12046 XML_ERR_INTERNAL_ERROR,
12047 "xmlSchemaCheckDerivationValidSimpleRestriction: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012048 "List simple type '%s': Failed to "
12049 "evaluate the item type of its base type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012050 type->name, type->baseType->name);
12051 return (-1);
12052 }
12053 if ((itemType != baseItemType) &&
12054 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema, itemType,
12055 baseItemType, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012056 xmlChar *strBIT = NULL, *strBT = NULL;
12057 xmlSchemaPCustomErrExt(ctxt,
12058 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
12059 NULL, type, NULL,
12060 "The item type %s is not validly derived from the "
12061 "item type %s of the base type %s",
12062 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1),
12063 xmlSchemaFormatItemForReport(&strBIT, NULL, baseItemType, NULL, 1),
12064 xmlSchemaFormatItemForReport(&strBT, NULL, type->baseType, NULL, 1));
12065
12066 FREE_AND_NULL(str)
12067 FREE_AND_NULL(strBIT)
12068 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012069 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
12070 }
12071 }
12072
12073 if (type->facets != NULL) {
12074 xmlSchemaFacetPtr facet;
12075 int ok = 1;
12076 /*
12077 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
12078 * and enumeration facet components are allowed among the {facets}.
12079 */
12080 facet = type->facets;
12081 do {
12082 switch (facet->type) {
12083 case XML_SCHEMA_FACET_LENGTH:
12084 case XML_SCHEMA_FACET_MINLENGTH:
12085 case XML_SCHEMA_FACET_MAXLENGTH:
12086 case XML_SCHEMA_FACET_WHITESPACE:
12087 /*
12088 * TODO: 2.5.1.2 List datatypes
12089 * The value of ·whiteSpace· is fixed to the value collapse.
12090 */
12091 case XML_SCHEMA_FACET_PATTERN:
12092 case XML_SCHEMA_FACET_ENUMERATION:
12093 break;
12094 default: {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012095 xmlSchemaPIllegalFacetListUnionErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012096 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012097 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012098 /*
12099 * We could return, but it's nicer to report all
12100 * invalid facets.
12101 */
12102 ok = 0;
12103 }
12104 }
12105 facet = facet->next;
12106 } while (facet != NULL);
12107 if (ok == 0)
12108 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
12109 /*
12110 * TODO: 2.3.2.5 For each facet in the {facets} (call this DF), if there
12111 * is a facet of the same kind in the {facets} of the {base type
12112 * definition} (call this BF),then the DF's {value} must be a valid
12113 * restriction of BF's {value} as defined in [XML Schemas: Datatypes].
12114 */
12115 }
12116
12117
12118 }
12119 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
12120 /*
12121 * 3.1 The {member type definitions} must all have {variety} of
12122 * atomic or list.
12123 */
12124 xmlSchemaTypeLinkPtr member;
12125
12126 member = type->memberTypes;
12127 while (member != NULL) {
12128 if (((member->type->flags &
12129 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
12130 ((member->type->flags &
12131 XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012132 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012133 XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012134 NULL, type, NULL,
12135 "The member type %s is neither an atomic, nor a list type",
12136 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
12137 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012138 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
12139 }
12140 member = member->next;
12141 }
12142 /*
12143 * 3.3.1 If the {base type definition} is the ·simple ur-type
12144 * definition·
12145 */
12146 if (type->baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE)) {
12147 /*
12148 * 3.3.1.1 All of the {member type definitions} must have a
12149 * {final} which does not contain union.
12150 */
12151 member = type->memberTypes;
12152 while (member != NULL) {
12153 if (xmlSchemaTypeFinalContains(ctxt->schema, member->type,
12154 XML_SCHEMAS_TYPE_FINAL_UNION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012155 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012156 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012157 NULL, type, NULL,
12158 "The final of member type %s contains 'union'",
12159 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
12160 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012161 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
12162 }
12163 member = member->next;
12164 }
12165 /*
12166 * 3.3.1.2 The {facets} must be empty.
12167 */
12168 if (type->facetSet != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012169 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012170 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012171 NULL, type, NULL,
12172 "No facets allowed", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012173 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
12174 }
12175 } else {
12176 /*
12177 * 3.3.2.1 The {base type definition} must have a {variety} of union.
12178 */
12179 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012180 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012181 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012182 NULL, type, NULL,
12183 "The base type %s is not a union type",
12184 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
12185 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012186 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
12187 }
12188 /*
12189 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
12190 */
12191 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
12192 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012193 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012194 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012195 NULL, type, NULL,
12196 "The final of its base type %s must not contain 'restriction'",
12197 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
12198 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012199 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
12200 }
12201 /*
12202 * 3.3.2.3 The {member type definitions}, in order, must be validly
12203 * derived from the corresponding type definitions in the {base
12204 * type definition}'s {member type definitions} given the empty set,
12205 * as defined in Type Derivation OK (Simple) (§3.14.6).
12206 */
12207 {
12208 xmlSchemaTypeLinkPtr baseMember;
12209
12210 /*
12211 * OPTIMIZE: if the type is restricting, it has no local defined
12212 * member types and inherits the member types of the base type;
12213 * thus a check for equality can be skipped.
12214 */
12215 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000012216 * Even worse: I cannot see a scenario where a restricting
Daniel Veillard01fa6152004-06-29 17:04:39 +000012217 * union simple type can have other member types as the member
12218 * types of it's base type. This check seems not necessary with
12219 * respect to the derivation process in libxml2.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000012220 * But necessary if constructing types with an API.
Daniel Veillard01fa6152004-06-29 17:04:39 +000012221 */
12222 if (type->memberTypes != NULL) {
12223 member = type->memberTypes;
12224 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
12225 if ((member == NULL) && (baseMember != NULL)) {
12226 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012227 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012228 "Internal error: "
12229 "xmlSchemaCheckDerivationValidSimpleRestriction "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012230 "(3.3.2.3), union simple type '%s', unequal number "
Daniel Veillard01fa6152004-06-29 17:04:39 +000012231 "of member types in the base type\n",
12232 type->name, NULL);
12233 }
12234 while (member != NULL) {
12235 if (baseMember == NULL) {
12236 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012237 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012238 "Internal error: "
12239 "xmlSchemaCheckDerivationValidSimpleRestriction "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012240 "(3.3.2.3), union simple type '%s', unequal number "
12241 "of member types in the base type.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012242 type->name, NULL);
12243 }
12244 if ((member->type != baseMember->type) &&
12245 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema,
12246 member->type, baseMember->type, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012247 xmlChar *strBMT = NULL, *strBT = NULL;
12248
12249 xmlSchemaPCustomErrExt(ctxt,
12250 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
12251 NULL, type, NULL,
12252 "The member type %s is not validly derived from its "
12253 "corresponding member type %s of the base type %s",
12254 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1),
12255 xmlSchemaFormatItemForReport(&strBMT, NULL, baseMember->type, NULL, 1),
12256 xmlSchemaFormatItemForReport(&strBT, NULL, type->baseType, NULL, 1));
12257 FREE_AND_NULL(str)
12258 FREE_AND_NULL(strBMT)
12259 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012260 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
12261 }
12262 member = member->next;
12263 baseMember = baseMember->next;
12264 }
12265 }
12266 }
12267 /*
12268 * 3.3.2.4 Only pattern and enumeration facet components are
12269 * allowed among the {facets}.
12270 */
12271 if (type->facets != NULL) {
12272 xmlSchemaFacetPtr facet;
12273 int ok = 1;
12274
12275 facet = type->facets;
12276 do {
12277 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
12278 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012279 xmlSchemaPIllegalFacetListUnionErr(ctxt,
12280 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
12281 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012282 ok = 0;
12283 }
12284 facet = facet->next;
12285 } while (facet != NULL);
12286 if (ok == 0)
12287 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
12288
12289 }
12290 /*
12291 * TODO: 3.3.2.5 (facet derivation)
12292 */
12293 }
12294 }
12295
12296 return (0);
12297}
12298
12299/**
12300 * xmlSchemaCheckSRCSimpleType:
12301 * @ctxt: the schema parser context
12302 * @type: the simple type definition
12303 *
12304 * Checks crc-simple-type constraints.
12305 *
12306 * Returns 0 if the constraints are satisfied,
12307 * if not a positive error code and -1 on internal
12308 * errors.
12309 */
12310static int
12311xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
12312 xmlSchemaTypePtr type)
12313{
12314 /*
12315 * NOTE: src-simple-type 2-4 are redundant, since the checks
12316 * were are done for the corresponding <restriction>, <list> and <union>
12317 * elements, but W3C wants a <simpleType> error as well, so it gets one.
12318 * Maby this can be skipped in the future, if we get sure it's not needed.
12319 */
12320 if (type->subtypes == NULL) {
12321 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012322 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012323 "Internal error: xmlSchemaCheckSRCSimpleType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012324 "no subtype on simple type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012325 type->name, NULL);
12326 return (-1);
12327 }
12328 /*
12329 * src-simple-type.1 The corresponding simple type definition, if any,
12330 * must satisfy the conditions set out in Constraints on Simple Type
12331 * Definition Schema Components (§3.14.6).
12332 */
12333 if ((xmlSchemaCheckSTPropsCorrect(ctxt, type) != 0) ||
12334 (xmlSchemaCheckCOSSTRestricts(ctxt, type) != 0)) {
12335 /*
12336 * TODO: Removed this, since it got annoying to get an
12337 * extra error report, if anything failed until now.
12338 * Enable this if needed.
12339 */
12340 /*
12341 xmlSchemaPErr(ctxt, type->node,
12342 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012343 "Simple type '%s' does not satisfy the constraints "
Daniel Veillard01fa6152004-06-29 17:04:39 +000012344 "on simple type definitions.\n",
12345 type->name, NULL);
12346 */
12347 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_1);
12348 }
12349
12350 if (type->subtypes->type == XML_SCHEMA_TYPE_RESTRICTION) {
12351 /*
12352 * src-simple-type.2 If the <restriction> alternative is chosen,
12353 * either it must have a base [attribute] or a <simpleType> among its
12354 * [children], but not both.
12355 */
William M. Brack2f2a6632004-08-20 23:09:47 +000012356 /*
12357 * XML_SCHEMAP_SRC_SIMPLE_TYPE_2
12358 * NOTE: This was removed, since this will be already handled
12359 * in the parse function for <restriction>.
12360 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012361 } else if (type->subtypes->type == XML_SCHEMA_TYPE_LIST) {
12362 /* src-simple-type.3 If the <list> alternative is chosen, either it must have
12363 * an itemType [attribute] or a <simpleType> among its [children],
12364 * but not both.
12365 * NOTE: baseType is set to the local simple type definiton,
12366 * if existent, at parse time. This is a hack and not nice.
12367 */
William M. Brack2f2a6632004-08-20 23:09:47 +000012368 /*
12369 * TODO: Remove this, and add the check to the parse function of <list>.
12370 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012371 if (((type->subtypes->base == NULL) &&
12372 (type->baseType == NULL)) ||
12373 ((type->subtypes->base != NULL) &&
12374 (type->subtypes->baseType != NULL))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012375 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012376 XML_SCHEMAP_SRC_SIMPLE_TYPE_3,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012377 NULL, type, NULL,
12378 "Either the attribute 'itemType' or the <simpleType> child "
12379 "must be present on the <list> child ", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012380 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_3);
12381 }
12382
12383
12384 } else if (type->subtypes->type == XML_SCHEMA_TYPE_UNION) {
12385 xmlSchemaTypeLinkPtr member;
12386 xmlSchemaTypePtr ancestor, anySimpleType;
12387
12388 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
12389
12390 /* src-simple-type.4 Circular union type definition is disallowed. That is, if
12391 * the <union> alternative is chosen, there must not be any entries
12392 * in the memberTypes [attribute] at any depth which resolve to the
12393 * component corresponding to the <simpleType>.
12394 */
12395 member = type->memberTypes;
12396 while (member != NULL) {
12397 ancestor = member->type;
12398 while ((ancestor != NULL) && (ancestor->type != XML_SCHEMA_TYPE_BASIC)) {
12399 if (ancestor->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
12400 xmlSchemaTypeFixup(ancestor, ctxt, NULL);
12401 if (ancestor == anySimpleType)
12402 break;
12403 else if (ancestor == type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012404 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012405 XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012406 NULL, type, NULL,
12407 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012408 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
12409 } else if (ancestor->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
12410 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000012411 * TODO, FIXME: Although a list simple type must not have a union ST
Daniel Veillard01fa6152004-06-29 17:04:39 +000012412 * type as item type, which in turn has a list ST as member
12413 * type, we will assume this here as well, since this check
12414 * was not yet performed.
12415 */
12416
12417 }
12418 ancestor = ancestor->baseType;
12419 }
12420 member = member->next;
12421 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012422 }
12423
12424 return (0);
12425}
12426
William M. Brack2f2a6632004-08-20 23:09:47 +000012427#if 0 /* Not yet used code for CT schema validation */
12428static int
12429xmlSchemaCheckCVCSimpleType(xmlSchemaValidCtxtPtr ctxt,
12430 const xmlChar * value,
12431 xmlSchemaTypePtr type,
12432 int fireErrors)
12433{
12434 int ret;
12435 /*
12436 * 3.14.4 Simple Type Definition Validation Rules
12437 * Validation Rule: String Valid
12438 */
12439 /*
12440 * 1 It is schema-valid with respect to that definition as defined
12441 * by Datatype Valid in [XML Schemas: Datatypes].
12442 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012443 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type, value,
12444 fireErrors, 1, 1, 1);
William M. Brack2f2a6632004-08-20 23:09:47 +000012445 return (ret);
12446 /*
12447 * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
12448 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6), then
12449 * the string must be a ·declared entity name·.
12450 */
12451 /*
12452 * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
12453 * given the empty set, as defined in Type Derivation OK (Simple) (§3.14.6),
12454 * then every whitespace-delimited substring of the string must be a ·declared
12455 * entity name·.
12456 */
12457 /*
12458 * 2.3 otherwise no further condition applies.
12459 */
12460
12461 return (0);
12462}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012463#endif
12464
William M. Brack2f2a6632004-08-20 23:09:47 +000012465
12466static int
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012467xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
12468{
12469 if (vctxt->pctxt == NULL) {
12470 vctxt->pctxt =xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
12471 /* vctxt->pctxt = xmlSchemaNewParserCtxt("*"); */
12472 if (vctxt->pctxt == NULL) {
12473 xmlSchemaVErr(vctxt, NULL,
12474 XML_SCHEMAV_INTERNAL,
12475 "Internal error: xmlSchemaCreatePCtxtOnVCtxt, "
12476 "failed to create a temp. parser context.\n",
William M. Brack2f2a6632004-08-20 23:09:47 +000012477 NULL, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012478 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012479 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012480 /* TODO: Pass user data. */
12481 xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error, vctxt->warning, NULL);
12482 }
12483 return (0);
12484}
12485
12486static int
12487xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
12488{
12489 if (ctxt->vctxt == NULL) {
12490 ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
12491 if (ctxt->vctxt == NULL) {
12492 xmlSchemaPErr(ctxt, NULL,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012493 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012494 "Internal error: xmlSchemaCreatePCtxtOnVCtxt, "
12495 "failed to create a temp. validation context.\n",
12496 NULL, NULL);
12497 return (-1);
12498 }
12499 /* TODO: Pass user data. */
12500 xmlSchemaSetValidErrors(ctxt->vctxt, ctxt->error, ctxt->warning, NULL);
12501 }
12502 return (0);
12503}
12504
12505/**
12506 * xmlSchemaCheckCOSValidDefault:
12507 * @ctxt: the schema parser context
12508 * @type: the simple type definition
12509 * @value: the default value
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000012510 * @val: the precomputed value to be returned
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012511 * @node: an optional node (the holder of the value)
12512 *
12513 * Checks the "cos-valid-default" constraints.
12514 *
12515 * Returns 0 if the constraints are satisfied,
12516 * if not, a positive error code and -1 on internal
12517 * errors.
12518 */
12519static int
12520xmlSchemaCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
12521 xmlSchemaValidCtxtPtr vctxt,
12522 xmlSchemaTypePtr type,
12523 const xmlChar *value,
12524 xmlNodePtr node)
12525{
12526 int ret = 0;
12527
12528 /*
12529 * cos-valid-default:
12530 * Schema Component Constraint: Element Default Valid (Immediate)
12531 * For a string to be a valid default with respect to a type
12532 * definition the appropriate case among the following must be true:
12533 */
12534 /*
12535 * NOTE: This has to work without a given node (the holder of the
12536 * value), since it should work on the component, i.e. an underlying
12537 * DOM must not be mandatory.
12538 */
12539 if ((pctxt == NULL) || (vctxt == NULL)) {
12540 xmlSchemaPErr(pctxt, node,
12541 XML_SCHEMAP_INTERNAL,
12542 "Internal error: xmlSchemaCheckCOSValidDefault, "
12543 "bad arguments: the parser and/or validation context is "
12544 "missing.\n",
12545 NULL, NULL);
12546 return (-1);
12547 }
12548 if IS_COMPLEX_TYPE(type) {
William M. Brack2f2a6632004-08-20 23:09:47 +000012549 /*
12550 * Complex type.
12551 *
12552 * 2.1 its {content type} must be a simple type definition or mixed.
12553 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012554 /*
12555 * TODO: Adjust this when the content type will be computed
12556 * correctly.
12557 */
12558 if ((type->contentType != XML_SCHEMA_CONTENT_SIMPLE) &&
12559 (type->contentType != XML_SCHEMA_CONTENT_BASIC) &&
12560 (type->contentType != XML_SCHEMA_CONTENT_MIXED)) {
12561 xmlSchemaPSimpleTypeErr(pctxt,
12562 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
12563 NULL, NULL, node,
12564 type, NULL, NULL,
12565 "If the type of a constraint value is complex, its content "
12566 "type must be mixed or a simple type",
12567 NULL, NULL);
12568 return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
12569 }
12570 if (type->contentType == XML_SCHEMA_CONTENT_MIXED) {
William M. Brack2f2a6632004-08-20 23:09:47 +000012571 /*
12572 * 2.2.2 If the {content type} is mixed, then the {content type}'s
12573 * particle must be ·emptiable· as defined by Particle Emptiable
12574 * (§3.9.6).
12575 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012576
William M. Brack2f2a6632004-08-20 23:09:47 +000012577 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012578 * URGENT TODO: Implement this.
William M. Brack2f2a6632004-08-20 23:09:47 +000012579 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012580 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000012581 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012582 }
12583 /*
12584 * 1 If the type definition is a simple type definition, then the string
12585 * must be ·valid· with respect to that definition as defined by String
12586 * Valid (§3.14.4).
12587 *
12588 * AND
12589 *
12590 * 2.2.1 If the {content type} is a simple type definition, then the
12591 * string must be ·valid· with respect to that simple type definition
12592 * as defined by String Valid (§3.14.4).
12593 */
12594 vctxt->node = node;
12595 vctxt->cur = NULL;
12596 ret = xmlSchemaValidateSimpleTypeValue(vctxt, type, value, 1, 1, 1, 0);
12597 /* ret = xmlSchemaCheckCVCSimpleType(vctxt, elemDecl->value, typeDef, 0); */
12598 if (ret < 0) {
12599 xmlSchemaPErr(pctxt, node,
12600 /* NOTNICE: error code: This function will be used during
12601 * schema construction and xsi:type validation.
12602 */
12603 XML_SCHEMAP_INTERNAL,
12604 "Internal error: xmlSchemaCheckCOSValidDefault, "
12605 "while validating a value constaint value.\n",
12606 NULL, NULL);
12607
12608 }
12609 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +000012610}
12611
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012612#if 0 /* Not yet used code for CT schema validation */
William M. Brack2f2a6632004-08-20 23:09:47 +000012613/**
12614 * xmlSchemaGetSTContentOfCT:
12615 * @ctxt: the schema parser context
12616 * @type: the complex type definition
12617 *
12618 *
12619 * Returns the corresponding simple type for the content of
12620 * the complex type.
12621 */
12622static xmlSchemaTypePtr
12623xmlSchemaGetSTContentOfCT(xmlSchemaParserCtxtPtr ctxt,
12624 xmlSchemaTypePtr type)
12625{
12626 xmlSchemaTypePtr orig = type, anyType;
12627
12628 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
12629 while ((type != NULL) && (type != anyType) &&
12630 (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
12631 if (type->type == XML_SCHEMA_TYPE_SIMPLE)
12632 return(type);
12633 type = type->baseType;
12634 }
12635 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012636 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000012637 NULL, orig, NULL,
12638 "Internal error: xmlSchemaGetSTContentTypeOfCT, "
12639 "no simple type for the content of complex type '%s' could be "
12640 "computed", orig->name);
12641 return (NULL);
12642}
12643
12644
William M. Brack2f2a6632004-08-20 23:09:47 +000012645
William M. Brack2f2a6632004-08-20 23:09:47 +000012646
12647/**
12648 * xmlSchemaCheckCOSCTExtends:
12649 * @ctxt: the schema parser context
12650 * @type: the complex type definition
12651 *
12652 * Schema Component Constraint: Derivation Valid (Extension)
12653 *
12654 * Returns 0 if the constraints are satisfied, a positive
12655 * error code if not and -1 if an internal error occured.
12656 */
12657static int
12658xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
12659 xmlSchemaTypePtr type)
12660{
12661 xmlSchemaTypePtr base;
12662 /*
12663 * 1 If the {base type definition} is a complex type definition,
12664 * then all of the following must be true:
12665 */
12666 base = type->baseType;
12667 if (base == NULL) {
12668 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012669 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000012670 NULL, type, NULL,
12671 "Internal error: xmlSchemaCheckCOSCTExtends, "
12672 "the complex type '%s' has no base type", type->name);
12673 return (-1);
12674 }
12675 if (base->type == XML_SCHEMA_TYPE_COMPLEX) {
12676 /*
12677 * 1.1 The {final} of the {base type definition} must not
12678 * contain extension.
12679 */
12680 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
12681 xmlSchemaPCustomErr(ctxt,
12682 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
12683 NULL, type, NULL,
12684 "The 'final' of the base type definition "
12685 "contains extension", NULL);
12686 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
12687 }
12688 /*
12689 * 1.2 Its {attribute uses} must be a subset of the {attribute uses}
12690 * of the complex type definition itself, that is, for every attribute
12691 * use in the {attribute uses} of the {base type definition}, there
12692 * must be an attribute use in the {attribute uses} of the complex
12693 * type definition itself whose {attribute declaration} has the same
12694 * {name}, {target namespace} and {type definition} as its attribute
12695 * declaration
12696 *
12697 * NOTE: This will be already satisfied by the way the attribute uses
12698 * are extended in xmlSchemaBuildAttributeValidation; thus this check
12699 * is not needed.
12700 */
12701
12702 /*
12703 * 1.3 If it has an {attribute wildcard}, the complex type definition
12704 * must also have one, and the base type definition's {attribute
12705 * wildcard}'s {namespace constraint} must be a subset of the complex
12706 * type definition's {attribute wildcard}'s {namespace constraint},
12707 * as defined by Wildcard Subset (§3.10.6).
12708 *
12709 * This is already checked in xmlSchemaBuildAttributeValidation; thus
12710 * this check is not needed.
12711 */
12712
12713 /*
12714 * 1.4 One of the following must be true:
12715 *
12716 * 1.4.1 The {content type} of the {base type definition} and the
12717 * {content type} of the complex type definition itself must be the same
12718 * simple type definition
12719 */
12720
12721
12722
12723 } else {
12724 /*
12725 * 2 If the {base type definition} is a simple type definition,
12726 * then all of the following must be true:
12727 */
12728 /*
12729 * 2.1 The {content type} must be the same simple type definition.
12730 */
12731 /*
12732 * 2.2 The {final} of the {base type definition} must not contain
12733 * extension
12734 */
12735 }
12736
12737}
12738
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012739static int
12740xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
12741 xmlSchemaTypePtr type)
12742{
12743 xmlSchemaTypePtr base, content;
12744 int OK = 0;
12745
12746 /*
12747 * TODO: Adjust the error codes here, as I used
12748 * XML_SCHEMAP_SRC_CT_1 only yet.
12749 */
12750 /*
12751 * Schema Representation Constraint:
12752 * Complex Type Definition Representation OK
12753 */
12754 base = type->baseType;
12755 if (base == NULL) {
12756 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL, NULL, type, NULL,
12757 "Internal error: xmlSchemaCheckSRCCT, '%s', no base type",
12758 type->name);
12759 return (-1);
12760 }
12761
12762 if (type->subtypes != NULL) {
12763 if (type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
12764 if IS_COMPLEX_TYPE(base) {
12765 /*
12766 * 1 If the <complexContent> alternative is chosen, the type definition
12767 * ·resolved· to by the ·actual value· of the base [attribute]
12768 * must be a complex type definition;
12769 */
12770 xmlSchemaPCustomErr(ctxt,
12771 XML_SCHEMAP_SRC_CT_1,
12772 NULL, type, NULL,
12773 "The base type is not a complex type", NULL);
12774 return (XML_SCHEMAP_SRC_CT_1);
12775 }
12776 } else if (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
12777
12778 if IS_SIMPLE_TYPE(base) {
12779 if (type->flags &
12780 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
12781 /*
12782 * 2.1.3 only if the <extension> alternative is also
12783 * chosen, a simple type definition.
12784 */
12785 /* TODO: Change error code to ..._SRC_CT_2_1_3. */
12786 xmlSchemaPCustomErr(ctxt,
12787 XML_SCHEMAP_SRC_CT_1,
12788 NULL, type, NULL,
12789 "A complex type (simple content) cannot restrict "
12790 "an other simple type",
12791 NULL);
12792 return (XML_SCHEMAP_SRC_CT_1);
12793 }
12794 OK = 1;
12795
12796 } else { /* if IS_SIMPLE_TYPE(base) */
12797 if (base->contentType = XML_SCHEMA_CONTENT_MIXED) {
12798 /*
12799 * 2.1.2 only if the <restriction> alternative is also
12800 * chosen, a complex type definition whose {content type}
12801 * is mixed and a particle emptyable.
12802 */
12803 /*
12804 * FIXME TODO: Check for *empiable particle* is missing.
12805 */
12806 if ((type->flags &
12807 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) == 0) {
12808 xmlSchemaPCustomErr(ctxt,
12809 XML_SCHEMAP_SRC_CT_1,
12810 NULL, type, NULL,
12811 "A complex type (simple content) cannot "
12812 "extend an other complex type which has a "
12813 "content type of: 'mixed' and emptiable particle",
12814 NULL);
12815 return (XML_SCHEMAP_SRC_CT_1);
12816 }
12817 /*
12818 * NOTE: This will be fired as well, if the base type
12819 * is *'anyType'*.
12820 * NOTE: type->subtypes->subtypes will be the
12821 * <restriction> item.
12822 */
12823 if (type->subtypes->subtypes == NULL) {
12824 /* Yes, this is paranoid programming. */
12825 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
12826 NULL, type, NULL,
12827 "Internal error: xmlSchemaCheckSRCCT, "
12828 "'%s', <simpleContent> has no <restriction>",
12829 type->name);
12830 return (-1);
12831 }
12832 /*
12833 * 2.2 If clause 2.1.2 above is satisfied, then there
12834 * must be a <simpleType> among the [children] of
12835 * <restriction>.
12836 */
12837 if (type->subtypes->subtypes->type !=
12838 XML_SCHEMA_TYPE_SIMPLE) {
12839 /* TODO: Change error code to ..._SRC_CT_2_2. */
12840 xmlSchemaPCustomErr(ctxt,
12841 XML_SCHEMAP_SRC_CT_1,
12842 NULL, type, NULL,
12843 "A <simpleType> is expected among the children "
12844 "of <restriction>", NULL);
12845 return (XML_SCHEMAP_SRC_CT_1);
12846 }
12847 OK = 1;
12848 } else { /* if (base->contentType = XML_SCHEMA_CONTENT_MIXED)*/
12849 /*
12850 * 2.1.1 a complex type definition whose {content type} is a
12851 * simple type definition;
12852 */
12853 if (base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) {
12854 xmlSchemaPCustomErr(ctxt,
12855 XML_SCHEMAP_SRC_CT_1,
12856 NULL, type, NULL,
12857 "A complex type (simple content) cannot "
12858 "be derived from the complex type '%s'",
12859 base->name);
12860 return (XML_SCHEMAP_SRC_CT_1);
12861 }
12862 content = base->contentTypeDef;
12863 if (content == NULL) {
12864 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
12865 NULL, type, NULL,
12866 "Internal error: xmlSchemaCheckSRCCT, "
12867 "'%s', base type has no content type",
12868 type->name);
12869 return (-1);
12870 }
12871 if (content->type != XML_SCHEMA_TYPE_SIMPLE) {
12872 xmlSchemaPCustomErr(ctxt,
12873 XML_SCHEMAP_SRC_CT_1,
12874 NULL, type, NULL,
12875 "A complex type (simple content) cannot "
12876 "be derived from the complex type '%s'",
12877 base->name);
12878 return (XML_SCHEMAP_SRC_CT_1);
12879 }
12880 }
12881 }
12882 }
12883 }
12884 /*
12885 * TODO: 3 The corresponding complex type definition component must
12886 * satisfy the conditions set out in Constraints on Complex Type
12887 * Definition Schema Components (§3.4.6);
12888 *
12889 * TODO: 4 If clause 2.2.1 or clause 2.2.2 in the correspondence specification
12890 * above for {attribute wildcard} is satisfied, the intensional
12891 * intersection must be expressible, as defined in Attribute Wildcard
12892 * Intersection (§3.10.6).
12893 */
12894
12895}
William M. Brack2f2a6632004-08-20 23:09:47 +000012896#endif
12897
Daniel Veillard01fa6152004-06-29 17:04:39 +000012898/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012899 * xmlSchemaGroupDefFixup:
12900 * @typeDecl: the schema model group definition
12901 * @ctxt: the schema parser context
12902 *
12903 * Fixes model group definitions.
12904 */
12905static void
12906xmlSchemaGroupDefFixup(xmlSchemaTypePtr group,
12907 xmlSchemaParserCtxtPtr ctxt,
12908 const xmlChar * name ATTRIBUTE_UNUSED)
12909{
12910 group->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
12911 if ((group->ref != NULL) && (group->subtypes == NULL)) {
12912 xmlSchemaTypePtr groupDef;
12913 /*
12914 * Resolve the reference.
12915 */
12916 groupDef = xmlSchemaGetGroup(ctxt->schema, group->ref,
12917 group->refNs);
12918 if (groupDef == NULL) {
12919 xmlSchemaPResCompAttrErr(ctxt,
12920 XML_SCHEMAP_SRC_RESOLVE,
12921 NULL, group, NULL,
12922 "ref", group->ref, group->refNs,
12923 XML_SCHEMA_TYPE_GROUP, NULL);
12924 return;
12925 }
12926 group->subtypes = groupDef;
12927 }
12928}
12929
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012930#if 0 /* Enable when the content type will be computed. */
12931static int
12932xmlSchemaComputeContentType(xmlSchemaParserCtxtPtr ctxt,
12933 xmlSchemaTypePtr type)
12934{
12935 xmlSchemaTypePtr base, res = NULL;
12936
12937 base = type->baseType;
12938 if (base == NULL) {
12939 xmlSchemaPCustomErr(ctxt,
12940 XML_SCHEMAP_INTERNAL,
12941 NULL, type, NULL,
12942 "Internal error: xmlSchemaGetContentType, "
12943 "the complex type '%s' has no base type", type->name);
12944 return (-1);
12945 }
12946 if (IS_ANYTYPE(base) || (type->subtypes->type ==
12947 XML_SCHEMA_TYPE_COMPLEX_CONTENT)) {
12948 xmlSchemaTypePtr start;
12949 /*
12950 * Effective 'mixed'.
12951 */
12952 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
12953 type->contentType = XML_SCHEMA_CONTENT_MIXED;
12954 /*
12955 * Effective content.
12956 */
12957 if (IS_ANYTYPE(base))
12958 start = type;
12959 else
12960 start = type->subtypes;
12961
12962 } else { /* if XML_SCHEMA_TYPE_COMPLEX_CONTENT */
12963 xmlSchemaTypePtr baseContentItem;
12964
12965 /*
12966 * Complex type with simple content.
12967 */
12968 if IS_COMPLEX_TYPE(base) {
12969 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
12970 /*
12971 * Summary: a complex type (simple content) can *restrict*
12972 * a complex type with the following content type:
12973 * 1. 'mixed' and an emptiable particle
12974 * 2. simple type
12975 */
12976 if (base->contentType == XML_SCHEMA_CONTENT_MIXED) {
12977 /*
12978 * 2 if the {content type} of the base type is mixed and a
12979 * particle which is ·emptiable·,
12980 * [...]
12981 * then starting from the simple type definition
12982 * corresponding to the <simpleType> among the [children]
12983 * of <restriction> (**which must be present**)
12984 *
12985 * FIXME TODO: Handle "emptiable particle".
12986 */
12987 res = type->subtypes->subtypes;
12988 if (res == NULL) {
12989 xmlSchemaPCustomErr(ctxt,
12990 XML_SCHEMAP_INTERNAL,
12991 NULL, type, NULL,
12992 "Internal error: xmlSchemaGetContentType, "
12993 "CT '%s' (restricting): <simpleContent> has no "
12994 "<restriction>",
12995 type->name);
12996 return (-1);
12997 }
12998
12999 res->subtypes;
13000 if (res == NULL) {
13001 xmlSchemaPCustomErr(ctxt,
13002 XML_SCHEMAP_INTERNAL,
13003 NULL, type, NULL,
13004 "Internal error: xmlSchemaGetContentType, "
13005 "CT '%s' (restricting): <restriction> has no "
13006 "mandatory <simpleType>",
13007 type->name);
13008 return (-1);
13009 }
13010 } else {
13011 baseContentItem = base->contentTypeDef;
13012 if (baseContentItem == NULL) {
13013 xmlSchemaPCustomErr(ctxt,
13014 XML_SCHEMAP_INTERNAL,
13015 NULL, type, NULL,
13016 "Internal error: xmlSchemaGetContentType, "
13017 "CT '%s' (restricting), the base type has no "
13018 "content type", type->name);
13019 return (-1);
13020 }
13021 if IS_SIMPLE_TYPE(baseContentItem) {
13022 /*
13023 * 1 If the base type is a complex type whose own
13024 * {content type} is a simple type and the <restriction>
13025 * alternative is chosen
13026 */
13027 /* type->subtypes->subtypes will be the restriction item.*/
13028 res = type->subtypes->subtypes;
13029 if (res == NULL) {
13030 xmlSchemaPCustomErr(ctxt,
13031 XML_SCHEMAP_INTERNAL,
13032 NULL, type, NULL,
13033 "Internal error: xmlSchemaGetContentType, "
13034 "CT '%s' (restricting): <simpleType> has no "
13035 "<restriction>", type->name);
13036 return (-1);
13037 }
13038 /*
13039 * 1.1 the simple type definition corresponding to the
13040 * <simpleType> among the [children] of <restriction>if
13041 * there is one;
13042 */
13043 res = res->subtypes;
13044 if (res == NULL) {
13045 /*
13046 * 1.2 otherwise the {content type}
13047 * of the base type .
13048 */
13049 res = baseContentItem;
13050 }
13051 }
13052 }
13053 /*
13054 * SPECIAL TODO: If *restricting* the spec wants us to
13055 * create an *additional* simple type which restricts the
13056 * located simple type; we won't do this yet, and look how
13057 * far we get with it.
13058 */
13059 } else { /* if XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION */
13060 /*
13061 * Summary: a complex type (simple content) can *extend*
13062 * only a complex base with a simple type as content.
13063 */
13064 /*
13065 * 3 If the type definition ·resolved· to by the ·actual
13066 * value· of the base [attribute] is a complex type
13067 * definition (whose own {content type} *must be* a simple
13068 * type definition, see below) and the *<extension>*
13069 * alternative is chosen, then the {content type} of that
13070 * complex type definition;
13071 */
13072 res = base->contentTypeDef;
13073 if (res == NULL) {
13074 xmlSchemaPCustomErr(ctxt,
13075 XML_SCHEMAP_INTERNAL,
13076 NULL, type, NULL,
13077 "Internal error: xmlSchemaGetContentType, "
13078 "CT '%s' (extending), the base type has no content "
13079 "type", type->name);
13080 return (-1);
13081 }
13082 if (! IS_SIMPLE_TYPE(res)) {
13083 xmlSchemaPCustomErr(ctxt,
13084 XML_SCHEMAP_INTERNAL,
13085 NULL, type, NULL,
13086 "Internal error: xmlSchemaGetContentType, "
13087 "CT '%s' (extending), the content type of the "
13088 "base is not a simple type", type->name);
13089 return (-1);
13090 }
13091 }
13092 } else /* if IS_COMPLEX_TYPE(base) */
13093 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
13094 /*
13095 * 4 otherwise (the type definition ·resolved· to by the
13096 * ·actual value· of the base [attribute] is a simple type
13097 * definition and the <extension> alternative is chosen),
13098 * then that simple type definition.
13099 */
13100 res = base;
13101 }
13102 type->contentTypeDef = res;
13103 if (res == NULL) {
13104 xmlSchemaPCustomErr(ctxt,
13105 XML_SCHEMAP_INTERNAL,
13106 NULL, type, NULL,
13107 "Internal error: xmlSchemaGetContentType, "
13108 "'%s', the content type could not be determined",
13109 type->name);
13110 return (-1);
13111 }
13112
13113 }
13114
13115}
13116#endif
13117
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013118/**
Daniel Veillard4255d502002-04-16 15:50:10 +000013119 * xmlSchemaTypeFixup:
13120 * @typeDecl: the schema type definition
13121 * @ctxt: the schema parser context
13122 *
13123 * Fixes the content model of the type.
13124 */
13125static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013126xmlSchemaTypeFixup(xmlSchemaTypePtr item,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013127 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000013128{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013129 xmlSchemaTypePtr ctxtType;
13130
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013131 if (item == NULL)
Daniel Veillard82bbbd42003-05-11 20:16:09 +000013132 return;
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013133 /*
13134 * Do not allow the following types to be typefixed, prior to
13135 * the corresponding simple/complex types.
13136 */
13137 if (ctxt->ctxtType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013138 switch (item->type) {
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013139 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
13140 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
13141 case XML_SCHEMA_TYPE_UNION:
13142 case XML_SCHEMA_TYPE_RESTRICTION:
13143 case XML_SCHEMA_TYPE_EXTENSION:
13144 return;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013145 default:
13146 break;
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013147 }
13148 }
Daniel Veillard4255d502002-04-16 15:50:10 +000013149 if (name == NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013150 name = item->name;
13151 if (item->contentType == XML_SCHEMA_CONTENT_UNKNOWN) {
13152 switch (item->type) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013153 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013154 if (item->subtypes != NULL) {
13155 if (item->subtypes->contentType ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013156 XML_SCHEMA_CONTENT_UNKNOWN) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013157 xmlSchemaTypeFixup(item->subtypes, ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013158 NULL);
13159 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013160 item->contentType =
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013161 XML_SCHEMA_CONTENT_SIMPLE;
13162 /* item->subtypes->contentType; */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013163 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013164 break;
13165 }
13166 case XML_SCHEMA_TYPE_RESTRICTION:{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013167 xmlSchemaTypePtr base = NULL;
13168
13169 ctxt->ctxtType->flags |=
13170 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013171 if (item->baseType != NULL)
13172 base = item->baseType;
13173 else if (item->base != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013174 base =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013175 xmlSchemaGetType(ctxt->schema, item->base,
13176 item->baseNs);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013177 if (base == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013178 xmlSchemaPResCompAttrErr(ctxt,
13179 XML_SCHEMAP_SRC_RESOLVE,
William M. Brack2f2a6632004-08-20 23:09:47 +000013180 NULL, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013181 (xmlNodePtr) xmlSchemaGetPropNode(item->node, "base"),
13182 "base", item->base, item->baseNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013183 XML_SCHEMA_TYPE_BASIC, "type definition");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013184 } else if (base->contentType ==
Daniel Veillard3646d642004-06-02 19:19:14 +000013185 XML_SCHEMA_CONTENT_UNKNOWN) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013186 xmlSchemaTypeFixup(base, ctxt, NULL);
13187 }
William M. Brack2f2a6632004-08-20 23:09:47 +000013188 }
13189 ctxt->ctxtType->baseType = base;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013190 if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX) {
13191 /*
13192 * ComplexType restriction.
William M. Brack2f2a6632004-08-20 23:09:47 +000013193 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013194 /*
13195 * Content type.
13196 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013197 if (item->subtypes == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013198 /* 1.1.1 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013199 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
13200 else if ((item->subtypes->subtypes == NULL) &&
13201 ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013202 XML_SCHEMA_TYPE_ALL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013203 || (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013204 XML_SCHEMA_TYPE_SEQUENCE)))
13205 /* 1.1.2 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013206 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
13207 else if ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013208 XML_SCHEMA_TYPE_CHOICE)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013209 && (item->subtypes->subtypes == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +000013210 /* 1.1.3 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013211 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013212 else {
13213 /* 1.2 and 2.X are applied at the other layer */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013214 item->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000013215 XML_SCHEMA_CONTENT_ELEMENTS;
13216 }
13217 } else {
13218 /*
13219 * SimpleType restriction.
13220 */
William M. Brack2f2a6632004-08-20 23:09:47 +000013221 /* TODO: Nothing? */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013222 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013223 break;
13224 }
13225 case XML_SCHEMA_TYPE_EXTENSION:{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013226 xmlSchemaTypePtr base = NULL;
13227 xmlSchemaContentType explicitContentType;
13228
13229 /*
13230 * An extension does exist on a complexType only.
13231 */
13232 ctxt->ctxtType->flags |=
13233 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013234 if (item->recurse) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013235 /* TODO: The word "recursive" should be changed to "circular" here. */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013236 xmlSchemaPCustomErr(ctxt,
13237 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013238 NULL, item, item->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013239 "This item is circular", NULL);
Daniel Veillard2582a332004-04-18 19:49:46 +000013240 return;
13241 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013242 if (item->base != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013243 base =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013244 xmlSchemaGetType(ctxt->schema, item->base,
13245 item->baseNs);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013246 if (base == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013247 xmlSchemaPResCompAttrErr(ctxt,
13248 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013249 NULL, item, item->node,
13250 "base", item->base, item->baseNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013251 XML_SCHEMA_TYPE_BASIC, "type definition");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013252 } else if (base->contentType ==
13253 XML_SCHEMA_CONTENT_UNKNOWN) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013254 item->recurse = 1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013255 xmlSchemaTypeFixup(base, ctxt, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013256 item->recurse = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013257 }
13258 /*
13259 * The type definition ·resolved· to by the ·actual
13260 * value· of the base [attribute]
13261 */
13262 ctxt->ctxtType->baseType = base;
13263 /*
13264 * TODO: This one is still needed for computation of
13265 * the content model by xmlSchemaBuildAContentModel.
13266 * Try to get rid of it.
13267 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013268 item->baseType = base;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013269 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013270 if ((item->subtypes != NULL) &&
13271 (item->subtypes->contentType == XML_SCHEMA_CONTENT_UNKNOWN))
13272 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013273
13274 explicitContentType = XML_SCHEMA_CONTENT_ELEMENTS;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013275 if (item->subtypes == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013276 /* 1.1.1 */
13277 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013278 else if ((item->subtypes->subtypes == NULL) &&
13279 ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013280 XML_SCHEMA_TYPE_ALL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013281 || (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013282 XML_SCHEMA_TYPE_SEQUENCE)))
13283 /* 1.1.2 */
13284 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013285 else if ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013286 XML_SCHEMA_TYPE_CHOICE)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013287 && (item->subtypes->subtypes == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +000013288 /* 1.1.3 */
13289 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
13290 if (base != NULL) {
13291 /* It will be reported later, if the base is missing. */
13292 if (explicitContentType == XML_SCHEMA_CONTENT_EMPTY) {
13293 /* 2.1 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013294 item->contentType = base->contentType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013295 } else if (base->contentType ==
13296 XML_SCHEMA_CONTENT_EMPTY) {
13297 /* 2.2 imbitable ! */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013298 item->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000013299 XML_SCHEMA_CONTENT_ELEMENTS;
13300 } else {
13301 /* 2.3 imbitable pareil ! */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013302 item->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000013303 XML_SCHEMA_CONTENT_ELEMENTS;
13304 }
13305 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013306 break;
13307 }
13308 case XML_SCHEMA_TYPE_COMPLEX:{
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013309 ctxtType = ctxt->ctxtType;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013310 ctxt->ctxtType = item;
13311 /*
13312 * Start with an empty content-type type.
13313 */
13314 if (item->subtypes == NULL)
13315 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
13316
13317 if ((item->subtypes == NULL) ||
13318 ((item->subtypes->type !=
Daniel Veillard01fa6152004-06-29 17:04:39 +000013319 XML_SCHEMA_TYPE_SIMPLE_CONTENT) &&
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013320 (item->subtypes->type !=
Daniel Veillard01fa6152004-06-29 17:04:39 +000013321 XML_SCHEMA_TYPE_COMPLEX_CONTENT))) {
13322 /*
13323 * This case is understood as shorthand for complex
13324 * content restricting the ur-type definition, and
13325 * the details of the mappings should be modified as
13326 * necessary.
13327 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013328 item->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
13329 item->flags |=
Daniel Veillard01fa6152004-06-29 17:04:39 +000013330 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013331 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013332 * Assume that we inherit the content-type type
13333 * from 'anyType', which is 'mixed' and a particle
13334 * emptiable.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013335 */
13336 item->contentType = item->baseType->contentType;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013337 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013338 /*
13339 * Fixup the sub components.
13340 */
13341 if ((item->subtypes != NULL) &&
13342 (item->subtypes->contentType ==
13343 XML_SCHEMA_CONTENT_UNKNOWN)) {
13344 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013345 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013346 if (item->flags & XML_SCHEMAS_TYPE_MIXED) {
13347 item->contentType = XML_SCHEMA_CONTENT_MIXED;
13348 } else if (item->subtypes != NULL) {
13349 /*
13350 * Use the content-type type of the model groups
13351 * defined, if 'mixed' is not set. If 'mixed' is set
13352 * it will expand the content-type by allowing character
13353 * content to appear.
13354 */
13355 item->contentType =
13356 item->subtypes->contentType;
13357 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013358
13359 /*
13360 * Some optimization for validation:
13361 * If there are no facets beside the "whitespace" facet,
13362 * then a value needs not to checked against against a
13363 * facet, thus no computed value is needed.
13364 * TODO URGENT: This is just a workaround, we need to
13365 * introduce the correct usage of contentType to store the
13366 * facets in!
13367 */
Daniel Veillardd3210bc2005-01-28 17:56:39 +000013368 if ((item->baseType != NULL) &&
13369 (item->baseType->flags &
13370 XML_SCHEMAS_TYPE_FACETSNEEDVALUE))
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013371 item->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
13372 else {
13373 xmlSchemaFacetLinkPtr cur;
13374
13375 for (cur = item->facetSet; cur != NULL;
13376 cur = cur->next) {
13377 if (cur->facet->type != XML_SCHEMA_FACET_WHITESPACE) {
13378 item->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
13379 break;
13380 }
13381 }
13382 }
13383
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013384 xmlSchemaBuildAttributeValidation(ctxt, item);
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000013385 xmlSchemaCheckDefaults(item, ctxt, item->name);
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013386 ctxt->ctxtType = ctxtType;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013387 break;
13388 }
13389 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013390 if (item->subtypes == NULL) {
13391 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
13392 if (item->flags & XML_SCHEMAS_TYPE_MIXED)
13393 item->contentType =
Daniel Veillard1aefc862004-03-04 11:40:48 +000013394 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013395 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013396 if (item->flags & XML_SCHEMAS_TYPE_MIXED) {
13397 item->contentType =
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013398 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillard3646d642004-06-02 19:19:14 +000013399 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013400 xmlSchemaTypeFixup(item->subtypes, ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013401 NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013402 if (item->subtypes != NULL)
13403 item->contentType =
13404 item->subtypes->contentType;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013405 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013406 /*
13407 * Removed due to implementation of the build of attribute uses.
13408 */
13409 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013410 if (item->attributes == NULL)
13411 item->attributes =
13412 item->subtypes->attributes;
Daniel Veillard3646d642004-06-02 19:19:14 +000013413 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013414 }
13415 break;
13416 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013417 case XML_SCHEMA_TYPE_SIMPLE:
13418 /*
13419 * Simple Type Definition Schema Component
13420 *
13421 */
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013422 ctxtType = ctxt->ctxtType;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013423 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
13424 if (item->subtypes->contentType ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013425 XML_SCHEMA_CONTENT_UNKNOWN) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013426 ctxt->ctxtType = item;
13427 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013428 }
13429 /* Fixup base type */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013430 if ((item->baseType != NULL) &&
13431 (item->baseType->contentType ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013432 XML_SCHEMA_CONTENT_UNKNOWN)) {
13433 /* OPTIMIZE: Actually this one will never by hit, since
13434 * the base type is already type-fixed in <restriction>.
13435 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013436 ctxt->ctxtType = item;
13437 xmlSchemaTypeFixup(item->baseType, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013438 }
13439 /* Base type:
13440 * 2 If the <list> or <union> alternative is chosen,
13441 * then the ·simple ur-type definition·.
13442 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013443 if (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013444 XML_SCHEMA_TYPE_LIST) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013445 item->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
13446 item->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
13447 } else if (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013448 XML_SCHEMA_TYPE_UNION) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013449 item->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
13450 item->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
13451 } else if (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013452 XML_SCHEMA_TYPE_RESTRICTION) {
13453 xmlSchemaFacetLinkPtr facet, cur, last = NULL;
13454
13455 /*
13456 * Variety
13457 * If the <restriction> alternative is chosen, then the
13458 * {variety} of the {base type definition}.
13459 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013460 if (item->baseType != NULL) {
13461 if (item->baseType->flags &
Daniel Veillard01fa6152004-06-29 17:04:39 +000013462 XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013463 item->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
13464 else if (item->baseType->flags &
Daniel Veillard01fa6152004-06-29 17:04:39 +000013465 XML_SCHEMAS_TYPE_VARIETY_LIST)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013466 item->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
13467 else if (item->baseType->flags &
Daniel Veillard01fa6152004-06-29 17:04:39 +000013468 XML_SCHEMAS_TYPE_VARIETY_UNION)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013469 item->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013470 /*
13471 * Schema Component Constraint: Simple Type Restriction
13472 * (Facets)
13473 * NOTE: Satisfaction of 1 and 2 arise from the fixup
13474 * applied beforehand.
13475 *
13476 * 3 The {facets} of R are the union of S and the {facets}
13477 * of B, eliminating duplicates. To eliminate duplicates,
13478 * when a facet of the same kind occurs in both S and the
13479 * {facets} of B, the one in the {facets} of B is not
13480 * included, with the exception of enumeration and pattern
13481 * facets, for which multiple occurrences with distinct values
13482 * are allowed.
13483 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013484 if (item->baseType->facetSet != NULL) {
13485 last = item->facetSet;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013486 if (last != NULL)
13487 while (last->next != NULL)
13488 last = last->next;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013489 cur = item->baseType->facetSet;
13490 for (; cur != NULL; cur = cur->next) {
13491 /*
13492 * Base patterns won't be add here:
13493 * they are ORed in a type and
13494 * ANDed in derived types. This will
13495 * happed at validation level by
13496 * walking the base axis of the type.
13497 */
13498 if (cur->facet->type ==
13499 XML_SCHEMA_FACET_PATTERN)
13500 continue;
13501 facet = NULL;
13502 if ((item->facetSet != NULL) &&
13503 /* REMOVED: a check for
13504 * XML_SCHEMA_FACET_PATTERN was already
13505 * performed above.
13506
13507 * (cur->facet->type !=
13508 * XML_SCHEMA_FACET_PATTERN) &&
Daniel Veillard01fa6152004-06-29 17:04:39 +000013509 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013510 (cur->facet->type !=
13511 XML_SCHEMA_FACET_ENUMERATION)) {
13512 facet = item->facetSet;
13513 do {
13514 if (cur->facet->type ==
13515 facet->facet->type)
13516 break;
13517 facet = facet->next;
13518 } while (facet != NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013519 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013520 if (facet == NULL) {
13521 facet = (xmlSchemaFacetLinkPtr)
13522 xmlMalloc(sizeof(xmlSchemaFacetLink));
13523 if (facet == NULL) {
13524 xmlSchemaPErrMemory(ctxt,
13525 "fixing simpleType", NULL);
13526 return;
13527 }
13528 /*
13529 * The facets are not copied but referenced
13530 * via the facet link.
13531 */
13532 facet->facet = cur->facet;
13533 facet->next = NULL;
13534 if (last == NULL)
13535 item->facetSet = facet;
13536 else
13537 last->next = facet;
13538 last = facet;
13539 }
13540 }
13541 }
13542 /*
13543 * Some optimization for validation:
13544 * If there are no facets beside the "whitespace" facet,
13545 * then a value needs not to checked against against a
13546 * facet, thus no computed value is needed.
13547 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000013548 if (item->baseType->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013549 item->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
13550 else {
13551 for (cur = item->facetSet; cur != NULL;
13552 cur = cur->next) {
13553 if (cur->facet->type != XML_SCHEMA_FACET_WHITESPACE) {
13554 item->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
13555 break;
13556 }
13557 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013558 }
13559 }
13560 }
13561 /*
13562 * Check constraints.
13563 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013564 xmlSchemaCheckSRCSimpleType(ctxt, item);
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000013565 xmlSchemaCheckDefaults(item, ctxt, item->name);
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013566 ctxt->ctxtType = ctxtType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013567 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013568 case XML_SCHEMA_TYPE_SEQUENCE:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013569 case XML_SCHEMA_TYPE_ALL:
13570 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013571 item->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013572 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013573 case XML_SCHEMA_TYPE_GROUP:
13574 /*
13575 * TODO: Handling was moved to xmlSchemaGroupDefFixup.
13576 */
13577 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013578 case XML_SCHEMA_TYPE_LIST:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013579 xmlSchemaParseListRefFixup(item, ctxt);
13580 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013581 break;
13582 case XML_SCHEMA_TYPE_UNION:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013583 xmlSchemaParseUnionRefCheck(item, ctxt);
13584 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013585 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013586 case XML_SCHEMA_TYPE_BASIC:
13587 case XML_SCHEMA_TYPE_ANY:
13588 case XML_SCHEMA_TYPE_FACET:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013589 case XML_SCHEMA_TYPE_UR:
13590 case XML_SCHEMA_TYPE_ELEMENT:
13591 case XML_SCHEMA_TYPE_ATTRIBUTE:
13592 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
William M. Brack29aa7722004-05-12 00:27:56 +000013593 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013594 case XML_SCHEMA_TYPE_NOTATION:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013595 case XML_SCHEMA_FACET_MININCLUSIVE:
13596 case XML_SCHEMA_FACET_MINEXCLUSIVE:
13597 case XML_SCHEMA_FACET_MAXINCLUSIVE:
13598 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
13599 case XML_SCHEMA_FACET_TOTALDIGITS:
13600 case XML_SCHEMA_FACET_FRACTIONDIGITS:
13601 case XML_SCHEMA_FACET_PATTERN:
13602 case XML_SCHEMA_FACET_ENUMERATION:
13603 case XML_SCHEMA_FACET_WHITESPACE:
13604 case XML_SCHEMA_FACET_LENGTH:
13605 case XML_SCHEMA_FACET_MAXLENGTH:
13606 case XML_SCHEMA_FACET_MINLENGTH:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013607 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
13608 if (item->subtypes != NULL)
13609 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013610 break;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000013611 case XML_SCHEMA_TYPE_IDC_UNIQUE:
13612 case XML_SCHEMA_TYPE_IDC_KEY:
13613 case XML_SCHEMA_TYPE_IDC_KEYREF:
13614 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013615 }
13616 }
Daniel Veillard8651f532002-04-17 09:06:27 +000013617#ifdef DEBUG_TYPE
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013618 if (item->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013619 xmlGenericError(xmlGenericErrorContext,
13620 "Type of %s : %s:%d :", name,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013621 item->node->doc->URL,
13622 xmlGetLineNo(item->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +000013623 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013624 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000013625 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013626 switch (item->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013627 case XML_SCHEMA_CONTENT_SIMPLE:
13628 xmlGenericError(xmlGenericErrorContext, "simple\n");
13629 break;
13630 case XML_SCHEMA_CONTENT_ELEMENTS:
13631 xmlGenericError(xmlGenericErrorContext, "elements\n");
13632 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000013633 case XML_SCHEMA_CONTENT_UNKNOWN:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013634 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
13635 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000013636 case XML_SCHEMA_CONTENT_EMPTY:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013637 xmlGenericError(xmlGenericErrorContext, "empty\n");
13638 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000013639 case XML_SCHEMA_CONTENT_MIXED:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013640 xmlGenericError(xmlGenericErrorContext, "mixed\n");
13641 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013642 /* Removed, since not used. */
13643 /*
Daniel Veillard8651f532002-04-17 09:06:27 +000013644 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013645 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
13646 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013647 */
Daniel Veillard8651f532002-04-17 09:06:27 +000013648 case XML_SCHEMA_CONTENT_BASIC:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013649 xmlGenericError(xmlGenericErrorContext, "basic\n");
13650 break;
13651 default:
13652 xmlGenericError(xmlGenericErrorContext,
13653 "not registered !!!\n");
13654 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000013655 }
13656#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000013657}
13658
13659/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000013660 * xmlSchemaCheckFacet:
13661 * @facet: the facet
13662 * @typeDecl: the schema type definition
13663 * @ctxt: the schema parser context or NULL
13664 * @name: name of the type
13665 *
13666 * Checks the default values types, especially for facets
13667 *
13668 * Returns 0 if okay or -1 in cae of error
13669 */
13670int
13671xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013672 xmlSchemaTypePtr typeDecl,
13673 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000013674{
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +000013675 xmlSchemaTypePtr nonNegativeIntegerType = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013676 int ret = 0, reuseValCtxt = 0;
13677
Daniel Veillardce682bc2004-11-05 17:22:25 +000013678 if ((facet == NULL) || (typeDecl == NULL))
13679 return(-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013680 /*
13681 * TODO: will the parser context be given if used from
13682 * the relaxNG module?
13683 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000013684
13685 if (nonNegativeIntegerType == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013686 nonNegativeIntegerType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000013687 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000013688 }
13689 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013690 case XML_SCHEMA_FACET_MININCLUSIVE:
13691 case XML_SCHEMA_FACET_MINEXCLUSIVE:
13692 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013693 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
13694 case XML_SCHEMA_FACET_ENUMERATION: {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013695 /*
13696 * Okay we need to validate the value
13697 * at that point.
13698 */
13699 xmlSchemaValidCtxtPtr vctxt;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013700 xmlSchemaTypePtr base;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013701
13702 /* 4.3.5.5 Constraints on enumeration Schema Components
13703 * Schema Component Constraint: enumeration valid restriction
13704 * It is an ·error· if any member of {value} is not in the
13705 * ·value space· of {base type definition}.
13706 *
13707 * minInclusive, maxInclusive, minExclusive, maxExclusive:
13708 * The value ·must· be in the
13709 * ·value space· of the ·base type·.
13710 */
13711 /*
13712 * This function is intended to deliver a compiled value
13713 * on the facet. In XML Schemas the type holding a facet,
13714 * cannot be a built-in type. Thus to ensure that other API
13715 * calls (relaxng) do work, if the given type is a built-in
13716 * type, we will assume that the given built-in type *is
13717 * already* the base type.
13718 */
13719 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
13720 base = typeDecl->baseType;
13721 if (base == NULL) {
13722 xmlSchemaPErr(ctxt, typeDecl->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013723 XML_SCHEMAP_INTERNAL,
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013724 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013725 "the type '%s' has no base type.\n",
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013726 typeDecl->name, NULL);
13727 return (-1);
13728 }
13729 } else
13730 base = typeDecl;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013731 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013732 * This avoids perseverative creation of the
13733 * validation context if a parser context is
13734 * used.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013735 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013736 if (ctxt != NULL) {
13737 reuseValCtxt = 1;
13738 if (ctxt->vctxt == NULL) {
13739 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
13740 return (-1);
13741 }
13742 vctxt = ctxt->vctxt;
13743 } else {
13744 vctxt = xmlSchemaNewValidCtxt(NULL);
13745 if (vctxt == NULL) {
13746 xmlSchemaPErr(ctxt, typeDecl->node,
13747 XML_SCHEMAP_INTERNAL,
13748 "Internal error: xmlSchemaCheckFacet, "
13749 "creating a new validation context.\n",
13750 NULL, NULL);
13751 return (-1);
13752 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013753 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013754
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013755 vctxt->node = facet->node;
13756 vctxt->cur = NULL;
13757 /*
13758 * NOTE: This call does not check the content nodes,
13759 * since they are not available:
13760 * facet->node is just the node holding the facet
13761 * definition, *not* the attribute holding the *value*
13762 * of the facet.
13763 */
13764 ret = xmlSchemaValidateSimpleTypeValue(vctxt, base,
13765 facet->value, 0, 1, 1, 0);
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013766 facet->val = vctxt->value;
13767 vctxt->value = NULL;
13768 if (ret > 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013769 /* error code */
13770 if (ctxt != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013771 xmlSchemaPErrExt(ctxt, facet->node,
13772 XML_SCHEMAP_INVALID_FACET,
13773 NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013774 "Type definition '%s': The value '%s' of the "
13775 "facet '%s' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013776 name, facet->value,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013777 BAD_CAST xmlSchemaFacetTypeToString(facet->type),
Daniel Veillard01fa6152004-06-29 17:04:39 +000013778 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013779 }
13780 ret = -1;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013781 } else if (ret < 0) {
13782 xmlSchemaPErrExt(ctxt, facet->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013783 XML_SCHEMAP_INTERNAL,
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013784 NULL, NULL, NULL,
13785 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013786 "failed to validate the value '%s' name of the "
13787 "facet '%s' against the base type '%s'.\n",
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013788 facet->value,
13789 BAD_CAST xmlSchemaFacetTypeToString(facet->type),
13790 base->name, NULL, NULL);
13791 ret = -1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013792 }
13793 if (reuseValCtxt == 0)
13794 xmlSchemaFreeValidCtxt(vctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013795 break;
13796 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013797 case XML_SCHEMA_FACET_PATTERN:
13798 facet->regexp = xmlRegexpCompile(facet->value);
13799 if (facet->regexp == NULL) {
13800 xmlSchemaPErr(ctxt, typeDecl->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013801 XML_SCHEMAP_REGEXP_INVALID,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013802 "Type definition '%s': The value '%s' of the "
13803 "facet 'pattern' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013804 name, facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013805 ret = -1;
13806 }
13807 break;
13808 case XML_SCHEMA_FACET_TOTALDIGITS:
13809 case XML_SCHEMA_FACET_FRACTIONDIGITS:
13810 case XML_SCHEMA_FACET_LENGTH:
13811 case XML_SCHEMA_FACET_MAXLENGTH:
13812 case XML_SCHEMA_FACET_MINLENGTH:{
13813 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000013814
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013815 tmp =
13816 xmlSchemaValidatePredefinedType(nonNegativeIntegerType,
13817 facet->value,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +000013818 &(facet->val));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013819 if (tmp != 0) {
13820 /* error code */
13821 if (ctxt != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013822 xmlSchemaPErrExt(ctxt, facet->node,
13823 XML_SCHEMAP_INVALID_FACET_VALUE,
13824 NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013825 "Type definition '%s': The value '%s' of the "
13826 "facet '%s' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013827 name, facet->value,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013828 BAD_CAST xmlSchemaFacetTypeToString(facet->type),
Daniel Veillard01fa6152004-06-29 17:04:39 +000013829 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013830 }
13831 ret = -1;
13832 }
13833 break;
13834 }
13835 case XML_SCHEMA_FACET_WHITESPACE:{
13836 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
13837 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
13838 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
13839 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
13840 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
13841 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
13842 } else {
13843 if (ctxt != NULL) {
13844 xmlSchemaPErr(ctxt, facet->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013845 XML_SCHEMAP_INVALID_WHITE_SPACE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013846 "Type definition '%s': The value '%s' of the "
13847 "facet 'whiteSpace' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013848 name, facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013849 }
13850 ret = -1;
13851 }
13852 }
13853 default:
13854 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000013855 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013856 return (ret);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000013857}
13858
13859/**
Daniel Veillard4255d502002-04-16 15:50:10 +000013860 * xmlSchemaCheckDefaults:
13861 * @typeDecl: the schema type definition
13862 * @ctxt: the schema parser context
13863 *
13864 * Checks the default values types, especially for facets
13865 */
13866static void
13867xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013868 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000013869{
Daniel Veillard4255d502002-04-16 15:50:10 +000013870 if (name == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013871 name = typeDecl->name;
13872 /*
13873 * NOTE: It is intended to use the facets list, instead
13874 * of facetSet.
13875 */
13876 if (typeDecl->facets != NULL) {
13877 xmlSchemaFacetPtr facet = typeDecl->facets;
13878
13879 while (facet != NULL) {
13880 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
13881 facet = facet->next;
13882 }
13883 }
Daniel Veillard4255d502002-04-16 15:50:10 +000013884}
13885
13886/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013887 * xmlSchemaGetCircModelGrDefRef:
13888 * @ctxtGr: the searched model group
13889 * @list: the list of model groups to be processed
13890 *
13891 * This one is intended to be used by
13892 * xmlSchemaCheckGroupDefCircular only.
13893 *
13894 * Returns the circular model group definition reference, otherwise NULL.
13895 */
13896static xmlSchemaTypePtr
13897xmlSchemaGetCircModelGrDefRef(xmlSchemaTypePtr ctxtGrDef,
13898 xmlSchemaTypePtr gr)
13899{
13900 xmlSchemaTypePtr circ = NULL;
13901 int marked;
13902 /*
13903 * We will search for an model group reference which
13904 * references the context model group definition.
13905 */
13906 while (gr != NULL) {
13907 if (((gr->type == XML_SCHEMA_TYPE_GROUP) ||
13908 (gr->type == XML_SCHEMA_TYPE_ALL) ||
13909 (gr->type == XML_SCHEMA_TYPE_SEQUENCE) ||
13910 (gr->type == XML_SCHEMA_TYPE_CHOICE)) &&
13911 (gr->subtypes != NULL)) {
13912 marked = 0;
13913 if ((gr->type == XML_SCHEMA_TYPE_GROUP) &&
13914 (gr->ref != NULL)) {
13915 if (gr->subtypes == ctxtGrDef)
13916 return (gr);
13917 else if (gr->subtypes->flags &
13918 XML_SCHEMAS_TYPE_MARKED) {
13919 gr = gr->next;
13920 continue;
13921 } else {
13922 /*
13923 * Mark to avoid infinite recursion on
13924 * circular references not yet examined.
13925 */
13926 gr->subtypes->flags |= XML_SCHEMAS_TYPE_MARKED;
13927 marked = 1;
13928 }
13929 if (gr->subtypes->subtypes != NULL)
13930 circ = xmlSchemaGetCircModelGrDefRef(ctxtGrDef,
13931 gr->subtypes->subtypes);
13932 /*
13933 * Unmark the visited model group definition.
13934 */
13935 if (marked)
13936 gr->subtypes->flags ^= XML_SCHEMAS_TYPE_MARKED;
13937 if (circ != NULL)
13938 return (circ);
13939 } else {
13940 circ = xmlSchemaGetCircModelGrDefRef(ctxtGrDef,
13941 (xmlSchemaTypePtr) gr->subtypes);
13942 if (circ != NULL)
13943 return (circ);
13944 }
13945
13946 }
13947 gr = gr->next;
13948 }
13949 return (NULL);
13950}
13951
13952/**
13953 * xmlSchemaCheckGroupDefCircular:
13954 * attrGr: the model group definition
13955 * @ctxt: the parser context
13956 * @name: the name
13957 *
13958 * Checks for circular references to model group definitions.
13959 */
13960static void
13961xmlSchemaCheckGroupDefCircular(xmlSchemaTypePtr modelGrDef,
13962 xmlSchemaParserCtxtPtr ctxt,
13963 const xmlChar * name ATTRIBUTE_UNUSED)
13964{
13965 /*
13966 * Schema Component Constraint: Model Group Correct
13967 * 2 Circular groups are disallowed. That is, within the {particles}
13968 * of a group there must not be at any depth a particle whose {term}
13969 * is the group itself.
13970 */
13971 /*
13972 * NOTE: "gr->subtypes" holds the referenced group.
13973 */
13974 if ((modelGrDef->type != XML_SCHEMA_TYPE_GROUP) ||
13975 ((modelGrDef->flags & XML_SCHEMAS_TYPE_GLOBAL) == 0) ||
13976 (modelGrDef->subtypes == NULL))
13977 return;
13978 else {
13979 xmlSchemaTypePtr circ;
13980
13981 circ = xmlSchemaGetCircModelGrDefRef(modelGrDef, modelGrDef->subtypes);
13982 if (circ != NULL) {
13983 /*
13984 * TODO: Report the referenced attr group as QName.
13985 */
13986 xmlSchemaPCustomErr(ctxt,
13987 XML_SCHEMAP_MG_PROPS_CORRECT_2,
13988 NULL, NULL, circ->node,
13989 "Circular reference to the model group definition '%s' "
13990 "defined", modelGrDef->name);
13991 /*
13992 * NOTE: We will cut the reference to avoid further
13993 * confusion of the processor.
13994 * TODO: SPEC: Does the spec define how to process here?
13995 */
13996 circ->subtypes = NULL;
13997 }
13998 }
13999}
14000
14001
14002/**
14003 * xmlSchemaGetCircAttrGrRef:
14004 * @ctxtGr: the searched attribute group
14005 * @attr: the current attribute list to be processed
14006 *
14007 * This one is intended to be used by
14008 * xmlSchemaCheckSRCAttributeGroupCircular only.
14009 *
14010 * Returns the circular attribute grou reference, otherwise NULL.
14011 */
14012static xmlSchemaAttributeGroupPtr
14013xmlSchemaGetCircAttrGrRef(xmlSchemaAttributeGroupPtr ctxtGr,
14014 xmlSchemaAttributePtr attr)
14015{
14016 xmlSchemaAttributeGroupPtr circ = NULL, gr;
14017 int marked;
14018 /*
14019 * We will search for an attribute group reference which
14020 * references the context attribute group.
14021 */
14022 while (attr != NULL) {
14023 marked = 0;
14024 if (attr->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
14025 gr = (xmlSchemaAttributeGroupPtr) attr;
14026 if (gr->refItem != NULL) {
14027 if (gr->refItem == ctxtGr)
14028 return (gr);
14029 else if (gr->refItem->flags &
14030 XML_SCHEMAS_ATTRGROUP_MARKED) {
14031 attr = attr->next;
14032 continue;
14033 } else {
14034 /*
14035 * Mark as visited to avoid infinite recursion on
14036 * circular references not yet examined.
14037 */
14038 gr->refItem->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
14039 marked = 1;
14040 }
14041 }
14042 if (gr->attributes != NULL)
14043 circ = xmlSchemaGetCircAttrGrRef(ctxtGr, gr->attributes);
14044 /*
14045 * Unmark the visited group's attributes.
14046 */
14047 if (marked)
14048 gr->refItem->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
14049 if (circ != NULL)
14050 return (circ);
14051 }
14052 attr = attr->next;
14053 }
14054 return (NULL);
14055}
14056
14057/**
14058 * xmlSchemaCheckSRCAttributeGroupCircular:
14059 * attrGr: the attribute group definition
14060 * @ctxt: the parser context
14061 * @name: the name
14062 *
14063 * Checks for circular references of attribute groups.
14064 */
14065static void
14066xmlSchemaCheckAttributeGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
14067 xmlSchemaParserCtxtPtr ctxt,
14068 const xmlChar * name ATTRIBUTE_UNUSED)
14069{
14070 /*
14071 * Schema Representation Constraint:
14072 * Attribute Group Definition Representation OK
14073 * 3 Circular group reference is disallowed outside <redefine>.
14074 * That is, unless this element information item's parent is
14075 * <redefine>, then among the [children], if any, there must
14076 * not be an <attributeGroup> with ref [attribute] which resolves
14077 * to the component corresponding to this <attributeGroup>. Indirect
14078 * circularity is also ruled out. That is, when QName resolution
14079 * (Schema Document) (§3.15.3) is applied to a ·QName· arising from
14080 * any <attributeGroup>s with a ref [attribute] among the [children],
14081 * it must not be the case that a ·QName· is encountered at any depth
14082 * which resolves to the component corresponding to this <attributeGroup>.
14083 */
14084 /*
14085 * Only global components can be referenced.
14086 */
14087 if (((attrGr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) == 0) ||
14088 (attrGr->attributes == NULL))
14089 return;
14090 else {
14091 xmlSchemaAttributeGroupPtr circ;
14092
14093 circ = xmlSchemaGetCircAttrGrRef(attrGr, attrGr->attributes);
14094 if (circ != NULL) {
14095 /*
14096 * TODO: Report the referenced attr group as QName.
14097 */
14098 xmlSchemaPCustomErr(ctxt,
14099 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
14100 NULL, NULL, circ->node,
14101 "Circular reference to the attribute group '%s' "
14102 "defined", attrGr->name);
14103 /*
14104 * NOTE: We will cut the reference to avoid further
14105 * confusion of the processor.
14106 * BADSPEC: The spec should define how to process in this case.
14107 */
14108 circ->attributes = NULL;
14109 circ->refItem = NULL;
14110 }
14111 }
14112}
14113
14114/**
Daniel Veillard13e04c62002-04-23 17:51:29 +000014115 * xmlSchemaAttrGrpFixup:
14116 * @attrgrpDecl: the schema attribute definition
14117 * @ctxt: the schema parser context
14118 * @name: the attribute name
14119 *
14120 * Fixes finish doing the computations on the attributes definitions
14121 */
14122static void
Daniel Veillard3646d642004-06-02 19:19:14 +000014123xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014124 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +000014125{
14126 if (name == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000014127 name = attrgrp->name;
14128 if (attrgrp->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014129 return;
Daniel Veillard3646d642004-06-02 19:19:14 +000014130 if (attrgrp->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014131 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +000014132
Daniel Veillardc0826a72004-08-10 14:17:33 +000014133 ref = xmlSchemaGetAttributeGroup(ctxt->schema, attrgrp->ref,
14134 attrgrp->refNs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014135 if (ref == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014136 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014137 XML_SCHEMAP_SRC_RESOLVE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014138 NULL, (xmlSchemaTypePtr) attrgrp, attrgrp->node,
14139 "ref", attrgrp->ref, attrgrp->refNs,
14140 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014141 return;
14142 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014143 attrgrp->refItem = ref;
14144 /*
14145 * Check for self reference!
14146 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014147 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000014148 attrgrp->attributes = ref->attributes;
14149 attrgrp->attributeWildcard = ref->attributeWildcard;
14150 }
Daniel Veillard13e04c62002-04-23 17:51:29 +000014151}
14152
14153/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014154 * xmlSchemaAttrCheckValConstr:
14155 * @item: an schema attribute declaration/use
14156 * @ctxt: a schema parser context
14157 * @name: the name of the attribute
14158 *
14159 * Validates the value constraints of an attribute declaration/use.
Daniel Veillard4255d502002-04-16 15:50:10 +000014160 *
14161 * Fixes finish doing the computations on the attributes definitions
14162 */
14163static void
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014164xmlSchemaCheckAttrValConstr(xmlSchemaAttributePtr item,
14165 xmlSchemaParserCtxtPtr ctxt,
14166 const xmlChar * name ATTRIBUTE_UNUSED)
14167{
14168
14169 /*
14170 * a-props-correct
14171 * Schema Component Constraint: Attribute Declaration Properties Correct
14172 *
14173 * 2 if there is a {value constraint}, the canonical lexical
14174 * representation of its value must be ·valid· with respect
14175 * to the {type definition} as defined in String Valid (§3.14.4).
14176 */
14177
14178 if (item->defValue != NULL) {
14179 int ret;
14180 xmlNodePtr node;
14181 xmlSchemaTypePtr type;
14182
14183 if (item->subtypes == NULL) {
14184 xmlSchemaPErr(ctxt, item->node,
14185 XML_SCHEMAP_INTERNAL,
14186 "Internal error: xmlSchemaCheckAttrValConstr, "
14187 "type is missing... skipping validation of "
14188 "value constraint", NULL, NULL);
14189 return;
14190 }
14191
14192 /*
14193 * TODO: Try to avoid creating a new context.
14194 * TODO: This all is not very performant.
14195 */
14196 type = item->subtypes;
14197 /*
14198 * Ensure there's validation context.
14199 */
14200 if (ctxt->vctxt == NULL) {
14201 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1) {
14202 xmlSchemaPErr(ctxt, item->node,
14203 XML_SCHEMAP_INTERNAL,
14204 "Internal error: xmlSchemaCheckAttrValConstr, "
14205 "creating a new validation context.\n",
14206 NULL, NULL);
14207 return;
14208 }
14209 }
14210
14211 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
14212 node = (xmlNodePtr) xmlHasProp(item->node, BAD_CAST "fixed");
14213 else
14214 node = (xmlNodePtr) xmlHasProp(item->node, BAD_CAST "default");
14215 ctxt->vctxt->node = node;
14216 ctxt->vctxt->cur = NULL;
14217 /*
14218 * NOTE: This call does not check the content nodes,
14219 * since they are not available:
14220 * facet->node is just the node holding the facet
14221 * definition, *not* the attribute holding the *value*
14222 * of the facet.
14223 */
14224 ret = xmlSchemaValidateSimpleTypeValue(ctxt->vctxt, type,
14225 item->defValue, 0, 1, 1, 0);
14226 if (ret == 0) {
14227 /*
14228 * Store the computed value.
14229 */
14230 item->defVal = ctxt->vctxt->value;
14231 ctxt->vctxt->value = NULL;
14232 } else if (ret > 0) {
14233 if (ctxt != NULL) {
14234 xmlSchemaPSimpleTypeErr(ctxt,
14235 XML_SCHEMAP_A_PROPS_CORRECT_2,
14236 NULL, NULL, node,
14237 type, NULL, item->defValue,
14238 NULL, NULL, NULL);
14239 }
14240 } else if (ret < 0) {
14241 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
14242 NULL, NULL, node,
14243 "Internal error: xmlSchemaAttrCheckValConstr, "
14244 "failed to validate the value constraint of the "
14245 "attribute decl/use against the type '%s'",
14246 type->name);
14247 }
14248 }
14249}
14250
14251#if 0 /* Not used yet. */
14252static int
14253xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
14254 xmlSchemaElementPtr edecl)
14255{
14256 /*
14257 * TODO: 1 The values of the properties of an element declaration must be as
14258 * described in the property tableau in The Element Declaration Schema
14259 * Component (§3.3.1), modulo the impact of Missing Sub-components (§5.3).
14260 */
14261 /*
14262 * 2 If there is a {value constraint}, the canonical lexical
14263 * representation of its value must be ·valid· with respect to the {type
14264 * definition} as defined in Element Default Valid (Immediate) (§3.3.6).
14265 *
14266 * NOTE: This is done in xmlSchemaCheckElemValConstr.
14267 */
14268 /*
14269 * 3 If there is a non-·absent· {substitution group affiliation},
14270 * then {scope} must be global.
14271 *
14272 * NOTE: This is done in xmlSchemaParseElement.
14273 * TODO: Move it to this layer here.
14274 */
14275 /*
14276 * TODO: 4 If there is a {substitution group affiliation}, the {type definition}
14277 * of the element declaration must be validly derived from the {type
14278 * definition} of the {substitution group affiliation}, given the value
14279 * of the {substitution group exclusions} of the {substitution group
14280 * affiliation}, as defined in Type Derivation OK (Complex) (§3.4.6)
14281 * (if the {type definition} is complex) or as defined in
14282 * Type Derivation OK (Simple) (§3.14.6) (if the {type definition} is
14283 * simple).
14284 */
14285 /*
14286 * TODO: 5 If the {type definition} or {type definition}'s {content type}
14287 * is or is derived from ID then there must not be a {value constraint}.
14288 * Note: The use of ID as a type definition for elements goes beyond
14289 * XML 1.0, and should be avoided if backwards compatibility is desired
14290 */
14291 /*
14292 * TODO: 6 Circular substitution groups are disallowed. That is, it must not
14293 * be possible to return to an element declaration by repeatedly following
14294 * the {substitution group affiliation} property.
14295 */
14296}
14297#endif
14298
14299/**
14300 * xmlSchemaCheckElemValConstr:
14301 * @item: an schema element declaration/particle
14302 * @ctxt: a schema parser context
14303 * @name: the name of the attribute
14304 *
14305 * Validates the value constraints of an element declaration.
14306 *
14307 * Fixes finish doing the computations on the element declarations.
14308 */
14309static void
14310xmlSchemaCheckElemValConstr(xmlSchemaElementPtr decl,
14311 xmlSchemaParserCtxtPtr ctxt,
14312 const xmlChar * name ATTRIBUTE_UNUSED)
14313{
14314 if (decl->value != NULL) {
14315 int ret;
14316 xmlNodePtr node = NULL;
14317 xmlSchemaTypePtr type;
14318
14319 /*
14320 * 2 If there is a {value constraint}, the canonical lexical
14321 * representation of its value must be ·valid· with respect to the {type
14322 * definition} as defined in Element Default Valid (Immediate) (§3.3.6).
14323 */
14324 if (decl->subtypes == NULL) {
14325 xmlSchemaPErr(ctxt, decl->node,
14326 XML_SCHEMAP_INTERNAL,
14327 "Internal error: xmlSchemaCheckElemValConstr, "
14328 "type is missing... skipping validation of "
14329 "the value constraint", NULL, NULL);
14330 return;
14331 }
14332 /*
14333 * Ensure there's a validation context.
14334 */
14335 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
14336 return;
14337
14338 type = decl->subtypes;
14339
14340 if (decl->node != NULL) {
14341 if (decl->flags & XML_SCHEMAS_ELEM_FIXED)
14342 node = (xmlNodePtr) xmlHasProp(decl->node, BAD_CAST "fixed");
14343 else
14344 node = (xmlNodePtr) xmlHasProp(decl->node, BAD_CAST "default");
14345 }
14346 ctxt->vctxt->node = node;
14347 ctxt->vctxt->cur = NULL;
14348 ret = xmlSchemaCheckCOSValidDefault(ctxt, ctxt->vctxt, type, decl->value,
14349 node);
14350 if (ret == 0) {
14351 /*
14352 * Consume the computed value.
14353 */
14354 decl->defVal = ctxt->vctxt->value;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000014355 ctxt->vctxt->value = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014356 } else if (ret < 0) {
14357 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
14358 NULL, NULL, node,
14359 "Internal error: xmlSchemaElemCheckValConstr, "
14360 "failed to validate the value constraint of the "
14361 "element declaration '%s'",
14362 decl->name);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000014363 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014364 }
14365}
14366
14367/**
14368 * xmlSchemaAttrFixup:
14369 * @item: an schema attribute declaration/use.
14370 * @ctxt: a schema parser context
14371 * @name: the name of the attribute
14372 *
14373 * Fixes finish doing the computations on attribute declarations/uses.
14374 */
14375static void
14376xmlSchemaAttrFixup(xmlSchemaAttributePtr item,
14377 xmlSchemaParserCtxtPtr ctxt,
14378 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000014379{
Daniel Veillardc0826a72004-08-10 14:17:33 +000014380 /*
14381 * TODO: If including this is done twice (!) for every attribute.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014382 * -> Hmm, check if this is still done.
Daniel Veillardc0826a72004-08-10 14:17:33 +000014383 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014384 /*
14385 * The simple type definition corresponding to the <simpleType> element
14386 * information item in the [children], if present, otherwise the simple
14387 * type definition ·resolved· to by the ·actual value· of the type
14388 * [attribute], if present, otherwise the ·simple ur-type definition·.
14389 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014390 if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
Daniel Veillardc0826a72004-08-10 14:17:33 +000014391 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014392 item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
14393 if (item->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014394 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014395 if (item->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014396 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000014397
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014398 type = xmlSchemaGetType(ctxt->schema, item->typeName,
14399 item->typeNs);
14400 if ((type == NULL) || (! IS_SIMPLE_TYPE(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014401 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014402 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014403 NULL, (xmlSchemaTypePtr) item, item->node,
14404 "type", item->typeName, item->typeNs,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014405 XML_SCHEMA_TYPE_SIMPLE, NULL);
14406 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014407 item->subtypes = type;
14408
14409 } else if (item->ref != NULL) {
14410 xmlSchemaAttributePtr decl;
Daniel Veillard4255d502002-04-16 15:50:10 +000014411
Daniel Veillardc0826a72004-08-10 14:17:33 +000014412 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014413 * We have an attribute use here; assign the referenced
14414 * attribute declaration.
14415 */
14416 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000014417 * TODO: Evaluate, what errors could occur if the declaration is not
14418 * found. It might be possible that the "typefixup" might crash if
14419 * no ref declaration was found.
14420 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014421 decl = xmlSchemaGetAttribute(ctxt->schema, item->ref, item->refNs);
14422 if (decl == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014423 xmlSchemaPResCompAttrErr(ctxt,
14424 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014425 NULL, (xmlSchemaTypePtr) item, item->node,
14426 "ref", item->ref, item->refNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014427 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014428 return;
14429 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014430 item->refDecl = decl;
14431 xmlSchemaAttrFixup(decl, ctxt, NULL);
14432
14433 item->subtypes = decl->subtypes;
14434 /*
14435 * Attribute Use Correct
14436 * au-props-correct.2: If the {attribute declaration} has a fixed
14437 * {value constraint}, then if the attribute use itself has a
14438 * {value constraint}, it must also be fixed and its value must match
14439 * that of the {attribute declaration}'s {value constraint}.
14440 */
14441 if ((decl->flags & XML_SCHEMAS_ATTR_FIXED) &&
14442 (item->defValue != NULL)) {
14443 if (((item->flags & XML_SCHEMAS_ATTR_FIXED) == 0) ||
14444 (!xmlStrEqual(item->defValue, decl->defValue))) {
14445 xmlSchemaPCustomErr(ctxt,
14446 XML_SCHEMAP_AU_PROPS_CORRECT_2,
14447 NULL, NULL, item->node,
14448 "The value constraint must be fixed "
14449 "and match the referenced attribute "
14450 "declarations's value constraint '%s'",
14451 decl->defValue);
14452 }
14453 /*
14454 * FUTURE: One should change the values of the attr. use
14455 * if ever validation should be attempted even if the
14456 * schema itself was not fully valid.
14457 */
14458 }
Daniel Veillard3646d642004-06-02 19:19:14 +000014459 } else {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014460 item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
14461 }
Daniel Veillard4255d502002-04-16 15:50:10 +000014462}
14463
14464/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000014465 * xmlSchemaResolveIDCKeyRef:
14466 * @idc: the identity-constraint definition
14467 * @ctxt: the schema parser context
14468 * @name: the attribute name
14469 *
14470 * Resolve keyRef references to key/unique IDCs.
14471 */
14472static void
14473xmlSchemaResolveIDCKeyRef(xmlSchemaIDCPtr idc,
14474 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000014475 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000014476{
14477 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
14478 return;
14479 if (idc->ref->name != NULL) {
14480 idc->ref->item = (xmlSchemaBasicItemPtr) xmlHashLookup2(
14481 ctxt->schema->idcDef,
14482 idc->ref->name,
14483 idc->ref->targetNamespace);
14484 if (idc->ref->item == NULL) {
14485 /*
14486 * TODO: It is actually not an error to fail to resolve.
14487 */
14488 xmlSchemaPResCompAttrErr(ctxt,
14489 XML_SCHEMAP_SRC_RESOLVE,
14490 NULL, (xmlSchemaTypePtr) idc, idc->node,
14491 "refer", idc->ref->name,
14492 idc->ref->targetNamespace,
14493 XML_SCHEMA_TYPE_IDC_KEYREF, NULL);
14494 return;
14495 }
14496 }
14497}
14498
14499/**
Daniel Veillard4255d502002-04-16 15:50:10 +000014500 * xmlSchemaParse:
14501 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000014502 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000014503 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +000014504 * XML Shema struture which can be used to validate instances.
14505 * *WARNING* this interface is highly subject to change
14506 *
14507 * Returns the internal XML Schema structure built from the resource or
14508 * NULL in case of error
14509 */
14510xmlSchemaPtr
14511xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
14512{
14513 xmlSchemaPtr ret = NULL;
14514 xmlDocPtr doc;
Daniel Veillardbd2904b2003-11-25 15:38:59 +000014515 xmlNodePtr root;
Daniel Veillarddda22c12004-01-24 08:31:30 +000014516 int preserve = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000014517
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014518 /*
14519 * This one is used if the schema to be parsed was specified via
14520 * the API; i.e. not automatically by the validated instance document.
14521 */
14522
Daniel Veillard4255d502002-04-16 15:50:10 +000014523 xmlSchemaInitTypes();
14524
Daniel Veillard6045c902002-10-09 21:13:59 +000014525 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +000014526 return (NULL);
14527
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000014528 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000014529 ctxt->counter = 0;
14530 ctxt->container = NULL;
14531
14532 /*
14533 * First step is to parse the input document into an DOM/Infoset
14534 */
Daniel Veillard6045c902002-10-09 21:13:59 +000014535 if (ctxt->URL != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000014536 doc = xmlReadFile((const char *) ctxt->URL, NULL,
14537 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014538 if (doc == NULL) {
14539 xmlSchemaPErr(ctxt, NULL,
14540 XML_SCHEMAP_FAILED_LOAD,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014541 "xmlSchemaParse: could not load '%s'.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014542 ctxt->URL, NULL);
14543 return (NULL);
14544 }
Daniel Veillard6045c902002-10-09 21:13:59 +000014545 } else if (ctxt->buffer != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000014546 doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
14547 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014548 if (doc == NULL) {
14549 xmlSchemaPErr(ctxt, NULL,
14550 XML_SCHEMAP_FAILED_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014551 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014552 NULL, NULL);
14553 return (NULL);
14554 }
14555 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard65765282004-01-08 16:59:30 +000014556 ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
Daniel Veillard9d751502003-10-29 13:21:47 +000014557 } else if (ctxt->doc != NULL) {
14558 doc = ctxt->doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000014559 preserve = 1;
Daniel Veillard6045c902002-10-09 21:13:59 +000014560 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014561 xmlSchemaPErr(ctxt, NULL,
14562 XML_SCHEMAP_NOTHING_TO_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014563 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014564 NULL, NULL);
14565 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000014566 }
14567
14568 /*
14569 * Then extract the root and Schema parse it
14570 */
14571 root = xmlDocGetRootElement(doc);
14572 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014573 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
14574 XML_SCHEMAP_NOROOT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014575 "The schema has no document element.\n", NULL, NULL);
Daniel Veillarddda22c12004-01-24 08:31:30 +000014576 if (!preserve) {
14577 xmlFreeDoc(doc);
14578 }
Daniel Veillard4255d502002-04-16 15:50:10 +000014579 return (NULL);
14580 }
14581
14582 /*
14583 * Remove all the blank text nodes
14584 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +000014585 xmlSchemaCleanupDoc(ctxt, root);
Daniel Veillard4255d502002-04-16 15:50:10 +000014586
14587 /*
14588 * Then do the parsing for good
14589 */
14590 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillard1d913862003-11-21 00:28:39 +000014591 if (ret == NULL) {
Daniel Veillarddda22c12004-01-24 08:31:30 +000014592 if (!preserve) {
14593 xmlFreeDoc(doc);
14594 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014595 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +000014596 }
Daniel Veillard4255d502002-04-16 15:50:10 +000014597 ret->doc = doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000014598 ret->preserve = preserve;
Daniel Veillard4255d502002-04-16 15:50:10 +000014599 ctxt->schema = ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014600 ctxt->ctxtType = NULL;
14601 ctxt->parentItem = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000014602 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +000014603 * Then fixup all attributes declarations
14604 */
14605 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
14606
14607 /*
14608 * Then fixup all attributes group declarations
14609 */
14610 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
14611 ctxt);
14612
14613 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000014614 * Resolve identity-constraint keyRefs.
14615 */
14616 xmlHashScan(ret->idcDef, (xmlHashScanner) xmlSchemaResolveIDCKeyRef, ctxt);
14617
14618 /*
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014619 * Check attribute groups for circular references.
14620 */
14621 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner)
14622 xmlSchemaCheckAttributeGroupCircular, ctxt);
14623
14624 /*
14625 * Then fixup all model group definitions.
14626 */
14627 xmlHashScan(ret->groupDecl, (xmlHashScanner) xmlSchemaGroupDefFixup, ctxt);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014628
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014629 /*
Daniel Veillard4255d502002-04-16 15:50:10 +000014630 * Then fixup all types properties
Daniel Veillardc0826a72004-08-10 14:17:33 +000014631 */
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014632 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014633
14634 /*
14635 * Then fix references of element declaration; apply constraints.
14636 */
14637 xmlHashScanFull(ret->elemDecl,
14638 (xmlHashScannerFull) xmlSchemaRefFixupCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000014639
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014640 /*
14641 * Check model groups defnitions for circular references.
14642 */
14643 xmlHashScan(ret->groupDecl, (xmlHashScanner)
14644 xmlSchemaCheckGroupDefCircular, ctxt);
14645
Daniel Veillard4255d502002-04-16 15:50:10 +000014646 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014647 * Then build the content model for all complex types
Daniel Veillard4255d502002-04-16 15:50:10 +000014648 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014649 xmlHashScan(ret->typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014650 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000014651
14652 /*
14653 * Then check the defaults part of the type like facets values
14654 */
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000014655 /* OLD: xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaCheckDefaults, ctxt); */
Daniel Veillard4255d502002-04-16 15:50:10 +000014656
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014657 /*
14658 * Validate the value constraint of attribute declarations/uses.
14659 */
14660 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaCheckAttrValConstr, ctxt);
14661
14662 /*
14663 * Validate the value constraint of element declarations.
14664 */
14665 xmlHashScan(ret->elemDecl, (xmlHashScanner) xmlSchemaCheckElemValConstr, ctxt);
14666
Daniel Veillardc0826a72004-08-10 14:17:33 +000014667
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000014668 if (ctxt->nberrors != 0) {
14669 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014670 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000014671 }
Daniel Veillard4255d502002-04-16 15:50:10 +000014672 return (ret);
14673}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014674
Daniel Veillard4255d502002-04-16 15:50:10 +000014675/**
Daniel Veillard01c13b52002-12-10 15:19:08 +000014676 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +000014677 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +000014678 * @err: the error callback
14679 * @warn: the warning callback
14680 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +000014681 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000014682 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000014683 */
14684void
14685xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014686 xmlSchemaValidityErrorFunc err,
14687 xmlSchemaValidityWarningFunc warn, void *ctx)
14688{
Daniel Veillard4255d502002-04-16 15:50:10 +000014689 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014690 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000014691 ctxt->error = err;
14692 ctxt->warning = warn;
14693 ctxt->userData = ctx;
14694}
14695
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014696/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000014697 * xmlSchemaGetParserErrors:
14698 * @ctxt: a XMl-Schema parser context
14699 * @err: the error callback result
14700 * @warn: the warning callback result
14701 * @ctx: contextual data for the callbacks result
14702 *
14703 * Get the callback information used to handle errors for a parser context
14704 *
14705 * Returns -1 in case of failure, 0 otherwise
14706 */
14707int
14708xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
14709 xmlSchemaValidityErrorFunc * err,
14710 xmlSchemaValidityWarningFunc * warn, void **ctx)
14711{
14712 if (ctxt == NULL)
14713 return(-1);
14714 if (err != NULL)
14715 *err = ctxt->error;
14716 if (warn != NULL)
14717 *warn = ctxt->warning;
14718 if (ctx != NULL)
14719 *ctx = ctxt->userData;
14720 return(0);
14721}
14722
14723/**
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014724 * xmlSchemaFacetTypeToString:
14725 * @type: the facet type
14726 *
14727 * Convert the xmlSchemaTypeType to a char string.
14728 *
14729 * Returns the char string representation of the facet type if the
14730 * type is a facet and an "Internal Error" string otherwise.
14731 */
14732static const char *
14733xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
14734{
14735 switch (type) {
14736 case XML_SCHEMA_FACET_PATTERN:
14737 return ("pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014738 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014739 return ("maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014740 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014741 return ("maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014742 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014743 return ("minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014744 case XML_SCHEMA_FACET_MININCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014745 return ("minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014746 case XML_SCHEMA_FACET_WHITESPACE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014747 return ("whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014748 case XML_SCHEMA_FACET_ENUMERATION:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014749 return ("enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014750 case XML_SCHEMA_FACET_LENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014751 return ("length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014752 case XML_SCHEMA_FACET_MAXLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014753 return ("maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014754 case XML_SCHEMA_FACET_MINLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014755 return ("minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014756 case XML_SCHEMA_FACET_TOTALDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014757 return ("totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014758 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014759 return ("fractionDigits");
14760 default:
14761 break;
14762 }
14763 return ("Internal Error");
14764}
14765
Daniel Veillardc0826a72004-08-10 14:17:33 +000014766
Daniel Veillardc0826a72004-08-10 14:17:33 +000014767
14768static int
14769xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
14770{
14771 xmlSchemaTypePtr anc;
14772
14773 /*
14774 * The normalization type can be changed only for types which are derived
14775 * from xsd:string.
14776 */
14777 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000014778 if (type->builtInType == XML_SCHEMAS_STRING)
Daniel Veillardc0826a72004-08-10 14:17:33 +000014779 return(XML_SCHEMAS_VAL_WTSP_PRESERVE);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000014780 else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
14781 return(XML_SCHEMAS_VAL_WTSP_REPLACE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014782 else {
14783 /*
14784 * For all ·atomic· datatypes other than string (and types ·derived·
14785 * by ·restriction· from it) the value of whiteSpace is fixed to
14786 * collapse
14787 */
14788 return(XML_SCHEMAS_VAL_WTSP_COLLAPSE);
14789 }
14790 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
14791 /*
14792 * For list types the facet "whiteSpace" is fixed to "collapse".
14793 */
14794 return (XML_SCHEMAS_VAL_WTSP_COLLAPSE);
14795 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
14796 return (-1);
14797 } else if (type->facetSet != NULL) {
14798 xmlSchemaTypePtr anyST;
14799 xmlSchemaFacetLinkPtr lin;
14800
14801 /*
14802 * Atomic types.
14803 */
14804 anyST = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
14805 anc = type->baseType;
14806 do {
14807 /*
14808 * For all ·atomic· datatypes other than string (and types ·derived·
14809 * by ·restriction· from it) the value of whiteSpace is fixed to
14810 * collapse
14811 */
14812 if ((anc->type == XML_SCHEMA_TYPE_BASIC) &&
14813 (anc->builtInType == XML_SCHEMAS_STRING)) {
14814
14815 lin = type->facetSet;
14816 do {
14817 if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
14818 if (lin->facet->whitespace ==
14819 XML_SCHEMAS_FACET_COLLAPSE) {
14820 return(XML_SCHEMAS_VAL_WTSP_COLLAPSE);
14821 } else if (lin->facet->whitespace ==
14822 XML_SCHEMAS_FACET_REPLACE) {
14823 return(XML_SCHEMAS_VAL_WTSP_REPLACE);
14824 } else
14825 return(XML_SCHEMAS_VAL_WTSP_PRESERVE);
14826 break;
14827 }
14828 lin = lin->next;
14829 } while (lin != NULL);
14830 break;
14831 }
14832 anc = anc->baseType;
14833 } while (anc != anyST);
14834 return (XML_SCHEMAS_VAL_WTSP_COLLAPSE);
14835 }
14836 return (-1);
14837}
14838
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014839/**
Daniel Veillard377e1a92004-04-16 16:30:05 +000014840 * xmlSchemaValidateFacetsInternal:
14841 * @ctxt: a schema validation context
Daniel Veillardc0826a72004-08-10 14:17:33 +000014842 * @type: the type holding the facets
Daniel Veillard377e1a92004-04-16 16:30:05 +000014843 * @facets: the list of facets to check
14844 * @value: the lexical repr of the value to validate
14845 * @val: the precomputed value
William M. Bracke7091952004-05-11 15:09:58 +000014846 * @fireErrors: if 0, only internal errors will be fired;
14847 * otherwise all errors will be fired.
Daniel Veillard377e1a92004-04-16 16:30:05 +000014848 *
14849 * Check a value against all facet conditions
14850 *
14851 * Returns 0 if the element is schemas valid, a positive error code
14852 * number otherwise and -1 in case of internal or API error.
14853 */
14854static int
14855xmlSchemaValidateFacetsInternal(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014856 xmlSchemaTypePtr type,
14857 const xmlChar * value,
14858 unsigned long length,
14859 int fireErrors)
Daniel Veillard377e1a92004-04-16 16:30:05 +000014860{
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014861 int ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014862 xmlNodePtr node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014863 xmlSchemaTypePtr biType; /* The build-in type. */
14864 xmlSchemaTypePtr tmpType;
14865 xmlSchemaFacetLinkPtr facetLink;
Daniel Veillardc7e3cc42004-09-28 12:33:52 +000014866 int retFacet;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014867 xmlSchemaFacetPtr facet;
14868 unsigned long len = 0;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014869
Daniel Veillardc0826a72004-08-10 14:17:33 +000014870#ifdef DEBUG_UNION_VALIDATION
14871 printf("Facets of type: '%s'\n", (const char *) type->name);
14872 printf(" fireErrors: %d\n", fireErrors);
14873#endif
14874
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014875 node = ctxt->node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014876 /*
14877 * NOTE: Do not jump away, if the facetSet of the given type is
14878 * empty: until now, "pattern" facets of the *base types* need to
14879 * be checked as well.
14880 */
14881 biType = type->baseType;
14882 while ((biType != NULL) && (biType->type != XML_SCHEMA_TYPE_BASIC))
14883 biType = biType->baseType;
14884 if (biType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014885 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014886 "Internal error: xmlSchemaValidateFacetsInternal, "
14887 "the base type axis of the given type '%s' does not resolve to "
14888 "a built-in type.\n",
14889 type->name, NULL);
14890 return (-1);
14891 }
14892
14893 if (type->facetSet != NULL) {
14894 facetLink = type->facetSet;
14895 while (facetLink != NULL) {
14896 facet = facetLink->facet;
14897 /*
14898 * Skip the pattern "whiteSpace": it is used to
14899 * format the character content beforehand.
14900 */
14901 switch (facet->type) {
14902 case XML_SCHEMA_FACET_WHITESPACE:
14903 case XML_SCHEMA_FACET_PATTERN:
14904 case XML_SCHEMA_FACET_ENUMERATION:
14905 break;
14906 case XML_SCHEMA_FACET_LENGTH:
14907 case XML_SCHEMA_FACET_MINLENGTH:
14908 case XML_SCHEMA_FACET_MAXLENGTH:
14909 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
14910 ret = xmlSchemaValidateListSimpleTypeFacet(facet,
14911 value, length, 0);
14912 len = length;
14913 } else
14914 ret = xmlSchemaValidateLengthFacet(biType, facet,
14915 value, ctxt->value, &len);
14916 break;
14917 default:
14918 ret = xmlSchemaValidateFacet(biType, facet, value,
14919 ctxt->value);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014920 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000014921 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014922 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014923 "Internal error: xmlSchemaValidateFacetsInternal, "
14924 "validating facet of type '%s'.\n",
14925 type->name, NULL);
14926 break;
14927 } else if ((ret > 0) && (fireErrors)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014928 xmlSchemaVFacetErr(ctxt, ret, node, value, len,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014929 type, facet, NULL, NULL, NULL, NULL);
14930 }
14931
14932 facetLink = facetLink->next;
14933 }
14934 if (ret >= 0) {
14935 /*
14936 * Process enumerations.
14937 */
14938 retFacet = 0;
14939 facetLink = type->facetSet;
14940 while (facetLink != NULL) {
14941 if (facetLink->facet->type == XML_SCHEMA_FACET_ENUMERATION) {
14942 retFacet = xmlSchemaValidateFacet(biType, facetLink->facet,
14943 value, ctxt->value);
14944 if (retFacet <= 0)
14945 break;
14946 }
14947 facetLink = facetLink->next;
14948 }
14949 if (retFacet > 0) {
14950 ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
14951 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014952 xmlSchemaVFacetErr(ctxt, ret, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014953 value, 0, type, NULL, NULL, NULL, NULL, NULL);
14954 } else if (retFacet < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014955 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014956 "Internal error: xmlSchemaValidateFacetsInternal, "
14957 "validating facet of type '%s'.\n",
14958 BAD_CAST "enumeration", NULL);
14959 ret = -1;
14960 }
14961 }
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014962 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000014963 if (ret >= 0) {
14964 /*
14965 * Process patters. Pattern facets are ORed at type level
14966 * and ANDed if derived. Walk the base type axis.
14967 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000014968 tmpType = type;
14969 facet = NULL;
14970 do {
14971 retFacet = 0;
14972 for (facetLink = tmpType->facetSet; facetLink != NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014973 facetLink = facetLink->next) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014974 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
14975 continue;
14976 retFacet = xmlSchemaValidateFacet(biType, facetLink->facet,
14977 value, ctxt->value);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014978 if (retFacet == 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +000014979 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014980 else if (retFacet < 0) {
14981 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
14982 "Internal error: xmlSchemaValidateFacetsInternal, "
14983 "validating 'pattern' facet '%s' of type '%s'.\n",
14984 facetLink->facet->value, tmpType->name);
14985 ret = -1;
14986 break;
14987 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +000014988 /* Save the last non-validating facet. */
14989 facet = facetLink->facet;
14990 }
14991 if (retFacet != 0)
14992 break;
14993 tmpType = tmpType->baseType;
14994 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014995 if (retFacet > 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014996 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
14997 if (fireErrors) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014998 xmlSchemaVFacetErr(ctxt, ret, node, value, 0, type, facet,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014999 NULL, NULL, NULL, NULL);
15000 }
15001 }
15002 }
15003
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000015004 return (ret);
15005}
15006
Daniel Veillard4255d502002-04-16 15:50:10 +000015007/************************************************************************
15008 * *
15009 * Simple type validation *
15010 * *
15011 ************************************************************************/
Daniel Veillard377e1a92004-04-16 16:30:05 +000015012
Daniel Veillard4255d502002-04-16 15:50:10 +000015013
15014/************************************************************************
15015 * *
15016 * DOM Validation code *
15017 * *
15018 ************************************************************************/
15019
Daniel Veillard4255d502002-04-16 15:50:10 +000015020static int xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015021 xmlNodePtr elem,
Daniel Veillard3646d642004-06-02 19:19:14 +000015022 xmlSchemaTypePtr type);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015023static int xmlSchemaValidateElementByType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015024 xmlSchemaTypePtr type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000015025 int isNil,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015026 int valSimpleContent);
Daniel Veillard4255d502002-04-16 15:50:10 +000015027
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015028static void xmlSchemaBeginElement(xmlSchemaValidCtxtPtr vctxt);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000015029static int xmlSchemaEndElement(xmlSchemaValidCtxtPtr vctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015030
15031#ifdef ELEM_INFO_ENABLED
15032/**
15033 * xmlSchemaGetFreshElemInfo:
15034 * @vctxt: the schema validation context
15035 *
15036 * Creates/reuses and initializes the element info item for
15037 * the currect tree depth.
15038 *
15039 * Returns the element info item or NULL on API or internal errors.
15040 */
15041static xmlSchemaElemInfoPtr
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000015042xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt,
15043 int depth)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015044{
15045 xmlSchemaElemInfoPtr info = NULL;
15046
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000015047 if (depth > vctxt->sizeElemInfos) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015048 xmlSchemaVErr(vctxt, NULL, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000015049 "Internal error: xmlSchemaGetFreshElemInfo, "
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015050 "an inconsistent depth encountered.\n",
15051 NULL, NULL);
15052 return (NULL);
15053 }
15054 if (vctxt->elemInfos == NULL) {
15055 vctxt->elemInfos = (xmlSchemaElemInfoPtr *)
15056 xmlMalloc(10 * sizeof(xmlSchemaElemInfoPtr));
15057 if (vctxt->elemInfos == NULL) {
15058 xmlSchemaVErrMemory(vctxt,
15059 "allocating the element info array", NULL);
15060 return (NULL);
15061 }
15062 memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaElemInfoPtr));
15063 vctxt->sizeElemInfos = 10;
15064 } else if (vctxt->sizeElemInfos == vctxt->depth) {
15065 int i = vctxt->sizeElemInfos;
15066
15067 vctxt->sizeElemInfos *= 2;
15068 vctxt->elemInfos = (xmlSchemaElemInfoPtr *)
15069 xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
15070 sizeof(xmlSchemaElemInfoPtr));
15071 if (vctxt->elemInfos == NULL) {
15072 xmlSchemaVErrMemory(vctxt,
15073 "re-allocating the element info array", NULL);
15074 return (NULL);
15075 }
15076 /*
15077 * We need the new memory to be NULLed.
15078 * TODO: Use memset instead?
15079 */
15080 for (; i < vctxt->sizeElemInfos; i++)
15081 vctxt->elemInfos[i] = NULL;
15082 } else
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000015083 info = vctxt->elemInfos[depth];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015084
15085 if (info == NULL) {
15086 info = (xmlSchemaElemInfoPtr)
15087 xmlMalloc(sizeof(xmlSchemaElemInfo));
15088 if (info == NULL) {
15089 xmlSchemaVErrMemory(vctxt,
15090 "allocating an element info", NULL);
15091 return (NULL);
15092 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000015093 vctxt->elemInfos[depth] = info;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015094 }
15095 memset(info, 0, sizeof(xmlSchemaElemInfo));
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000015096 info->depth = depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015097
15098 return (info);
15099}
15100#endif /* ELEM_INFO_ENABLED */
15101
Daniel Veillard3646d642004-06-02 19:19:14 +000015102
15103/**
15104 * xmlSchemaFreeAttrStates:
15105 * @state: a list of attribute states
15106 *
15107 * Free the given list of attribute states
15108 *
15109 */
15110static void
15111xmlSchemaFreeAttributeStates(xmlSchemaAttrStatePtr state)
15112{
15113 xmlSchemaAttrStatePtr tmp;
15114 while (state != NULL) {
15115 tmp = state;
15116 state = state->next;
15117 xmlFree(tmp);
15118 }
15119}
15120
Daniel Veillard4255d502002-04-16 15:50:10 +000015121/**
15122 * xmlSchemaRegisterAttributes:
15123 * @ctxt: a schema validation context
15124 * @attrs: a list of attributes
15125 *
15126 * Register the list of attributes as the set to be validated on that element
15127 *
15128 * Returns -1 in case of error, 0 otherwise
15129 */
15130static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015131xmlSchemaRegisterAttributes(xmlSchemaValidCtxtPtr ctxt, xmlAttrPtr attrs)
15132{
Daniel Veillard3646d642004-06-02 19:19:14 +000015133 xmlSchemaAttrStatePtr tmp;
15134
15135 ctxt->attr = NULL;
15136 ctxt->attrTop = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000015137 while (attrs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015138 if ((attrs->ns != NULL) &&
15139 (xmlStrEqual(attrs->ns->href, xmlSchemaInstanceNs))) {
15140 attrs = attrs->next;
15141 continue;
15142 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000015143 tmp = (xmlSchemaAttrStatePtr)
15144 xmlMalloc(sizeof(xmlSchemaAttrState));
15145 if (tmp == NULL) {
15146 xmlSchemaVErrMemory(ctxt, "registering attributes", NULL);
15147 return (-1);
15148 }
Daniel Veillard3646d642004-06-02 19:19:14 +000015149 tmp->attr = attrs;
15150 tmp->state = XML_SCHEMAS_ATTR_UNKNOWN;
15151 tmp->next = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015152 tmp->decl = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000015153 if (ctxt->attr == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015154 ctxt->attr = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000015155 else
15156 ctxt->attrTop->next = tmp;
15157 ctxt->attrTop = tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015158 attrs = attrs->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000015159 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015160 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000015161}
15162
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015163#if 0 /* Currently not used */
Daniel Veillard4255d502002-04-16 15:50:10 +000015164/**
Daniel Veillard4255d502002-04-16 15:50:10 +000015165 * xmlSchemaValidateCheckNodeList
15166 * @nodelist: the list of nodes
15167 *
15168 * Check the node list is only made of text nodes and entities pointing
15169 * to text nodes
15170 *
15171 * Returns 1 if true, 0 if false and -1 in case of error
15172 */
15173static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015174xmlSchemaValidateCheckNodeList(xmlNodePtr nodelist)
15175{
Daniel Veillard4255d502002-04-16 15:50:10 +000015176 while (nodelist != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015177 if (nodelist->type == XML_ENTITY_REF_NODE) {
15178 TODO /* implement recursion in the entity content */
15179 }
15180 if ((nodelist->type != XML_TEXT_NODE) &&
15181 (nodelist->type != XML_COMMENT_NODE) &&
15182 (nodelist->type != XML_PI_NODE) &&
William M. Bracke7091952004-05-11 15:09:58 +000015183 (nodelist->type != XML_CDATA_SECTION_NODE)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015184 return (0);
15185 }
15186 nodelist = nodelist->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000015187 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015188 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +000015189}
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015190#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000015191
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015192static void
15193xmlSchemaPostSchemaAssembleFixup(xmlSchemaParserCtxtPtr ctxt)
15194{
15195 int i, nbItems;
15196 xmlSchemaTypePtr item, *items;
15197
15198
15199 /*
15200 * During the Assemble of the schema ctxt->curItems has
15201 * been filled with the relevant new items. Fix those up.
15202 */
15203 nbItems = ctxt->assemble->nbItems;
15204 items = (xmlSchemaTypePtr *) ctxt->assemble->items;
15205
15206 for (i = 0; i < nbItems; i++) {
15207 item = items[i];
15208 switch (item->type) {
15209 case XML_SCHEMA_TYPE_ATTRIBUTE:
15210 xmlSchemaAttrFixup((xmlSchemaAttributePtr) item, ctxt, NULL);
15211 break;
15212 case XML_SCHEMA_TYPE_ELEMENT:
15213 xmlSchemaRefFixupCallback((xmlSchemaElementPtr) item, ctxt,
15214 NULL, NULL, NULL);
15215 break;
15216 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
15217 xmlSchemaAttrGrpFixup((xmlSchemaAttributeGroupPtr) item,
15218 ctxt, NULL);
15219 break;
15220 case XML_SCHEMA_TYPE_GROUP:
15221 xmlSchemaGroupDefFixup(item, ctxt, NULL);
15222 default:
15223 break;
15224 }
15225 }
15226 /*
15227 * Circularity checks.
15228 */
15229 for (i = 0; i < nbItems; i++) {
15230 item = items[i];
15231 switch (item->type) {
15232 case XML_SCHEMA_TYPE_GROUP:
15233 xmlSchemaCheckGroupDefCircular(item, ctxt, NULL);
15234 break;
15235 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
15236 xmlSchemaCheckAttributeGroupCircular(
15237 (xmlSchemaAttributeGroupPtr) item, ctxt, NULL);
15238 break;
15239 default:
15240 break;
15241 }
15242 }
15243 /*
15244 * Fixup for all other item.
15245 * TODO: Hmm, not sure if starting from complex/simple types,
15246 * all subsequent items will be reached.
15247 */
15248 for (i = 0; i < nbItems; i++) {
15249 item = items[i];
15250 switch (item->type) {
15251 case XML_SCHEMA_TYPE_SIMPLE:
15252 case XML_SCHEMA_TYPE_COMPLEX:
15253 xmlSchemaTypeFixup(item, ctxt, NULL);
15254 break;
15255 default:
15256 break;
15257 }
15258 }
15259 /*
15260 * Check facet values. Note that facets are
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000015261 * hold by simple type components only (and
15262 * by complex types in the current implementation).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015263 */
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000015264 /* OLD:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015265 for (i = 0; i < nbItems; i++) {
15266 item = items[i];
15267 switch (item->type) {
15268 case XML_SCHEMA_TYPE_SIMPLE:
15269 case XML_SCHEMA_TYPE_COMPLEX:
15270 xmlSchemaCheckDefaults(item, ctxt, NULL);
15271 break;
15272 default:
15273 break;
15274 }
15275 }
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000015276 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015277 /*
15278 * Build the content model for complex types.
15279 */
15280 for (i = 0; i < nbItems; i++) {
15281 item = items[i];
15282 switch (item->type) {
15283 case XML_SCHEMA_TYPE_COMPLEX:
15284 xmlSchemaBuildContentModel(item, ctxt, NULL);
15285 break;
15286 default:
15287 break;
15288 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015289 }
15290 /*
15291 * Validate value contraint values.
15292 */
15293 for (i = 0; i < nbItems; i++) {
15294 item = items[i];
15295 switch (item->type) {
15296 case XML_SCHEMA_TYPE_ATTRIBUTE:
15297 xmlSchemaCheckAttrValConstr((xmlSchemaAttributePtr) item, ctxt, NULL);
15298 break;
15299 case XML_SCHEMA_TYPE_ELEMENT:
15300 xmlSchemaCheckElemValConstr((xmlSchemaElementPtr) item, ctxt, NULL);
15301 break;
15302 default:
15303 break;
15304 }
15305 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015306}
15307
15308/**
15309 * xmlSchemaAssembleByLocation:
15310 * @pctxt: a schema parser context
15311 * @vctxt: a schema validation context
15312 * @schema: the existing schema
15313 * @node: the node that fired the assembling
15314 * @nsName: the namespace name of the new schema
15315 * @location: the location of the schema
15316 *
15317 * Expands an existing schema by an additional schema.
15318 *
15319 * Returns 0 if the new schema is correct, a positive error code
15320 * number otherwise and -1 in case of an internal or API error.
15321 */
15322static int
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015323xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
15324 xmlSchemaPtr schema,
15325 xmlNodePtr node,
15326 const xmlChar *nsName,
15327 const xmlChar *location)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015328{
15329 const xmlChar *targetNs, *oldtns;
15330 xmlDocPtr doc, olddoc;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015331 int oldflags, ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015332 xmlNodePtr docElem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015333 xmlSchemaParserCtxtPtr pctxt;
15334
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015335 /*
15336 * This should be used:
15337 * 1. on <import>(s)
15338 * 2. if requested by the validated instance
15339 * 3. if requested via the API
15340 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015341 if ((vctxt == NULL) || (schema == NULL))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015342 return (-1);
15343 /*
15344 * Create a temporary parser context.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015345 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015346 if ((vctxt->pctxt == NULL) &&
15347 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1)) {
15348 xmlSchemaVErr(vctxt, node,
15349 XML_SCHEMAV_INTERNAL,
15350 "Internal error: xmlSchemaAssembleByLocation, "
15351 "failed to create a temp. parser context.\n",
15352 NULL, NULL);
15353 return (-1);
15354 }
15355 pctxt = vctxt->pctxt;
15356 /*
15357 * Set the counter to produce unique names for anonymous items.
15358 */
15359 pctxt->counter = schema->counter;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015360 /*
15361 * Acquire the schema document.
15362 */
15363 ret = xmlSchemaAcquireSchemaDoc(pctxt, schema, node,
15364 nsName, location, &doc, &targetNs, 0);
15365 if (ret != 0) {
15366 if (doc != NULL)
15367 xmlFreeDoc(doc);
15368 } else if (doc != NULL) {
15369 docElem = xmlDocGetRootElement(doc);
15370 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015371 * Create new assemble info.
15372 */
15373 if (pctxt->assemble == NULL) {
15374 pctxt->assemble = xmlSchemaNewAssemble();
15375 if (pctxt->assemble == NULL) {
15376 xmlSchemaVErrMemory(vctxt,
15377 "Memory error: xmlSchemaAssembleByLocation, "
15378 "allocating assemble info", NULL);
15379 xmlFreeDoc(doc);
15380 return (-1);
15381 }
15382 }
15383 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015384 * Save and reset the context & schema.
15385 */
15386 oldflags = schema->flags;
15387 oldtns = schema->targetNamespace;
15388 olddoc = schema->doc;
15389
15390 xmlSchemaClearSchemaDefaults(schema);
15391 schema->targetNamespace = targetNs;
15392 /* schema->nbCurItems = 0; */
15393 pctxt->schema = schema;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015394 pctxt->ctxtType = NULL;
15395 pctxt->parentItem = NULL;
15396
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015397 xmlSchemaParseSchemaDefaults(pctxt, schema, docElem);
15398 xmlSchemaParseSchemaTopLevel(pctxt, schema, docElem->children);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015399 xmlSchemaPostSchemaAssembleFixup(pctxt);
15400 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015401 * Set the counter of items.
15402 */
15403 schema->counter = pctxt->counter;
15404 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015405 * Free the list of assembled components.
15406 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015407 pctxt->assemble->nbItems = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015408 /*
15409 * Restore the context & schema.
15410 */
15411 schema->flags = oldflags;
15412 schema->targetNamespace = oldtns;
15413 schema->doc = olddoc;
15414 ret = pctxt->err;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015415 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015416 return (ret);
15417}
15418
15419/**
15420 * xmlSchemaAssembleByXSIAttr:
15421 * @vctxt: a schema validation context
15422 * @xsiAttr: an xsi attribute
15423 * @noNamespace: whether a schema with no target namespace is exptected
15424 *
15425 * Expands an existing schema by an additional schema using
15426 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
15427 * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
15428 * must be set to 1.
15429 *
15430 * Returns 0 if the new schema is correct, a positive error code
15431 * number otherwise and -1 in case of an internal or API error.
15432 */
15433static int
15434xmlSchemaAssembleByXSIAttr(xmlSchemaValidCtxtPtr vctxt,
15435 xmlAttrPtr xsiAttr,
15436 int noNamespace)
15437{
15438 xmlChar *value;
15439 const xmlChar *cur, *end;
15440 const xmlChar *nsname = NULL, *location;
15441 int count = 0;
15442 int ret = 0;
15443
15444 if (xsiAttr == NULL) {
15445 xmlSchemaVCustomErr(vctxt, XML_SCHEMAV_INTERNAL,
15446 NULL, NULL,
15447 "Internal error: xmlSchemaAssembleByXSIAttr, "
15448 "bad arguments", NULL);
15449 return (-1);
15450 }
15451 /*
15452 * Parse the value; we will assume an even number of values
15453 * to be given (this is how Xerces and XSV work).
15454 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015455 value = xmlNodeGetContent((xmlNodePtr) xsiAttr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015456 cur = value;
15457 do {
15458 if (noNamespace != 1) {
15459 /*
15460 * Get the namespace name.
15461 */
15462 while (IS_BLANK_CH(*cur))
15463 cur++;
15464 end = cur;
15465 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
15466 end++;
15467 if (end == cur)
15468 break;
15469 count++;
15470 nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
15471 cur = end;
15472 }
15473 /*
15474 * Get the URI.
15475 */
15476 while (IS_BLANK_CH(*cur))
15477 cur++;
15478 end = cur;
15479 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
15480 end++;
15481 if (end == cur)
15482 break;
15483 count++;
15484 location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015485 cur = end;
15486 ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015487 xsiAttr->parent, nsname, location);
15488 if (ret == -1) {
15489 xmlSchemaVCustomErr(vctxt,
15490 XML_SCHEMAV_INTERNAL,
15491 (xmlNodePtr) xsiAttr, NULL,
15492 "Internal error: xmlSchemaAssembleByXSIAttr, "
15493 "assembling schemata", NULL);
15494 if (value != NULL)
15495 xmlFree(value);
15496 return (-1);
15497 }
15498 } while (*cur != 0);
15499 if (value != NULL)
15500 xmlFree(value);
15501 return (ret);
15502}
15503
15504/**
15505 * xmlSchemaAssembleByXSIElem:
15506 * @vctxt: a schema validation context
15507 * @elem: an element node possibly holding xsi attributes
15508 * @noNamespace: whether a schema with no target namespace is exptected
15509 *
15510 * Assembles an existing schema by an additional schema using
15511 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attributes
15512 * of the given @elem.
15513 *
15514 * Returns 0 if the new schema is correct, a positive error code
15515 * number otherwise and -1 in case of an internal or API error.
15516 */
15517static int
15518xmlSchemaAssembleByXSIElem(xmlSchemaValidCtxtPtr vctxt,
15519 xmlNodePtr elem)
15520{
15521 int ret = 0, retNs = 0;
15522 xmlAttrPtr attr;
15523
15524 attr = xmlHasNsProp(elem, BAD_CAST "schemaLocation", xmlSchemaInstanceNs);
15525 if (attr != NULL) {
15526 retNs = xmlSchemaAssembleByXSIAttr(vctxt, attr, 0);
15527 if (retNs == -1)
15528 return (-1);
15529 }
15530 attr = xmlHasNsProp(elem, BAD_CAST "noNamespaceSchemaLocation", xmlSchemaInstanceNs);
15531 if (attr != NULL) {
15532 ret = xmlSchemaAssembleByXSIAttr(vctxt, attr, 1);
15533 if (ret == -1)
15534 return (-1);
15535 }
15536 if (retNs != 0)
15537 return (retNs);
15538 else
15539 return (ret);
15540}
15541
Daniel Veillard4255d502002-04-16 15:50:10 +000015542/**
Daniel Veillard4255d502002-04-16 15:50:10 +000015543 * xmlSchemaValidateCallback:
15544 * @ctxt: a schema validation context
15545 * @name: the name of the element detected (might be NULL)
15546 * @type: the type
15547 *
15548 * A transition has been made in the automata associated to an element
15549 * content model
15550 */
15551static void
15552xmlSchemaValidateCallback(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015553 const xmlChar * name ATTRIBUTE_UNUSED,
15554 xmlSchemaTypePtr type, xmlNodePtr node)
15555{
Daniel Veillard4255d502002-04-16 15:50:10 +000015556 xmlSchemaTypePtr oldtype = ctxt->type;
15557 xmlNodePtr oldnode = ctxt->node;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015558
Daniel Veillard4255d502002-04-16 15:50:10 +000015559#ifdef DEBUG_CONTENT
Daniel Veillard8651f532002-04-17 09:06:27 +000015560 xmlGenericError(xmlGenericErrorContext,
15561 "xmlSchemaValidateCallback: %s, %s, %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015562 name, type->name, node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +000015563#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015564 /*
15565 * @type->type will be XML_SCHEMA_TYPE_ANY or XML_SCHEMA_TYPE_ELEMENT.
15566 */
Daniel Veillard4255d502002-04-16 15:50:10 +000015567 ctxt->type = type;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015568 ctxt->node = node;
15569 ctxt->cur = node->children;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015570
15571#ifdef ELEM_INFO_ENABLED
15572 xmlSchemaBeginElement(ctxt);
15573#endif
15574
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015575 /*
15576 * Assemble new schemata using xsi.
15577 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015578 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015579 int ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015580
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015581 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
15582 if (ret == -1) {
15583 xmlSchemaVCustomErr(ctxt,
15584 XML_SCHEMAV_INTERNAL,
15585 ctxt->node, NULL,
15586 "Internal error: xmlSchemaValidateElement, "
15587 "assembling schema by xsi", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015588 goto leave;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015589 }
15590 /*
15591 * NOTE: We won't react on schema parser errors here.
15592 * TODO: But a warning would be nice.
15593 */
15594 }
15595 switch (type->type) {
15596 case XML_SCHEMA_TYPE_ELEMENT: {
15597 /*
15598 * NOTE: The build of the content model
15599 * (xmlSchemaBuildAContentModel) ensures that the element
15600 * declaration (and not a reference to it) will be given.
15601 */
15602 if (((xmlSchemaElementPtr) ctxt->type)->ref != NULL) {
15603 /*
15604 * This is paranoid coding ;-)... it should not
15605 * happen here any more.
15606 */
15607 xmlSchemaVCustomErr(ctxt,
15608 XML_SCHEMAV_INTERNAL,
15609 node, NULL,
15610 "Internal error: xmlSchemaValidateCallback, "
15611 "element declaration 'reference' encountered, "
15612 "but an element declaration was expected",
15613 NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015614 goto leave;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015615 }
15616 xmlSchemaValidateElementByDeclaration(ctxt,
15617 (xmlSchemaElementPtr) type);
15618 break;
15619 }
15620 case XML_SCHEMA_TYPE_ANY:
15621 xmlSchemaValidateElementByWildcard(ctxt, type);
15622 break;
15623 default:
15624 break;
15625 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015626leave:
15627
15628#ifdef ELEM_INFO_ENABLED
15629 xmlSchemaEndElement(ctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015630#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000015631 ctxt->type = oldtype;
15632 ctxt->node = oldnode;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015633}
Daniel Veillard4255d502002-04-16 15:50:10 +000015634
Daniel Veillard01fa6152004-06-29 17:04:39 +000015635/**
15636 * xmlSchemaValidateSimpleTypeValue:
15637 * @ctxt: a schema validation context
15638 * @value: the value to be validated
15639 * @fireErrors: shall errors be reported?
15640 * @applyFacets: shall facets be applied?
Daniel Veillardc0826a72004-08-10 14:17:33 +000015641 * @normalize: shall the value be normalized?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015642 * @checkNodes: shall the content nodes be checked?
Daniel Veillard01fa6152004-06-29 17:04:39 +000015643 *
15644 * Validates a value by the given type (user derived or built-in).
15645 *
15646 * Returns 0 if the value is valid, a positive error code
15647 * number otherwise and -1 in case of an internal or API error.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015648 */
15649static int
15650xmlSchemaValidateSimpleTypeValue(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015651 xmlSchemaTypePtr type,
15652 const xmlChar *value,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015653 int fireErrors,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015654 int applyFacets,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015655 int normalize,
15656 int checkNodes)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015657{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015658 xmlNodePtr node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015659 int ret = 0;
15660 xmlChar *normValue = NULL;
15661 int wtsp;
15662
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015663 node = ctxt->node;
15664 /* Save the current whitespace normalization type. */
Daniel Veillardc0826a72004-08-10 14:17:33 +000015665 wtsp = ctxt->valueWS;
15666 /*
15667 * Normalize the value.
15668 */
15669 if (normalize &&
15670 (ctxt->valueWS != XML_SCHEMAS_VAL_WTSP_COLLAPSE)) {
15671 int norm = xmlSchemaGetWhiteSpaceFacetValue(type);
15672
15673 if ((norm != -1) && (norm > ctxt->valueWS)) {
15674 if (norm == XML_SCHEMAS_VAL_WTSP_COLLAPSE)
15675 normValue = xmlSchemaCollapseString(value);
15676 else
15677 normValue = xmlSchemaWhiteSpaceReplace(value);
15678 ctxt->valueWS = norm;
15679 if (normValue != NULL)
15680 value = (const xmlChar *) normValue;
15681 }
15682 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015683 /*
15684 * The nodes of a content must be checked only once,
15685 * this is not working since list types will fire this
15686 * multiple times.
15687 */
15688 if ((checkNodes == 1) && (ctxt->cur != NULL)) {
15689 xmlNodePtr cur = ctxt->cur;
15690
15691 do {
15692 switch (cur->type) {
15693 case XML_TEXT_NODE:
15694 case XML_CDATA_SECTION_NODE:
15695 case XML_PI_NODE:
15696 case XML_COMMENT_NODE:
15697 case XML_XINCLUDE_START:
15698 case XML_XINCLUDE_END:
15699 break;
15700 case XML_ENTITY_REF_NODE:
15701 case XML_ENTITY_NODE:
15702 /* TODO: Scour the entities for illegal nodes. */
15703 TODO break;
15704 case XML_ELEMENT_NODE: {
15705 /* NOTE: Changed to an internal error, since the
15706 * existence of an element node will be already checked in
15707 * xmlSchemaValidateElementBySimpleType and in
15708 * xmlSchemaValidateElementByComplexType.
15709 */
15710 xmlSchemaVCustomErr(ctxt,
15711 XML_SCHEMAV_INTERNAL,
15712 /* XML_SCHEMAS_ERR_INVALIDELEM, */
15713 node, type,
15714 "Element '%s' found in simple type content",
15715 cur->name);
15716 return (XML_SCHEMAV_INTERNAL);
15717 }
15718 case XML_ATTRIBUTE_NODE:
15719 case XML_DOCUMENT_NODE:
15720 case XML_DOCUMENT_TYPE_NODE:
15721 case XML_DOCUMENT_FRAG_NODE:
15722 case XML_NOTATION_NODE:
15723 case XML_HTML_DOCUMENT_NODE:
15724 case XML_DTD_NODE:
15725 case XML_ELEMENT_DECL:
15726 case XML_ATTRIBUTE_DECL:
15727 case XML_ENTITY_DECL:
15728 case XML_NAMESPACE_DECL:
15729#ifdef LIBXML_DOCB_ENABLED
15730 case XML_DOCB_DOCUMENT_NODE:
15731#endif
15732 xmlSchemaVCustomErr(ctxt,
15733 XML_SCHEMAV_INTERNAL,
15734 /* XML_SCHEMAS_ERR_INVALIDELEM, */
15735 node, NULL,
15736 "Node of unexpected type found in simple type content",
15737 NULL);
15738 return (XML_SCHEMAV_INTERNAL);
15739 }
15740 cur = cur->next;
15741 } while (cur != NULL);
15742 }
15743
William M. Brack2f2a6632004-08-20 23:09:47 +000015744 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
15745 xmlSchemaTypePtr base, anyType;
15746
15747 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
15748
15749 base = type->baseType;
15750 while ((base != NULL) &&
15751 (base->type != XML_SCHEMA_TYPE_SIMPLE) &&
15752 (base->type != XML_SCHEMA_TYPE_BASIC) &&
15753 (base != anyType)) {
15754 base = base->baseType;
15755 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015756 ret = xmlSchemaValidateSimpleTypeValue(ctxt, base, value, 1, 0, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000015757 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015758 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000015759 "Internal error: xmlSchemaValidateSimpleTypeValue, "
15760 "validating complex type '%s'\n",
15761 type->name, NULL);
15762 } else if ((ret == 0) && (applyFacets) && (type->facetSet != NULL)) {
15763 /*
15764 * Check facets.
15765 */
15766 /*
15767 * This is somehow not nice, since if an error occurs
15768 * the reported type will be the complex type; the spec
15769 * wants a simple type to be created on the complex type
15770 * if it has a simple content. For now we have to live with
15771 * it.
15772 */
15773 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
15774 value, 0, fireErrors);
15775 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015776 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000015777 "Internal error: xmlSchemaValidateSimpleTypeValue, "
15778 "validating facets of complex type '%s'\n",
15779 type->name, NULL);
15780 } else if (ret > 0) {
15781 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
William M. Brack2f2a6632004-08-20 23:09:47 +000015782 if (fireErrors)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015783 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
William M. Brack2f2a6632004-08-20 23:09:47 +000015784 }
15785 }
15786 } else if (type->type == XML_SCHEMA_TYPE_BASIC) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015787
15788 if (ctxt->value != NULL) {
15789 xmlSchemaFreeValue(ctxt->value);
15790 ctxt->value = NULL;
15791 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015792 /*
15793 * STREAM-READ-CHILDREN.
15794 */
15795 ret = xmlSchemaValPredefTypeNodeNoNorm(type, value, &(ctxt->value), node);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015796 if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015797 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
15798 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
15799 else
15800 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015801 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015802 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015803 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015804 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015805 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000015806 "validating built-in type '%s'\n", type->name, NULL);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000015807 } else if ((ctxt->value == NULL) &&
15808 (type->builtInType == XML_SCHEMAS_STRING) &&
15809 (ctxt->nodeInfo != NULL) &&
15810 (ctxt->nodeInfo->flags & XML_SCHEMA_ELEM_INFO_VALUE_NEEDED)) {
15811#ifdef IDC_VALUE_SUPPORT
15812 xmlChar *valdup;
15813 /*
15814 * Create a precomputed string value for "string" as well if
15815 * requested.
15816 */
15817 valdup = xmlStrdup(value);
15818 ctxt->value = xmlSchemaNewStringValue(XML_SCHEMAS_STRING,
15819 BAD_CAST valdup);
15820 if ((valdup != NULL) && (ctxt->value == NULL))
15821 xmlFree(valdup);
15822#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +000015823 }
15824 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
15825 /* 1.2.1 if {variety} is ·atomic· then the string must ·match·
15826 * a literal in the ·lexical space· of {base type definition}
15827 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015828 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type->baseType, value, 0, 0, 0, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015829 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015830 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015831 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000015832 "validating atomic simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000015833 type->name, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015834 } else if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015835 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015836 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015837 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015838 } else if ((applyFacets) && (type->facetSet != NULL)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015839 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000015840 * Check facets.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015841 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000015842 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
15843 value, 0, fireErrors);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015844 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015845 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015846 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000015847 "validating facets of atomic simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000015848 type->name, NULL);
15849 } else if (ret > 0) {
15850 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015851 /*
15852 Disabled, since the facet validation already reports errors.
15853 if (fireErrors)
15854 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
15855 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015856 }
15857 }
15858 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
15859
15860 xmlSchemaTypePtr tmpType;
15861 const xmlChar *cur, *end;
15862 xmlChar *tmp;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015863 unsigned long len = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015864
15865 /* 1.2.2 if {variety} is ·list· then the string must be a sequence
15866 * of white space separated tokens, each of which ·match·es a literal
15867 * in the ·lexical space· of {item type definition}
15868 */
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +000015869
Kasimier T. Buchcikde938cd2005-01-13 12:25:57 +000015870 if (value == NULL)
15871 value = BAD_CAST "";
Daniel Veillardc0826a72004-08-10 14:17:33 +000015872 tmpType = xmlSchemaGetListSimpleTypeItemType(type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015873 cur = value;
15874 do {
15875 while (IS_BLANK_CH(*cur))
15876 cur++;
15877 end = cur;
15878 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
15879 end++;
15880 if (end == cur)
15881 break;
15882 tmp = xmlStrndup(cur, end - cur);
15883 len++;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015884 ret = xmlSchemaValidateSimpleTypeValue(ctxt, tmpType, tmp, 0, 1, 0, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015885 xmlFree(tmp);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015886 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015887 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015888 "Internal error: xmlSchemaValidateSimpleTypeValue, "
15889 "validating an item of list simple type '%s'\n",
15890 type->name, NULL);
15891 break;
15892 } else if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015893 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015894 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015895 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015896 break;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015897 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015898 cur = end;
15899 } while (*cur != 0);
15900 /*
15901 * Check facets.
15902 */
15903 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015904 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015905 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000015906 "validating list simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000015907 type->name, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015908 } else if ((ret == 0) && (applyFacets)) {
15909 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
15910 value, len, fireErrors);
15911 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015912 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015913 "Internal error: xmlSchemaValidateSimpleTypeValue, "
15914 "validating facets of list simple type '%s'\n",
15915 type->name, NULL);
15916 } else if (ret > 0) {
15917 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015918 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000015919 Disabled, since the facet validation already reports errors.
15920 if (fireErrors)
15921 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015922 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000015923 }
15924
Daniel Veillard01fa6152004-06-29 17:04:39 +000015925 }
15926 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
15927 xmlSchemaTypeLinkPtr memberLink;
15928
15929 /*
15930 * TODO: For all datatypes ·derived· by ·union· whiteSpace does
15931 * not apply directly; however, the normalization behavior of ·union·
15932 * types is controlled by the value of whiteSpace on that one of the
15933 * ·memberTypes· against which the ·union· is successfully validated.
15934 *
15935 * This means that the value is normalized by the first validating
15936 * member type, then the facets of the union type are applied. This
15937 * needs changing of the value!
15938 */
15939
15940 /*
15941 * 1.2.3 if {variety} is ·union· then the string must ·match· a
15942 * literal in the ·lexical space· of at least one member of
15943 * {member type definitions}
15944 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000015945#ifdef DEBUG_UNION_VALIDATION
15946 printf("Union ST : '%s'\n", (const char *) type->name);
15947 printf(" fireErrors : %d\n", fireErrors);
15948 printf(" applyFacets: %d\n", applyFacets);
15949#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +000015950 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
15951 if (memberLink == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015952 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015953 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000015954 "union simple type '%s' has no member types\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000015955 type->name, NULL);
15956 ret = -1;
15957 }
15958 if (ret == 0) {
15959 while (memberLink != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015960 ret = xmlSchemaValidateSimpleTypeValue(ctxt, memberLink->type,
15961 value, 0, 1, 1, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015962 if ((ret <= 0) || (ret == 0))
15963 break;
15964 memberLink = memberLink->next;
15965 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015966 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015967 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015968 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000015969 "validating members of union simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000015970 type->name, NULL);
15971 } else if (ret > 0) {
15972 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015973 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015974 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015975 }
15976 }
15977 /*
15978 * Apply facets (pattern, enumeration).
15979 */
15980 if ((ret == 0) && (applyFacets) && (type->facetSet != NULL)) {
15981 int mws;
15982 /*
15983 * The normalization behavior of ·union· types is controlled by
15984 * the value of whiteSpace on that one of the ·memberTypes·
15985 * against which the ·union· is successfully validated.
15986 */
15987 if (normValue != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015988 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015989 "Internal error: xmlSchemaValidateSimpleTypeValue, "
15990 "the value was already normalized for the union simple "
15991 "type '%s'.\n", type->name, NULL);
15992 }
15993 mws = xmlSchemaGetWhiteSpaceFacetValue(memberLink->type);
15994 if (mws > ctxt->valueWS) {
15995 if (mws == XML_SCHEMAS_VAL_WTSP_COLLAPSE)
15996 normValue = xmlSchemaCollapseString(value);
15997 else
15998 normValue = xmlSchemaWhiteSpaceReplace(value);
15999 if (normValue != NULL)
16000 value = (const xmlChar *) normValue;
16001 }
16002
16003 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
16004 value, 0, fireErrors);
16005 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016006 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016007 "Internal error: xmlSchemaValidateSimpleTypeValue, "
16008 "validating facets of union simple type '%s'\n",
16009 type->name, NULL);
16010 } else if (ret > 0) {
16011 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
16012 /*
16013 if (fireErrors)
16014 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
16015 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000016016 }
16017 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000016018 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000016019 ctxt->valueWS = wtsp;
16020 if (normValue != NULL)
16021 xmlFree(normValue);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016022 return (ret);
16023}
16024
16025/**
16026 * xmlSchemaValidateSimpleTypeElement:
16027 * @ctxt: a schema validation context
16028 * @node: the element node to be validated.
16029 *
16030 * Validate the element against a simple type.
16031 *
16032 * Returns 0 if the element is valid, a positive error code
16033 * number otherwise and -1 in case of an internal or API error.
16034 */
16035static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016036xmlSchemaValidateElementBySimpleType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016037 xmlSchemaTypePtr type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000016038 int isNil,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016039 int valSimpleContent)
Daniel Veillard01fa6152004-06-29 17:04:39 +000016040{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016041 xmlSchemaTypePtr oldtype;
16042 xmlNodePtr node;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016043 xmlAttrPtr attr;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016044 xmlNodePtr cur;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016045 int ret = 0, retval = 0;
16046
Daniel Veillard01fa6152004-06-29 17:04:39 +000016047 if ((ctxt == NULL) || (type == NULL)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016048 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_INTERNAL, NULL, NULL,
16049 "Internal error: xmlSchemaValidateElementBySimpleType, "
16050 "bad arguments", NULL);
16051 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016052 }
16053
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016054 oldtype = ctxt->type;
16055 node = ctxt->node;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016056 /*
16057 * cvc-type: 3.1.2 The element information item must have no element
16058 * information item [children].
16059 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016060 /*
16061 * STREAM: Child nodes are processed.
16062 */
16063 cur = node->children;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016064 while (cur != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016065 /*
16066 * TODO: Entities, will they produce elements as well?
16067 */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016068 if (cur->type == XML_ELEMENT_NODE) {
16069 xmlSchemaVCustomErr(ctxt,
16070 XML_SCHEMAV_CVC_TYPE_3_1_2,
16071 node, type,
16072 "No element content allowed", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016073 ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016074 }
16075 cur = cur->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016076 }
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016077
Daniel Veillard01fa6152004-06-29 17:04:39 +000016078 /*
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016079 * cvc-type 3.1.1:
16080 *
16081 * The attributes of must be empty, excepting those whose namespace name
16082 * is identical to http://www.w3.org/2001/XMLSchema-instance and whose local
16083 * name is one of type, nil, schemaLocation or noNamespaceSchemaLocation.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016084 */
16085 /*
16086 * STREAM: Attribute nodes are processed.
16087 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000016088 attr = node->properties;
16089 while (attr != NULL) {
16090 if ((attr->ns == NULL) ||
16091 (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
16092 ((!xmlStrEqual(attr->name, BAD_CAST "type")) &&
16093 (!xmlStrEqual(attr->name, BAD_CAST "nil")) &&
16094 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation")) &&
16095 (!xmlStrEqual
16096 (attr->name, BAD_CAST "noNamespaceSchemaLocation")))) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016097 xmlSchemaVIllegalAttrErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016098 XML_SCHEMAV_CVC_TYPE_3_1_1, attr);
16099 ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016100 }
16101 attr = attr->next;
16102 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016103 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016104 * This will skip validation if the type is 'anySimpleType' and
16105 * if the value was already validated (e.g. default values).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016106 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000016107 if ((! isNil) &&
16108 (valSimpleContent == 1) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016109 ((type->type != XML_SCHEMA_TYPE_BASIC) ||
16110 (type->builtInType != XML_SCHEMAS_ANYSIMPLETYPE))) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016111 xmlChar *value;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016112
16113 value = xmlNodeGetContent(node);
16114 /*
16115 * NOTE: This call will not check the content nodes, since
16116 * this should be checked here already.
16117 */
16118 retval = xmlSchemaValidateSimpleTypeValue(ctxt, type, value,
16119 1, 1, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000016120 if (value != NULL)
16121 xmlFree(value);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016122 if (retval != 0)
16123 ret = retval;
William M. Brack2f2a6632004-08-20 23:09:47 +000016124 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016125 ctxt->type = oldtype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016126 return (ret);
16127}
Daniel Veillard4255d502002-04-16 15:50:10 +000016128
16129/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016130 * xmlSchemaValQNameAcquire:
16131 * @value: the lexical represantation of the QName value
16132 * @node: the node to search for the corresponding namespace declaration
16133 * @nsName: the resulting namespace name if found
16134 *
16135 * Checks that a value conforms to the lexical space of the type QName;
16136 * if valid, the corresponding namespace name is searched and retured
16137 * as a copy in @nsName. The local name is returned in @localName as
16138 * a copy.
16139 *
16140 * Returns 0 if valid, 1 if not valid by type, 2 if no corresponding
16141 * namespace declaration was found in scope; -1 in case of an internal or
16142 * API error.
16143 */
16144static int
16145xmlSchemaValQNameAcquire(const xmlChar *value, xmlNodePtr node,
16146 xmlChar **nsName, xmlChar **localName)
16147{
16148 int ret;
16149 xmlChar *local = NULL;
16150
16151 if ((nsName == NULL) || (localName == NULL) || (node == NULL))
16152 return (-1);
16153 *nsName = NULL;
16154 *localName = NULL;
16155 ret = xmlValidateQName(value, 1);
16156 if (ret == 0) {
16157 xmlChar *prefix;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016158 xmlNsPtr ns;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016159
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016160 /*
16161 * NOTE: xmlSplitQName2 will return a duplicated
16162 * string.
16163 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016164 local = xmlSplitQName2(value, &prefix);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016165 if (local == NULL)
16166 local = xmlStrdup(value);
16167 ns = xmlSearchNs(node->doc, node, prefix);
16168 /*
16169 * A namespace need not to be found if the prefix is NULL.
16170 */
16171 if (ns != NULL) {
16172 /*
16173 * TODO: Is it necessary to duplicate the URI here?
16174 */
16175 *nsName = xmlStrdup(ns->href);
16176 } else if (prefix != NULL) {
16177 xmlFree(prefix);
16178 if (local != NULL)
16179 xmlFree(local);
16180 return (2);
16181 }
16182 *localName = local;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016183 if (prefix != NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016184 xmlFree(prefix);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016185 } else
16186 return (1);
16187 return (ret);
16188}
16189
16190/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016191 * xmlSchemaHasElemContent:
16192 * @node: the node
16193 *
16194 * Scours the content of the given node for element
16195 * nodes.
16196 *
16197 * Returns 1 if an element node is found,
16198 * 0 otherwise.
16199 */
16200static int
16201xmlSchemaHasElemContent(xmlNodePtr node)
16202{
16203 if (node == NULL)
16204 return (0);
16205 node = node->children;
16206 while (node != NULL) {
16207 if (node->type == XML_ELEMENT_NODE)
16208 return (1);
16209 node = node->next;
16210 }
16211 return (0);
16212}
16213/**
16214 * xmlSchemaHasElemOrCharContent:
16215 * @node: the node
16216 *
16217 * Scours the content of the given node for element
16218 * and character nodes.
16219 *
16220 * Returns 1 if an element or character node is found,
16221 * 0 otherwise.
16222 */
16223static int
16224xmlSchemaHasElemOrCharContent(xmlNodePtr node)
16225{
16226 if (node == NULL)
16227 return (0);
16228 node = node->children;
16229 while (node != NULL) {
16230 switch (node->type) {
16231 case XML_ELEMENT_NODE:
16232 /*
16233 * TODO: Ask Daniel if these are all character nodes.
16234 */
16235 case XML_TEXT_NODE:
16236 case XML_CDATA_SECTION_NODE:
16237 /*
16238 * TODO: How XML_ENTITY_NODEs evaluated?
16239 */
16240 case XML_ENTITY_REF_NODE:
16241 case XML_ENTITY_NODE:
16242 return (1);
16243 break;
16244 default:
16245 break;
16246 }
16247 node = node->next;
16248 }
16249 return (0);
16250}
16251
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016252/************************************************************************
16253 * *
16254 * Identity-constraints (IDC) *
16255 * *
16256 ************************************************************************/
16257
16258#ifdef IDC_ENABLED
16259
16260/**
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016261 * xmlSchemaAugmentIDC:
16262 * @idcDef: the IDC definition
16263 *
16264 * Creates an augmented IDC definition item.
16265 *
16266 * Returns the item, or NULL on internal errors.
16267 */
16268static void
16269xmlSchemaAugmentIDC(xmlSchemaIDCPtr idcDef,
16270 xmlSchemaValidCtxtPtr vctxt)
16271{
16272 xmlSchemaIDCAugPtr aidc;
16273
16274 aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
16275 if (aidc == NULL) {
16276 xmlSchemaVErrMemory(vctxt,
16277 "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
16278 NULL);
16279 return;
16280 }
16281 aidc->bubbleDepth = -1;
16282 aidc->def = idcDef;
16283 aidc->next = NULL;
16284 if (vctxt->aidcs == NULL)
16285 vctxt->aidcs = aidc;
16286 else {
16287 aidc->next = vctxt->aidcs;
16288 vctxt->aidcs = aidc;
16289 }
16290}
16291
16292/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016293 * xmlSchemaIDCNewBinding:
16294 * @idcDef: the IDC definition of this binding
16295 *
16296 * Creates a new IDC binding.
16297 *
16298 * Returns the new binding in case of succeeded, NULL on internal errors.
16299 */
16300static xmlSchemaPSVIIDCBindingPtr
16301xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
16302{
16303 xmlSchemaPSVIIDCBindingPtr ret;
16304
16305 ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
16306 sizeof(xmlSchemaPSVIIDCBinding));
16307 if (ret == NULL) {
16308 xmlSchemaVErrMemory(NULL,
16309 "allocating a PSVI IDC binding item", NULL);
16310 return (NULL);
16311 }
16312 memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
16313 ret->definition = idcDef;
16314 return (ret);
16315}
16316
16317/**
16318 * xmlSchemaIDCStoreNodeTableItem:
16319 * @vctxt: the WXS validation context
16320 * @item: the IDC node table item
16321 *
16322 * The validation context is used to store an IDC node table items.
16323 * They are stored to avoid copying them if IDC node-tables are merged
16324 * with corresponding parent IDC node-tables (bubbling).
16325 *
16326 * Returns 0 if succeeded, -1 on internal errors.
16327 */
16328static int
16329xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
16330 xmlSchemaPSVIIDCNodePtr item)
16331{
16332 /*
16333 * Add to gobal list.
16334 */
16335 if (vctxt->idcNodes == NULL) {
16336 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
16337 xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
16338 if (vctxt->idcNodes == NULL) {
16339 xmlSchemaVErrMemory(vctxt,
16340 "allocating the IDC node table item list", NULL);
16341 return (-1);
16342 }
16343 vctxt->sizeIdcNodes = 20;
16344 } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
16345 vctxt->sizeIdcNodes *= 2;
16346 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
16347 xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
16348 sizeof(xmlSchemaPSVIIDCNodePtr));
16349 if (vctxt->idcNodes == NULL) {
16350 xmlSchemaVErrMemory(vctxt,
16351 "re-allocating the IDC node table item list", NULL);
16352 return (-1);
16353 }
16354 }
16355 vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
16356
16357 return (0);
16358}
16359
16360/**
16361 * xmlSchemaIDCStoreKey:
16362 * @vctxt: the WXS validation context
16363 * @item: the IDC key
16364 *
16365 * The validation context is used to store an IDC key.
16366 *
16367 * Returns 0 if succeeded, -1 on internal errors.
16368 */
16369static int
16370xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
16371 xmlSchemaPSVIIDCKeyPtr key)
16372{
16373 /*
16374 * Add to gobal list.
16375 */
16376 if (vctxt->idcKeys == NULL) {
16377 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
16378 xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
16379 if (vctxt->idcKeys == NULL) {
16380 xmlSchemaVErrMemory(vctxt,
16381 "allocating the IDC key storage list", NULL);
16382 return (-1);
16383 }
16384 vctxt->sizeIdcKeys = 40;
16385 } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
16386 vctxt->sizeIdcKeys *= 2;
16387 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
16388 xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
16389 sizeof(xmlSchemaPSVIIDCKeyPtr));
16390 if (vctxt->idcKeys == NULL) {
16391 xmlSchemaVErrMemory(vctxt,
16392 "re-allocating the IDC key storage list", NULL);
16393 return (-1);
16394 }
16395 }
16396 vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
16397
16398 return (0);
16399}
16400
16401/**
16402 * xmlSchemaIDCAppendNodeTableItem:
16403 * @bind: the IDC binding
16404 * @ntItem: the node-table item
16405 *
16406 * Appends the IDC node-table item to the binding.
16407 *
16408 * Returns 0 on success and -1 on internal errors.
16409 */
16410static int
16411xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
16412 xmlSchemaPSVIIDCNodePtr ntItem)
16413{
16414 if (bind->nodeTable == NULL) {
16415 bind->sizeNodes = 10;
16416 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
16417 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
16418 if (bind->nodeTable == NULL) {
16419 xmlSchemaVErrMemory(NULL,
16420 "allocating an array of IDC node-table items", NULL);
16421 return(-1);
16422 }
16423 } else if (bind->sizeNodes <= bind->nbNodes) {
16424 bind->sizeNodes *= 2;
16425 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
16426 xmlRealloc(bind->nodeTable, bind->sizeNodes *
16427 sizeof(xmlSchemaPSVIIDCNodePtr));
16428 if (bind->nodeTable == NULL) {
16429 xmlSchemaVErrMemory(NULL,
16430 "re-allocating an array of IDC node-table items", NULL);
16431 return(-1);
16432 }
16433 }
16434 bind->nodeTable[bind->nbNodes++] = ntItem;
16435 return(0);
16436}
16437
16438/**
16439 * xmlSchemaIDCAquireBinding:
16440 * @vctxt: the WXS validation context
16441 * @matcher: the IDC matcher
16442 *
16443 * Looks up an PSVI IDC binding, for the IDC definition and
16444 * of the given matcher. If none found, a new one is created
16445 * and added to the IDC table.
16446 *
16447 * Returns an IDC binding or NULL on internal errors.
16448 */
16449static xmlSchemaPSVIIDCBindingPtr
16450xmlSchemaIDCAquireBinding(xmlSchemaValidCtxtPtr vctxt,
16451 xmlSchemaIDCMatcherPtr matcher)
16452{
16453 xmlSchemaElemInfoPtr info;
16454
16455 info = vctxt->elemInfos[matcher->depth];
16456
16457 if (info->idcTable == NULL) {
16458 info->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
16459 if (info->idcTable == NULL)
16460 return (NULL);
16461 return(info->idcTable);
16462 } else {
16463 xmlSchemaPSVIIDCBindingPtr bind = NULL;
16464
16465 bind = info->idcTable;
16466 do {
16467 if (bind->definition == matcher->aidc->def)
16468 return(bind);
16469 if (bind->next == NULL) {
16470 bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
16471 if (bind->next == NULL)
16472 return (NULL);
16473 return(bind->next);
16474 }
16475 bind = bind->next;
16476 } while (bind != NULL);
16477 }
16478 return (NULL);
16479}
16480
16481/**
16482 * xmlSchemaIDCFreeKey:
16483 * @key: the IDC key
16484 *
16485 * Frees an IDC key together with its compiled value.
16486 */
16487static void
16488xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
16489{
16490 if (key->compValue != NULL)
16491 xmlSchemaFreeValue(key->compValue);
16492 xmlFree(key);
16493}
16494
16495/**
16496 * xmlSchemaIDCFreeBinding:
16497 *
16498 * Frees an IDC binding. Note that the node table-items
16499 * are not freed.
16500 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000016501static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016502xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
16503{
16504 if (bind->nodeTable != NULL) {
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000016505 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
16506 int i;
16507 /*
16508 * Node-table items for keyrefs are not stored globally
16509 * to the validation context, since they are not bubbled.
16510 * We need to free them here.
16511 */
16512 for (i = 0; i < bind->nbNodes; i++) {
16513 xmlFree(bind->nodeTable[i]->keys);
16514 xmlFree(bind->nodeTable[i]);
16515 }
16516 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016517 xmlFree(bind->nodeTable);
16518 }
16519 xmlFree(bind);
16520}
16521
16522/**
16523 * xmlSchemaIDCFreeIDCTable:
16524 * @bind: the first IDC binding in the list
16525 *
16526 * Frees an IDC table, i.e. all the IDC bindings in the list.
16527 */
16528static void
16529xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
16530{
16531 xmlSchemaPSVIIDCBindingPtr prev;
16532
16533 while (bind != NULL) {
16534 prev = bind;
16535 bind = bind->next;
16536 xmlSchemaIDCFreeBinding(prev);
16537 }
16538}
16539
16540/**
16541 * xmlSchemaIDCFreeMatcherList:
16542 * @matcher: the first IDC matcher in the list
16543 *
16544 * Frees a list of IDC matchers.
16545 */
16546static void
16547xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
16548{
16549 xmlSchemaIDCMatcherPtr next;
16550
16551 while (matcher != NULL) {
16552 next = matcher->next;
16553 if (matcher->keySeqs != NULL) {
16554 int i;
16555 for (i = 0; i < matcher->sizeKeySeqs; i++)
16556 if (matcher->keySeqs[i] != NULL)
16557 xmlFree(matcher->keySeqs[i]);
16558 xmlFree(matcher->keySeqs);
16559 }
16560 xmlFree(matcher);
16561 matcher = next;
16562 }
16563}
16564
16565/**
16566 * xmlSchemaAreValuesEqual:
16567 * @ta: the first type
16568 * @a: the first value
16569 * @tb: the second type
16570 * @b: the second value
16571 *
16572 * Compares two values.
16573 *
16574 * Returns 1 if they are equal, 0 if not and -1 on internal errors.
16575 */
16576static int
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000016577xmlSchemaAreValuesEqual(xmlSchemaValidCtxtPtr vctxt,
16578 xmlSchemaTypePtr ta,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016579 xmlSchemaValPtr a,
16580 xmlSchemaTypePtr tb,
16581 xmlSchemaValPtr b)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000016582{
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016583 /* Same user derived/built-in derived/built-in primitive types. */
16584 if (ta == tb)
16585 goto compareValue;
16586
16587 /*
16588 * Comparison with anySimpleTypes is not supported by this implemention.
16589 */
16590 if ((ta->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
16591 (tb->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
16592 return(0);
16593
16594 /*
16595 * 4.2.1 equal (data-types)
16596 *
16597 * the ·value space·s of all ·primitive· datatypes are disjoint
16598 * (they do not share any values)
16599 */
16600 if ((ta->builtInType != 0) && (tb->builtInType != 0) &&
16601 (ta->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE) &&
16602 (tb->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
16603 return(0);
16604
16605 if ((ta->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
16606 (ta->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) ||
16607 (tb->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
16608 (tb->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)) {
16609 TODO
16610 return(0);
16611 }
16612 /*
16613 * (1) if a datatype T' is ·derived· by ·restriction· from an atomic datatype
16614 * T then the ·value space· of T' is a subset of the ·value space· of T.
16615 */
16616 /*
16617 * (2) if datatypes T' and T'' are ·derived· by ·restriction· from a common
16618 * atomic ancestor T then the ·value space·s of T' and T'' may overlap.
16619 */
16620
16621 {
16622 xmlSchemaTypePtr pta = ta, ptb = tb;
16623
16624 /* Note that we will compare the primitives here. */
16625 while ((pta->builtInType == 0) ||
16626 ((pta->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE) == 0))
16627 pta = pta->baseType;
16628 while ((ptb->builtInType == 0) ||
16629 ((ptb->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE) == 0))
16630 ptb = ptb->baseType;
16631 if (pta == ptb)
16632 goto compareValue;
16633 return(0);
16634 }
16635compareValue:
16636 {
16637#ifdef IDC_VALUE_SUPPORT
16638 int ret;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000016639 ret = xmlSchemaCompareValues(a, b);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016640 if (ret == 0)
16641 return(1);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000016642 else if (ret == -2) {
16643 xmlSchemaVErr(vctxt, vctxt->node,
16644 XML_SCHEMAV_INTERNAL,
16645 "Internal error: xmlSchemaAreValuesEqual, "
16646 "failed to compare the values.\n",
16647 NULL, NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016648 return(-1);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000016649 } else
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016650 return(0);
16651#else
16652 return (1);
16653#endif
16654 }
16655}
16656
16657/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016658 * xmlSchemaIDCAddStateObject:
16659 * @vctxt: the WXS validation context
16660 * @matcher: the IDC matcher
16661 * @sel: the XPath information
16662 * @parent: the parent "selector" state object if any
16663 * @type: "selector" or "field"
16664 *
16665 * Creates/reuses and activates state objects for the given
16666 * XPath information; if the XPath expression consists of unions,
16667 * multiple state objects are created for every unioned expression.
16668 *
16669 * Returns 0 on success and -1 on internal errors.
16670 */
16671static int
16672xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
16673 xmlSchemaIDCMatcherPtr matcher,
16674 xmlSchemaIDCSelectPtr sel,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016675 int type)
16676{
16677 xmlSchemaIDCStateObjPtr sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016678
16679 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016680 * Reuse the state objects from the pool.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016681 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016682 if (vctxt->xpathStatePool != NULL) {
16683 sto = vctxt->xpathStatePool;
16684 vctxt->xpathStatePool = sto->next;
16685 sto->next = NULL;
16686 } else {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016687 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016688 * Create a new state object.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016689 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016690 sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
16691 if (sto == NULL) {
16692 xmlSchemaVErrMemory(NULL,
16693 "allocating an IDC state object", NULL);
16694 return (-1);
16695 }
16696 memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
16697 }
16698 /*
16699 * Add to global list.
16700 */
16701 if (vctxt->xpathStates != NULL)
16702 sto->next = vctxt->xpathStates;
16703 vctxt->xpathStates = sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016704
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016705 /*
16706 * Free the old xpath validation context.
16707 */
16708 if (sto->xpathCtxt != NULL)
16709 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
16710
16711 /*
16712 * Create a new XPath (pattern) validation context.
16713 */
16714 sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
16715 (xmlPatternPtr) sel->xpathComp);
16716 if (sto->xpathCtxt == NULL) {
16717 xmlSchemaVErr(vctxt, vctxt->node,
16718 XML_SCHEMAV_INTERNAL,
16719 "Internal error: xmlSchemaIDCAddStateObject, "
16720 "failed to create the XPath validation context.\n",
16721 NULL, NULL);
16722 return (-1);
16723 }
16724 sto->type = type;
16725 sto->depth = vctxt->depth;
16726 sto->matcher = matcher;
16727 sto->sel = sel;
16728 sto->nbHistory = 0;
16729
16730#if DEBUG_IDC
16731 xmlGenericError(xmlGenericErrorContext, "IDC: STO push '%s'\n",
16732 sto->sel->xpath);
16733#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016734 return (0);
16735}
16736
16737/**
16738 * xmlSchemaXPathEvaluate:
16739 * @vctxt: the WXS validation context
16740 * @nodeType: the nodeType of the current node
16741 *
16742 * Evaluates all active XPath state objects.
16743 *
16744 * Returns the number of IC "field" state objects which resolved to
16745 * this node, 0 if none resolved and -1 on internal errors.
16746 */
16747static int
16748xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016749 xmlElementType nodeType)
16750{
16751 xmlSchemaIDCStateObjPtr sto, head = NULL, first;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000016752 int res, resolved = 0, depth = vctxt->depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016753
16754 if (vctxt->xpathStates == NULL)
16755 return (0);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000016756
16757 if (nodeType == XML_ATTRIBUTE_NODE)
16758 depth++;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016759#if DEBUG_IDC
16760 {
16761 xmlChar *str = NULL;
16762 xmlGenericError(xmlGenericErrorContext,
16763 "IDC: EVAL on %s, depth %d, type %d\n",
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000016764 xmlSchemaFormatNsUriLocal(&str, vctxt->nodeInfo->namespaceName,
16765 vctxt->nodeInfo->localName), depth, nodeType);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016766 FREE_AND_NULL(str)
16767 }
16768#endif
16769 /*
16770 * Process all active XPath state objects.
16771 */
16772 first = vctxt->xpathStates;
16773 sto = first;
16774 while (sto != head) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016775#if DEBUG_IDC
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016776 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016777 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] selector '%s'\n",
16778 sto->matcher->aidc->def->name, sto->sel->xpath);
16779 else
16780 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] field '%s'\n",
16781 sto->matcher->aidc->def->name, sto->sel->xpath);
16782#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016783
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016784#ifdef IDC_XPATH_SUPPORT
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000016785 if (nodeType == XML_ELEMENT_NODE)
16786 res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
16787 vctxt->nodeInfo->localName, vctxt->nodeInfo->namespaceName);
16788 else
16789 res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
16790 vctxt->nodeInfo->localName, vctxt->nodeInfo->namespaceName);
16791
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016792#else
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016793 res = 0;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000016794#endif
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016795 if (res == -1) {
16796 xmlSchemaVErr(vctxt, vctxt->node,
16797 XML_SCHEMAV_INTERNAL,
16798 "Internal error: xmlSchemaXPathEvaluate, "
16799 "failed to evaluate a node.\n",
16800 NULL, NULL);
16801 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016802 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016803 if (res == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016804 goto next_sto;
16805 /*
16806 * Full match.
16807 */
16808#if DEBUG_IDC
16809 xmlGenericError(xmlGenericErrorContext, "IDC: "
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016810 "MATCH\n");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016811#endif
16812 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016813 * Register a match in the state object history.
16814 */
16815 if (sto->history == NULL) {
16816 sto->history = (int *) xmlMalloc(5 * sizeof(int));
16817 if (sto->history == NULL) {
16818 xmlSchemaVErrMemory(NULL,
16819 "allocating the state object history", NULL);
16820 return(-1);
16821 }
16822 sto->sizeHistory = 10;
16823 } else if (sto->sizeHistory <= sto->nbHistory) {
16824 sto->sizeHistory *= 2;
16825 sto->history = (int *) xmlRealloc(sto->history,
16826 sto->sizeHistory * sizeof(int));
16827 if (sto->history == NULL) {
16828 xmlSchemaVErrMemory(NULL,
16829 "re-allocating the state object history", NULL);
16830 return(-1);
16831 }
16832 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000016833 sto->history[sto->nbHistory++] = depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016834
16835#ifdef DEBUG_IDC
16836 xmlGenericError(xmlGenericErrorContext, "IDC: push match '%d'\n",
16837 vctxt->depth);
16838#endif
16839
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016840 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
16841 xmlSchemaIDCSelectPtr sel;
16842 /*
16843 * Activate state objects for the IDC fields of
16844 * the IDC selector.
16845 */
16846#if DEBUG_IDC
16847 xmlGenericError(xmlGenericErrorContext, "IDC: "
16848 "activating field states\n");
16849#endif
16850 sel = sto->matcher->aidc->def->fields;
16851 while (sel != NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016852 if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
16853 sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
16854 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016855 sel = sel->next;
16856 }
16857 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
16858 /*
16859 * An IDC key node was found.
16860 */
16861#if DEBUG_IDC
16862 xmlGenericError(xmlGenericErrorContext,
16863 "IDC: key found\n");
16864#endif
16865 /*
16866 * Notify that the character value of this node is
16867 * needed.
16868 */
16869 if (resolved == 0)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000016870 vctxt->nodeInfo->flags |= XML_SCHEMA_ELEM_INFO_VALUE_NEEDED;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016871 resolved++;
16872 }
16873next_sto:
16874 if (sto->next == NULL) {
16875 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016876 * Evaluate field state objects created on this node as well.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016877 */
16878 head = first;
16879 sto = vctxt->xpathStates;
16880 } else
16881 sto = sto->next;
16882 }
16883 return (resolved);
16884}
16885
16886/**
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000016887 * xmlSchemaXPathProcessHistory:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016888 * @vctxt: the WXS validation context
16889 * @type: the simple/complex type of the current node if any at all
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000016890 * @compValue: the precompiled value
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016891 *
16892 * Processes and pops the history items of the IDC state objects.
16893 * IDC key-sequences are validated/created on IDC bindings.
16894 *
16895 * Returns 0 on success and -1 on internal errors.
16896 */
16897static int
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000016898xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000016899 int depth)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016900{
16901 xmlSchemaIDCStateObjPtr sto, nextsto;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016902 int res, matchDepth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016903 xmlSchemaPSVIIDCKeyPtr key = NULL;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000016904 xmlSchemaTypePtr type = vctxt->nodeInfo->typeDef;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016905
16906 if (vctxt->xpathStates == NULL)
16907 return (0);
16908 sto = vctxt->xpathStates;
16909
16910#if DEBUG_IDC
16911 {
16912 xmlChar *str = NULL;
16913 xmlGenericError(xmlGenericErrorContext,
16914 "IDC: BACK on %s, depth %d\n",
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000016915 xmlSchemaFormatNsUriLocal(&str, vctxt->nodeInfo->namespaceName,
16916 vctxt->nodeInfo->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016917 FREE_AND_NULL(str)
16918 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000016919#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016920 /*
16921 * Evaluate the state objects.
16922 */
16923 while (sto != NULL) {
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000016924#ifdef IDC_XPATH_SUPPORT
16925 xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
16926 #if DEBUG_IDC
16927 xmlGenericError(xmlGenericErrorContext, "IDC: stream pop '%s'\n",
16928 sto->sel->xpath);
16929 #endif
16930#endif
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016931 if (sto->nbHistory == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016932 goto deregister_check;
16933
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016934 matchDepth = sto->history[sto->nbHistory -1];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016935
16936 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016937 * Only matches at the current depth are of interest.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016938 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000016939 if (matchDepth != depth) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016940 sto = sto->next;
16941 continue;
16942 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016943
16944 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
16945 if (! IS_SIMPLE_TYPE(type)) {
16946 /*
16947 * Not qualified if the field resolves to a node of non
16948 * simple type.
16949 */
16950 xmlSchemaVCustomErr(vctxt,
16951 XML_SCHEMAV_CVC_IDC,
16952 vctxt->node,
16953 (xmlSchemaTypePtr) sto->matcher->aidc->def,
16954 "The field '%s' does evaluate to a node of "
16955 "non-simple type", sto->sel->xpath);
16956
16957 sto->nbHistory--;
16958 goto deregister_check;
16959 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000016960 if ((key == NULL) && (vctxt->nodeInfo->value == NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016961 /*
16962 * Failed to provide the normalized value; maby
16963 * the value was invalid.
16964 */
16965 xmlSchemaVErr(vctxt, NULL,
16966 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000016967 "Internal error: xmlSchemaXPathProcessHistory, "
16968 "computed value not available.\n",
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016969 NULL, NULL);
16970 sto->nbHistory--;
16971 goto deregister_check;
16972 } else {
16973 xmlSchemaIDCMatcherPtr matcher = sto->matcher;
16974 xmlSchemaPSVIIDCKeyPtr *keySeq;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000016975 int pos, idx;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016976
16977 /*
16978 * The key will be anchored on the matcher's list of
16979 * key-sequences. The position in this list is determined
16980 * by the target node's depth relative to the matcher's
16981 * depth of creation (i.e. the depth of the scope element).
16982 */
16983 pos = sto->depth - matcher->depth;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000016984 idx = sto->sel->index;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016985
16986 /*
16987 * Create/grow the array of key-sequences.
16988 */
16989 if (matcher->keySeqs == NULL) {
16990 if (pos > 9)
16991 matcher->sizeKeySeqs = pos * 2;
16992 else
16993 matcher->sizeKeySeqs = 10;
16994 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
16995 xmlMalloc(matcher->sizeKeySeqs *
16996 sizeof(xmlSchemaPSVIIDCKeyPtr *));
16997 if (matcher->keySeqs == NULL) {
16998 xmlSchemaVErrMemory(NULL,
16999 "allocating an array of key-sequences",
17000 NULL);
17001 return(-1);
17002 }
17003 memset(matcher->keySeqs, 0,
17004 matcher->sizeKeySeqs *
17005 sizeof(xmlSchemaPSVIIDCKeyPtr *));
17006 } else if (pos >= matcher->sizeKeySeqs) {
17007 int i = matcher->sizeKeySeqs;
17008
17009 matcher->sizeKeySeqs *= 2;
17010 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
17011 xmlRealloc(matcher->keySeqs,
17012 matcher->sizeKeySeqs *
17013 sizeof(xmlSchemaPSVIIDCKeyPtr *));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017014 if (matcher->keySeqs == NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017015 xmlSchemaVErrMemory(NULL,
17016 "reallocating an array of key-sequences",
17017 NULL);
17018 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017019 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017020 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017021 * The array needs to be NULLed.
17022 * TODO: Use memset?
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017023 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017024 for (; i < matcher->sizeKeySeqs; i++)
17025 matcher->keySeqs[i] = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017026 }
17027
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017028 /*
17029 * Get/create the key-sequence.
17030 */
17031 keySeq = matcher->keySeqs[pos];
17032 if (keySeq == NULL) {
17033 goto create_sequence;
17034 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017035 if (keySeq[idx] != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017036 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017037 * cvc-identity-constraint:
17038 * 3 For each node in the ·target node set· all
17039 * of the {fields}, with that node as the context
17040 * node, evaluate to either an empty node-set or
17041 * a node-set with exactly one member, which must
17042 * have a simple type.
17043 *
17044 * The key was already set; report an error.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017045 */
17046 xmlSchemaVCustomErr(vctxt,
17047 XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017048 vctxt->node, (xmlSchemaTypePtr) matcher->aidc->def,
17049 "The field '%s' evaluates to a node-set "
17050 "with more than one member", sto->sel->xpath);
17051 sto->nbHistory--;
17052 goto deregister_check;
17053 } else {
17054 goto create_key;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017055 }
17056 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017057
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017058create_sequence:
17059 /*
17060 * Create a key-sequence.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017061 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017062 keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
17063 matcher->aidc->def->nbFields *
17064 sizeof(xmlSchemaPSVIIDCKeyPtr));
17065 if (keySeq == NULL) {
17066 xmlSchemaVErrMemory(NULL,
17067 "allocating an IDC key-sequence", NULL);
17068 return(-1);
17069 }
17070 memset(keySeq, 0, matcher->aidc->def->nbFields *
17071 sizeof(xmlSchemaPSVIIDCKeyPtr));
17072 matcher->keySeqs[pos] = keySeq;
17073create_key:
17074 /*
17075 * Created a key once per node only.
17076 */
17077 if (key == NULL) {
17078 key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
17079 sizeof(xmlSchemaPSVIIDCKey));
17080 if (key == NULL) {
17081 xmlSchemaVErrMemory(NULL,
17082 "allocating a IDC key", NULL);
17083 xmlFree(keySeq);
17084 matcher->keySeqs[pos] = NULL;
17085 return(-1);
17086 }
17087 /*
17088 * Consume the compiled value.
17089 */
17090 key->type = type;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017091 key->compValue = vctxt->nodeInfo->value;
17092 vctxt->nodeInfo->value = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017093 /*
17094 * Store the key in a global list.
17095 */
17096 if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
17097 xmlSchemaIDCFreeKey(key);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017098 return (-1);
17099 }
17100 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017101 keySeq[idx] = key;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017102 }
17103 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017104
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017105 xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
17106 xmlSchemaPSVIIDCBindingPtr bind;
17107 xmlSchemaPSVIIDCNodePtr ntItem;
17108 xmlSchemaIDCMatcherPtr matcher;
17109 xmlSchemaIDCPtr idc;
17110 int pos, i, j, nbKeys;
17111 /*
17112 * Here we have the following scenario:
17113 * An IDC 'selector' state object resolved to a target node,
17114 * during the time this target node was in the
17115 * ancestor-or-self axis, the 'field' state object(s) looked
17116 * out for matching nodes to create a key-sequence for this
17117 * target node. Now we are back to this target node and need
17118 * to put the key-sequence, together with the target node
17119 * itself, into the node-table of the corresponding IDC
17120 * binding.
17121 */
17122 matcher = sto->matcher;
17123 idc = matcher->aidc->def;
17124 nbKeys = idc->nbFields;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017125 pos = depth - matcher->depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017126 /*
17127 * Check if the matcher has any key-sequences at all, plus
17128 * if it has a key-sequence for the current target node.
17129 */
17130 if ((matcher->keySeqs == NULL) ||
17131 (matcher->sizeKeySeqs <= pos)) {
17132 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
17133 goto selector_key_error;
17134 else
17135 goto selector_leave;
17136 }
17137
17138 keySeq = &(matcher->keySeqs[pos]);
17139 if (*keySeq == NULL) {
17140 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
17141 goto selector_key_error;
17142 else
17143 goto selector_leave;
17144 }
17145
17146 for (i = 0; i < nbKeys; i++) {
17147 if ((*keySeq)[i] == NULL) {
17148 /*
17149 * Not qualified, if not all fields did resolve.
17150 */
17151 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
17152 /*
17153 * All fields of a "key" IDC must resolve.
17154 */
17155 goto selector_key_error;
17156 }
17157 goto selector_leave;
17158 }
17159 }
17160 /*
17161 * All fields did resolve.
17162 */
17163
17164 /*
17165 * 4.1 If the {identity-constraint category} is unique(/key),
17166 * then no two members of the ·qualified node set· have
17167 * ·key-sequences· whose members are pairwise equal, as
17168 * defined by Equal in [XML Schemas: Datatypes].
17169 *
17170 * Get the IDC binding from the matcher and check for
17171 * duplicate key-sequences.
17172 */
17173 bind = xmlSchemaIDCAquireBinding(vctxt, matcher);
17174 if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
17175 (bind->nbNodes != 0)) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017176 xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017177
17178 i = 0;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017179 res = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017180 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017181 * Compare the key-sequences, key by key.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017182 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017183 do {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017184 bkeySeq = bind->nodeTable[i]->keys;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017185 for (j = 0; j < nbKeys; j++) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017186 ckey = (*keySeq)[j];
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017187 bkey = bkeySeq[j];
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017188 res = xmlSchemaAreValuesEqual(vctxt, ckey->type,
17189 ckey->compValue, bkey->type, bkey->compValue);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017190 if (res == -1) {
17191 return (-1);
17192 } else if (res == 0)
17193 break;
17194 }
17195 if (res == 1) {
17196 /*
17197 * Duplicate found.
17198 */
17199 break;
17200 }
17201 i++;
17202 } while (i < bind->nbNodes);
17203 if (i != bind->nbNodes) {
17204 /*
17205 * TODO: Try to report the key-sequence.
17206 */
17207 xmlSchemaVCustomErr(vctxt,
17208 XML_SCHEMAV_CVC_IDC,
17209 vctxt->node,
17210 (xmlSchemaTypePtr) idc,
17211 "Duplicate key-sequence found", NULL);
17212
17213 goto selector_leave;
17214 }
17215 }
17216 /*
17217 * Add a node-table item to the IDC binding.
17218 */
17219 ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
17220 sizeof(xmlSchemaPSVIIDCNode));
17221 if (ntItem == NULL) {
17222 xmlSchemaVErrMemory(NULL,
17223 "allocating an IDC node-table item", NULL);
17224 xmlFree(*keySeq);
17225 *keySeq = NULL;
17226 return(-1);
17227 }
17228 memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
17229
17230 /*
17231 * Store the node-table item on global list.
17232 */
17233 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
17234 if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
17235 xmlFree(ntItem);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017236 xmlFree(*keySeq);
17237 *keySeq = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017238 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017239 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017240 }
17241 /*
17242 * Init the node-table item. Consume the key-sequence.
17243 */
17244 ntItem->node = vctxt->node;
17245 ntItem->keys = *keySeq;
17246 *keySeq = NULL;
17247 if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1) {
17248 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
17249 /*
17250 * Free the item, since keyref items won't be
17251 * put on a global list.
17252 */
17253 xmlFree(ntItem->keys);
17254 xmlFree(ntItem);
17255 }
17256 return (-1);
17257 }
17258
17259 goto selector_leave;
17260selector_key_error:
17261 /*
17262 * 4.2.1 (KEY) The ·target node set· and the
17263 * ·qualified node set· are equal, that is, every
17264 * member of the ·target node set· is also a member
17265 * of the ·qualified node set· and vice versa.
17266 */
17267 xmlSchemaVCustomErr(vctxt,
17268 XML_SCHEMAV_CVC_IDC,
17269 vctxt->node,
17270 (xmlSchemaTypePtr) idc,
17271 "All 'key' fields must evaluate to a node",
17272 NULL);
17273selector_leave:
17274 /*
17275 * Free the key-sequence if not added to the IDC table.
17276 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017277 if ((keySeq != NULL) && (*keySeq != NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017278 xmlFree(*keySeq);
17279 *keySeq = NULL;
17280 }
17281 } /* if selector */
17282
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017283 sto->nbHistory--;
17284
17285deregister_check:
17286 /*
17287 * Deregister state objects if they reach the depth of creation.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017288 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017289 if ((sto->nbHistory == 0) && (sto->depth == depth)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017290#if DEBUG_IDC
17291 xmlGenericError(xmlGenericErrorContext, "IDC: STO pop '%s'\n",
17292 sto->sel->xpath);
17293#endif
17294 if (vctxt->xpathStates != sto) {
17295 xmlSchemaVErr(vctxt, vctxt->node,
17296 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017297 "Internal error: xmlSchemaXPathProcessHistory, "
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017298 "The state object to be removed is not the first "
17299 "in the list.\n",
17300 NULL, NULL);
17301 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017302 nextsto = sto->next;
17303 /*
17304 * Unlink from the list of active XPath state objects.
17305 */
17306 vctxt->xpathStates = sto->next;
17307 sto->next = vctxt->xpathStatePool;
17308 /*
17309 * Link it to the pool of reusable state objects.
17310 */
17311 vctxt->xpathStatePool = sto;
17312 sto = nextsto;
17313 } else
17314 sto = sto->next;
17315 } /* while (sto != NULL) */
17316 return (0);
17317}
17318
17319/**
17320 * xmlSchemaIDCRegisterMatchers:
17321 * @vctxt: the WXS validation context
17322 * @elemDecl: the element declaration
17323 *
17324 * Creates helper objects to evaluate IDC selectors/fields
17325 * successively.
17326 *
17327 * Returns 0 if OK and -1 on internal errors.
17328 */
17329static int
17330xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
17331 xmlSchemaElementPtr elemDecl)
17332{
17333 xmlSchemaIDCMatcherPtr matcher, last = NULL;
17334 xmlSchemaIDCPtr idc, refIdc;
17335 xmlSchemaIDCAugPtr aidc;
17336
17337 idc = (xmlSchemaIDCPtr) elemDecl->idcs;
17338 if (idc == NULL)
17339 return (0);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017340
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017341#if DEBUG_IDC
17342 {
17343 xmlChar *str = NULL;
17344 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017345 "IDC: REGISTER on %s, depth %d\n",
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017346 (char *) xmlSchemaFormatNsUriLocal(&str, vctxt->nodeInfo->namespaceName,
17347 vctxt->nodeInfo->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017348 FREE_AND_NULL(str)
17349 }
17350#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017351 if (vctxt->nodeInfo->idcMatchers != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017352 xmlSchemaVErr(vctxt, vctxt->node,
17353 XML_SCHEMAV_INTERNAL,
17354 "Internal error: xmlSchemaIDCRegisterMatchers: "
17355 "The chain of IDC matchers is expected to be empty.\n",
17356 NULL, NULL);
17357 return (-1);
17358 }
17359 do {
17360 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
17361 /*
17362 * Since IDCs bubbles are expensive we need to know the
17363 * depth at which the bubbles should stop; this will be
17364 * the depth of the top-most keyref IDC. If no keyref
17365 * references a key/unique IDC, the bubbleDepth will
17366 * be -1, indicating that no bubbles are needed.
17367 */
17368 refIdc = (xmlSchemaIDCPtr) idc->ref->item;
17369 if (refIdc != NULL) {
17370 /*
17371 * Lookup the augmented IDC.
17372 */
17373 aidc = vctxt->aidcs;
17374 while (aidc != NULL) {
17375 if (aidc->def == refIdc)
17376 break;
17377 aidc = aidc->next;
17378 }
17379 if (aidc == NULL) {
17380 xmlSchemaVErr(vctxt, vctxt->node,
17381 XML_SCHEMAV_INTERNAL,
17382 "Internal error: xmlSchemaIDCRegisterMatchers: "
17383 "Could not find an augmented IDC item for an IDC "
17384 "definition.\n",
17385 NULL, NULL);
17386 return (-1);
17387 }
17388 if ((aidc->bubbleDepth == -1) ||
17389 (vctxt->depth < aidc->bubbleDepth))
17390 aidc->bubbleDepth = vctxt->depth;
17391 }
17392 }
17393 /*
17394 * Lookup the augmented IDC item for the IDC definition.
17395 */
17396 aidc = vctxt->aidcs;
17397 while (aidc != NULL) {
17398 if (aidc->def == idc)
17399 break;
17400 aidc = aidc->next;
17401 }
17402 if (aidc == NULL) {
17403 xmlSchemaVErr(vctxt, vctxt->node,
17404 XML_SCHEMAV_INTERNAL,
17405 "Internal error: xmlSchemaIDCRegisterMatchers: "
17406 "Could not find an augmented IDC item for an IDC definition.\n",
17407 NULL, NULL);
17408 return (-1);
17409 }
17410 /*
17411 * Create an IDC matcher for every IDC definition.
17412 */
17413 matcher = (xmlSchemaIDCMatcherPtr)
17414 xmlMalloc(sizeof(xmlSchemaIDCMatcher));
17415 if (matcher == NULL) {
17416 xmlSchemaVErrMemory(vctxt,
17417 "allocating an IDC matcher", NULL);
17418 return (-1);
17419 }
17420 memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
17421 if (last == NULL)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017422 vctxt->nodeInfo->idcMatchers = matcher;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017423 else
17424 last->next = matcher;
17425 last = matcher;
17426
17427 matcher->type = IDC_MATCHER;
17428 matcher->depth = vctxt->depth;
17429 matcher->aidc = aidc;
17430#if DEBUG_IDC
17431 xmlGenericError(xmlGenericErrorContext, "IDC: register matcher\n");
17432#endif
17433 /*
17434 * Init the automaton state object.
17435 */
17436 if (xmlSchemaIDCAddStateObject(vctxt, matcher,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017437 idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017438 return (-1);
17439
17440 idc = idc->next;
17441 } while (idc != NULL);
17442 return (0);
17443}
17444
17445/**
17446 * xmlSchemaBubbleIDCNodeTables:
17447 * @depth: the current tree depth
17448 *
17449 * Merges IDC bindings of an element at @depth into the corresponding IDC
17450 * bindings of its parent element. If a duplicate note-table entry is found,
17451 * both, the parent node-table entry and child entry are discarded from the
17452 * node-table of the parent.
17453 *
17454 * Returns 0 if OK and -1 on internal errors.
17455 */
17456static int
17457xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
17458{
17459 xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017460 xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL, lastParBind = NULL; /* parent IDC bindings. */
17461 xmlSchemaPSVIIDCNodePtr node, parNode = NULL; /* node-table entries. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017462 xmlSchemaPSVIIDCKeyPtr key, parKey; /* keys of in a key-sequence. */
17463 xmlSchemaIDCAugPtr aidc;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017464 int i, j, k, ret = 0, oldNum, newDupls = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017465 int duplTop;
17466
17467 /*
17468 * The node table has the following sections:
17469 *
17470 * O --> old node-table entries (first)
17471 * O
17472 * + --> new node-table entries
17473 * +
17474 * % --> new duplicate node-table entries
17475 * %
17476 * # --> old duplicate node-table entries
17477 * # (last)
17478 *
17479 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017480 bind = vctxt->nodeInfo->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017481 if (bind == NULL) {
17482 /* Fine, no table, no bubbles. */
17483 return (0);
17484 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017485
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017486 parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
17487 /*
17488 * Walk all bindings; create new or add to existing bindings.
17489 * Remove duplicate key-sequences.
17490 */
17491start_binding:
17492 while (bind != NULL) {
17493 /*
17494 * Skip keyref IDCs.
17495 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017496 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
17497 bind = bind->next;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017498 continue;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017499 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017500 /*
17501 * Check if the key/unique IDC table needs to be bubbled.
17502 */
17503 aidc = vctxt->aidcs;
17504 do {
17505 if (aidc->def == bind->definition) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017506 if (aidc->bubbleDepth >= vctxt->depth) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017507 bind = bind->next;
17508 goto start_binding;
17509 }
17510 break;
17511 }
17512 aidc = aidc->next;
17513 } while (aidc != NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017514
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017515 if (parTable != NULL)
17516 parBind = *parTable;
17517 while (parBind != NULL) {
17518 /*
17519 * Search a matching parent binding for the
17520 * IDC definition.
17521 */
17522 if (parBind->definition == bind->definition) {
17523
17524 /*
17525 * Compare every node-table entry of the child node,
17526 * i.e. the key-sequence within, ...
17527 */
17528 oldNum = parBind->nbNodes; /* Skip newly added items. */
17529 duplTop = oldNum + parBind->nbDupls;
17530
17531 for (i = 0; i < bind->nbNodes; i++) {
17532 node = bind->nodeTable[i];
17533 if (node == NULL)
17534 continue;
17535 /*
17536 * ...with every key-sequence of the parent node, already
17537 * evaluated to be a duplicate key-sequence.
17538 */
17539 if (parBind->nbDupls != 0) {
17540 j = bind->nbNodes + newDupls;
17541 while (j < duplTop) {
17542 parNode = parBind->nodeTable[j];
17543 for (k = 0; k < bind->definition->nbFields; k++) {
17544 key = node->keys[k];
17545 parKey = parNode->keys[k];
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017546 ret = xmlSchemaAreValuesEqual(vctxt, key->type,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017547 key->compValue,
17548 parKey->type, parKey->compValue);
17549 if (ret == -1) {
17550 /* TODO: Internal error */
17551 return(-1);
17552 } else if (ret == 0)
17553 break;
17554
17555 }
17556 if (ret == 1)
17557 /* Duplicate found. */
17558 break;
17559 j++;
17560 }
17561 if (j != duplTop) {
17562 /* Duplicate found. */
17563 continue;
17564 }
17565 }
17566 /*
17567 * ... and with every key-sequence of the parent node.
17568 */
17569 j = 0;
17570 while (j < oldNum) {
17571 parNode = parBind->nodeTable[j];
17572 /*
17573 * Compare key by key.
17574 */
17575 for (k = 0; k < parBind->definition->nbFields; k++) {
17576 key = node->keys[k];
17577 parKey = parNode->keys[k];
17578
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017579 ret = xmlSchemaAreValuesEqual(vctxt, key->type,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017580 key->compValue,
17581 parKey->type, parKey->compValue);
17582 if (ret == -1) {
17583 /* TODO: Internal error */
17584 } else if (ret == 0)
17585 break;
17586
17587 }
17588 if (ret == 1)
17589 /*
17590 * The key-sequences are equal.
17591 */
17592 break;
17593 j++;
17594 }
17595 if (j != oldNum) {
17596 /*
17597 * Handle duplicates.
17598 */
17599 newDupls++;
17600 oldNum--;
17601 parBind->nbNodes--;
17602 /*
17603 * Move last old item to pos of duplicate.
17604 */
17605 parBind->nodeTable[j] =
17606 parBind->nodeTable[oldNum];
17607
17608 if (parBind->nbNodes != oldNum) {
17609 /*
17610 * If new items exist, move last new item to
17611 * last of old items.
17612 */
17613 parBind->nodeTable[oldNum] =
17614 parBind->nodeTable[parBind->nbNodes];
17615 }
17616 /*
17617 * Move duplicate to last pos of new/old items.
17618 */
17619 parBind->nodeTable[parBind->nbNodes] = parNode;
17620
17621 } else {
17622 /*
17623 * Add the node-table entry (node and key-sequence) of
17624 * the child node to the node table of the parent node.
17625 */
17626 if (parBind->nodeTable == NULL) {
17627 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
17628 xmlMalloc(1 * sizeof(xmlSchemaPSVIIDCNodePtr));
17629 if (parBind->nodeTable == NULL) {
17630 xmlSchemaVErrMemory(NULL,
17631 "allocating IDC list of node-table items", NULL);
17632 return(-1);
17633 }
17634 parBind->sizeNodes = 1;
17635 } else if (duplTop >= parBind->sizeNodes) {
17636 parBind->sizeNodes++;
17637 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
17638 xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
17639 sizeof(xmlSchemaPSVIIDCNodePtr));
17640 if (parBind->nodeTable == NULL) {
17641 xmlSchemaVErrMemory(NULL,
17642 "re-allocating IDC list of node-table items", NULL);
17643 return(-1);
17644 }
17645 }
17646
17647 /*
17648 * Move first old duplicate to last position
17649 * of old duplicates +1.
17650 */
17651 if (parBind->nbDupls != 0) {
17652 parBind->nodeTable[duplTop] =
17653 parBind->nodeTable[parBind->nbNodes + newDupls];
17654 }
17655 /*
17656 * Move first new duplicate to last position of
17657 * new duplicates +1.
17658 */
17659 if (newDupls != 0) {
17660 parBind->nodeTable[parBind->nbNodes + newDupls] =
17661 parBind->nodeTable[parBind->nbNodes];
17662 }
17663 /*
17664 * Append the new node-table entry to the 'new node-table
17665 * entries' section.
17666 */
17667 parBind->nodeTable[parBind->nbNodes] = node;
17668 parBind->nbNodes++;
17669 duplTop++;
17670 }
17671 }
17672 parBind->nbDupls += newDupls;
17673 break;
17674 }
17675 if (parBind->next == NULL)
17676 lastParBind = parBind;
17677 parBind = parBind->next;
17678 }
17679 if (parBind == NULL) {
17680 /*
17681 * No binding for the IDC was found: create a new one and
17682 * copy all node-tables.
17683 */
17684 parBind = xmlSchemaIDCNewBinding(bind->definition);
17685 if (parBind == NULL)
17686 return(-1);
17687
17688 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
17689 xmlMalloc(bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
17690 if (parBind->nodeTable == NULL) {
17691 xmlSchemaVErrMemory(NULL,
17692 "allocating an array of IDC node-table items", NULL);
17693 xmlSchemaIDCFreeBinding(parBind);
17694 return(-1);
17695 }
17696 parBind->sizeNodes = bind->nbNodes;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017697 parBind->nbNodes = bind->nbNodes;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017698 memcpy(parBind->nodeTable, bind->nodeTable,
17699 bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017700 if (*parTable == NULL)
17701 *parTable = parBind;
17702 else
17703 lastParBind->next = parBind;
17704 }
17705 bind = bind->next;
17706 }
17707 return (0);
17708}
17709
17710/**
17711 * xmlSchemaCheckCVCIDCKeyRef:
17712 * @vctxt: the WXS validation context
17713 * @elemDecl: the element declaration
17714 *
17715 * Check the cvc-idc-keyref constraints.
17716 */
17717static int
17718xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
17719{
17720 xmlSchemaPSVIIDCBindingPtr refbind, bind;
17721
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017722 refbind = vctxt->nodeInfo->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017723 /*
17724 * Find a keyref.
17725 */
17726 while (refbind != NULL) {
17727 if (refbind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
17728 int i, j, k, res;
17729 xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
17730 xmlSchemaPSVIIDCKeyPtr refKey, key;
17731
17732 /*
17733 * Find the referred key/unique.
17734 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017735 bind = vctxt->nodeInfo->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017736 do {
17737 if ((xmlSchemaIDCPtr) refbind->definition->ref->item ==
17738 bind->definition)
17739 break;
17740 bind = bind->next;
17741 } while (bind != NULL);
17742
17743 /*
17744 * Search for a matching key-sequences.
17745 */
17746 for (i = 0; i < refbind->nbNodes; i++) {
17747 res = 0;
17748 if (bind != NULL) {
17749 refKeys = refbind->nodeTable[i]->keys;
17750 for (j = 0; j < bind->nbNodes; j++) {
17751 keys = bind->nodeTable[j]->keys;
17752 for (k = 0; k < bind->definition->nbFields; k++) {
17753 refKey = refKeys[k];
17754 key = keys[k];
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017755 res = xmlSchemaAreValuesEqual(vctxt,
17756 key->type, key->compValue,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017757 refKey->type, refKey->compValue);
17758 if (res == 0)
17759 break;
17760 else if (res == -1) {
17761 return (-1);
17762 }
17763 }
17764 if (res == 1) {
17765 /*
17766 * Match found.
17767 */
17768 break;
17769 }
17770 }
17771 }
17772 if (res == 0) {
17773 /* TODO: Report the key-sequence. */
17774 xmlSchemaVCustomErr(vctxt,
17775 XML_SCHEMAV_CVC_IDC,
17776 refbind->nodeTable[i]->node,
17777 (xmlSchemaTypePtr) refbind->definition,
17778 "No matching key-sequence found", NULL);
17779 }
17780 }
17781 }
17782 refbind = refbind->next;
17783 }
17784 return (0);
17785}
17786#endif /* IDC_ENABLED */
17787
17788#ifdef ELEM_INFO_ENABLED
17789/**
17790 * xmlSchemaBeginElement:
17791 * @vctxt: the WXS validation context
17792 *
17793 * Just a temporary workaround to simulate streaming validation
17794 * a bit.
17795 */
17796static void
17797xmlSchemaBeginElement(xmlSchemaValidCtxtPtr vctxt)
17798{
17799 vctxt->depth++;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017800 vctxt->nodeInfo = xmlSchemaGetFreshElemInfo(vctxt, vctxt->depth);
17801 vctxt->nodeInfo->node = vctxt->node;
17802 vctxt->nodeInfo->localName = vctxt->node->name;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017803 if (vctxt->node->ns != NULL)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017804 vctxt->nodeInfo->namespaceName = vctxt->node->ns->href;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017805 else
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017806 vctxt->nodeInfo->namespaceName = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017807}
17808
17809/**
17810 * xmlSchemaEndElement:
17811 * @vctxt: the WXS validation context
17812 *
17813 * Just a temporary workaround to simulate streaming validation
17814 * a bit.
17815 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017816static int
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017817xmlSchemaEndElement(xmlSchemaValidCtxtPtr vctxt)
17818{
17819 if (vctxt->depth < 0) {
17820 /* TODO: raise error? */
17821 vctxt->depth--;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017822 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017823 }
17824#ifdef IDC_ENABLED
17825 /*
17826 * Evaluate the history of changes of active state objects.
17827 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017828 if (xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1)
17829 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017830
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017831 if (vctxt->nodeInfo->value != NULL) {
17832 xmlSchemaFreeValue(vctxt->nodeInfo->value);
17833 vctxt->nodeInfo->value = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017834 }
17835 /*
17836 * TODO: 6 The element information item must be ·valid· with respect to each of
17837 * the {identity-constraint definitions} as per Identity-constraint
17838 * Satisfied (§3.11.4).
17839 */
17840 /*
17841 * Validate IDC keyrefs.
17842 */
17843 xmlSchemaCheckCVCIDCKeyRef(vctxt);
17844#endif
17845
17846 /*
17847 * Merge/free the IDC table.
17848 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017849 if (vctxt->nodeInfo->idcTable != NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017850#ifdef IDC_ENABLED
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017851#ifdef DEBUG_IDC
17852 xmlSchemaDebugDumpIDCTable(stdout,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017853 vctxt->nodeInfo->namespaceName,
17854 vctxt->nodeInfo->localName,
17855 vctxt->nodeInfo->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017856#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017857 if (vctxt->depth > 0) {
17858 /*
17859 * Merge the IDC node table with the table of the parent node.
17860 */
17861 xmlSchemaBubbleIDCNodeTables(vctxt);
17862 }
17863 /*
17864 * TODO: Don't free the PSVI IDC tables if they are
17865 * requested for the PSVI.
17866 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017867 xmlSchemaIDCFreeIDCTable(vctxt->nodeInfo->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017868#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017869 vctxt->nodeInfo->idcTable = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017870 }
17871
17872 /*
17873 * Cleanup IDC matchers.
17874 */
17875#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017876 if (vctxt->nodeInfo->idcMatchers != NULL) {
17877 xmlSchemaIDCFreeMatcherList(vctxt->nodeInfo->idcMatchers);
17878 vctxt->nodeInfo->idcMatchers = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017879 }
17880#endif
17881
17882 /*
17883 * Skip further processing if we are on the validation root.
17884 */
17885 if (vctxt->depth == 0) {
17886 vctxt->depth--;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017887 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017888 }
17889
17890 /*
17891 * Reset the bubbleDepth if needed.
17892 */
17893#ifdef IDC_ENABLED
17894 if (vctxt->aidcs != NULL) {
17895 xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
17896 do {
17897 if (aidc->bubbleDepth == vctxt->depth) {
17898 /*
17899 * A bubbleDepth of a key/unique IDC matches the current
17900 * depth, this means that we are leaving the scope of the
17901 * top-most keyref IDC.
17902 */
17903 aidc->bubbleDepth = -1;
17904 }
17905 aidc = aidc->next;
17906 } while (aidc != NULL);
17907 }
17908#endif
17909 vctxt->depth--;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017910 /*
17911 * Clear the current elemInfo.
17912 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017913 if (vctxt->nodeInfo->value != NULL) {
17914 xmlSchemaFreeValue(vctxt->nodeInfo->value);
17915 vctxt->nodeInfo->value = NULL;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017916 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017917 vctxt->nodeInfo = vctxt->elemInfos[vctxt->depth];
17918 vctxt->node = vctxt->nodeInfo->node;
17919
17920 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017921}
17922
17923#endif /* ELEM_INFO_ENABLED */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017924
17925/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017926 * xmlSchemaValidateElementByDeclaration:
Daniel Veillard4255d502002-04-16 15:50:10 +000017927 * @ctxt: a schema validation context
17928 * @node: the top node.
17929 *
17930 * Validate the content of an element type.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017931 * Validation Rule: Element Locally Valid (Element)
Daniel Veillard4255d502002-04-16 15:50:10 +000017932 *
17933 * Returns 0 if the element is schemas valid, a positive error code
17934 * number otherwise and -1 in case of internal or API error.
17935 */
17936static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017937xmlSchemaValidateElementByDeclaration(xmlSchemaValidCtxtPtr ctxt,
17938 xmlSchemaElementPtr elemDecl)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017939{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017940 xmlNodePtr elem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017941 int ret = 0;
17942 xmlSchemaTypePtr actualType = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017943 xmlAttrPtr attr;
17944 xmlChar *attrValue;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017945 int nilled = 0, elemHasContent = -1;
Daniel Veillard3646d642004-06-02 19:19:14 +000017946
17947 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017948 * This one is called by xmlSchemaValidateElementByWildcardInternal,
17949 * xmlSchemaValidateElementByAnyType and xmlSchemaValidateElement.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017950 * Note that @elemDecl will be the declaration and never the
17951 * reference to a declaration.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017952 */
Daniel Veillard3646d642004-06-02 19:19:14 +000017953
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017954 if (ctxt == NULL) {
17955 xmlSchemaVErr(ctxt, NULL, XML_SCHEMAV_INTERNAL,
17956 "Internal error: xmlSchemaValidateElementByDeclaration, "
17957 "bad arguments.\n",
17958 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017959 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000017960 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017961
17962 elem = ctxt->node;
17963
17964 /*
17965 * cvc-elt (3.3.4) : 1
17966 */
17967 if (elemDecl == NULL) {
17968 xmlSchemaVCustomErr(ctxt,
17969 XML_SCHEMAV_CVC_ELT_1,
17970 elem, NULL,
17971 "No matching declaration available", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017972 /*
17973 * Evaluate IDCs even if an error occured.
17974 */
17975#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017976 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017977 return (-1);
17978#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017979 return (ctxt->err);
17980 }
17981 /*
17982 * cvc-elt (3.3.4) : 2
17983 */
17984 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
17985 xmlSchemaVCustomErr(ctxt,
17986 XML_SCHEMAV_CVC_ELT_2,
17987 elem, NULL,
17988 "The element declaration is abstract", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017989 /*
17990 * Evaluate IDCs even if an error occured.
17991 */
17992#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000017993 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017994 return (-1);
17995#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017996 return (ctxt->err);
17997 }
17998
17999 /*
18000 * cvc-elt (3.3.4) : 3
18001 * Handle 'xsi:nil'.
18002 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018003
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018004 attr = xmlHasNsProp(elem, BAD_CAST "nil", xmlSchemaInstanceNs);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018005 if (attr != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018006 attrValue = xmlNodeGetContent((xmlNodePtr) attr);
18007 ctxt->node = (xmlNodePtr) attr;
18008 ctxt->cur = attr->children;
18009 ret = xmlSchemaValidateSimpleTypeValue(ctxt,
18010 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
18011 BAD_CAST attrValue, 1, 1, 1, 1);
18012 ctxt->node = elem;
18013 ctxt->type = (xmlSchemaTypePtr) elemDecl;
18014 if (ret < 0) {
18015 xmlSchemaVCustomErr(ctxt,
18016 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018017 (xmlNodePtr) attr, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018018 "Internal error: xmlSchemaValidateElementByDeclaration, "
18019 "validating the attribute 'xsi:nil'", NULL);
18020 if (attrValue != NULL)
18021 xmlFree(attrValue);
18022 return (-1);
18023 }
18024 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018025 /*
18026 * cvc-elt (3.3.4) : 3.1
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018027 */
18028 xmlSchemaVCustomErr(ctxt,
18029 XML_SCHEMAV_CVC_ELT_3_1,
18030 elem, NULL,
18031 "The element is not 'nillable'", NULL);
18032 } else {
18033 if (xmlStrEqual(BAD_CAST attrValue, BAD_CAST "true") ||
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018034 xmlStrEqual(BAD_CAST attrValue, BAD_CAST "1")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018035 ret = 0;
18036 /*
18037 * cvc-elt (3.3.4) : 3.2.1
18038 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018039 elemHasContent = xmlSchemaHasElemOrCharContent(elem);
18040 if (elemHasContent == 1) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018041 xmlSchemaVCustomErr(ctxt,
18042 XML_SCHEMAV_CVC_ELT_3_2_1,
18043 /* XML_SCHEMAS_ERR_NOTEMPTY, */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018044 elem, (xmlSchemaTypePtr) elemDecl,
18045 "The 'nilled' element must have no character or "
18046 "element content", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018047 ret = XML_SCHEMAV_CVC_ELT_3_2_1;
18048 }
18049 /*
18050 * cvc-elt (3.3.4) : 3.2.2
18051 */
18052 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
18053 (elemDecl->value != NULL)) {
18054 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_CVC_ELT_3_2_2,
18055 /* XML_SCHEMAS_ERR_HAVEDEFAULT, */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018056 elem, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018057 "There is a fixed value constraint defined for "
18058 "the 'nilled' element", NULL);
18059 ret = XML_SCHEMAV_CVC_ELT_3_2_2;
18060 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018061 if (ret == 0)
18062 nilled = 1;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018063 }
18064 }
18065 if (attrValue != NULL)
18066 xmlFree(attrValue);
18067 }
18068
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018069
18070 actualType = elemDecl->subtypes;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018071 /*
18072 * cvc-elt (3.3.4) : 4
18073 * Handle 'xsi:type'.
18074 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018075
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018076 attr = xmlHasNsProp(elem, BAD_CAST "type", xmlSchemaInstanceNs);
18077 if (attr != NULL) {
18078 xmlChar *nsName = NULL, *local = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018079
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018080 /*
18081 * TODO: We should report a *warning* that the type was overriden
18082 * by the instance.
18083 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018084
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018085 /*
18086 * cvc-elt (3.3.4) : 4.1
18087 */
18088 attrValue = xmlNodeGetContent((xmlNodePtr) attr);
18089 ret = xmlSchemaValQNameAcquire(attrValue, attr->parent,
18090 &nsName, &local);
18091 if (ret < 0) {
18092 xmlSchemaVCustomErr(ctxt,
18093 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018094 (xmlNodePtr) attr, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018095 "Internal error: xmlSchemaValidateElementByDeclaration, "
18096 "validating the attribute 'xsi:type'", NULL);;
18097 FREE_AND_NULL(attrValue)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018098 FREE_AND_NULL(nsName)
18099 FREE_AND_NULL(local)
18100 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018101 } else if (ret == 1) {
18102 xmlSchemaVSimpleTypeErr(ctxt,
18103 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
18104 (xmlNodePtr) attr, attrValue,
18105 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME));
18106 } else if (ret == 2) {
18107 xmlSchemaVCustomErr(ctxt,
18108 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
18109 (xmlNodePtr) attr,
18110 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
18111 "The QName value '%s' has no "
18112 "corresponding namespace declaration in scope",
18113 attrValue);
18114 } else {
18115 /*
18116 * cvc-elt (3.3.4) : 4.2
18117 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018118 actualType = xmlSchemaGetType(ctxt->schema, local, nsName);
18119 if (actualType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018120 xmlChar *strA = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018121
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018122 xmlSchemaVCustomErr(ctxt,
18123 XML_SCHEMAV_CVC_ELT_4_2,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018124 (xmlNodePtr) attr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018125 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
18126 "The value %s does not resolve to a type "
18127 "definition",
18128 xmlSchemaFormatNsUriLocal(&strA, nsName, local));
18129 FREE_AND_NULL(strA);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018130 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018131 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018132 * URGENT TODO: cvc-elt (3.3.4) : 4.3 (Type Derivation OK)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018133 */
18134 }
18135 }
18136 FREE_AND_NULL(attrValue)
18137 FREE_AND_NULL(nsName)
18138 FREE_AND_NULL(local)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018139 }
18140 /* TODO: Change the handling of missing types according to
18141 * the spec.
18142 */
18143 if (actualType == NULL) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018144 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018145 XML_SCHEMAV_CVC_TYPE_1,
18146 elem, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018147 "The type definition is absent", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018148 /*
18149 * Evaluate IDCs even if an error occured.
18150 */
18151#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018152 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018153 return (-1);
18154#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018155 return (XML_SCHEMAV_CVC_TYPE_1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018156 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018157
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018158 /*
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018159 * Remember the actual-type definition.
18160 */
18161#ifdef ELEM_INFO_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018162 ctxt->nodeInfo->typeDef = actualType;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018163#endif
18164
18165 /*
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018166 * TODO: Since this should be already checked by the content model automaton,
18167 * and we want to get rid of the XML_SCHEMAS_ERR... types, the error code
18168 * has been changed to XML_SCHEMAV_INTERNAL.
18169 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018170 /*
Daniel Veillard4255d502002-04-16 15:50:10 +000018171 if (child == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000018172 if (decl->minOccurs > 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018173 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018174 XML_SCHEMAS_ERR_MISSING,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018175 "Element %s: missing child %s\n",
18176 node->name, decl->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018177 }
18178 return (ctxt->err);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018179 }
18180 */
Daniel Veillard4255d502002-04-16 15:50:10 +000018181 /*
18182 * Verify the element matches
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018183 * TODO, FIXME: Can this still happen here? Isn't this already checked
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018184 * by the content model automaton?
Daniel Veillardc0826a72004-08-10 14:17:33 +000018185 if (!xmlStrEqual(child->name, decl->name)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018186 xmlSchemaVErr3(ctxt, node, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018187 XML_SCHEMAS_ERR_WRONGELEM,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018188 "Element %s: missing child %s found %s\n",
18189 node->name, decl->name, child->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018190 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000018191 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018192 */
18193 if (elemHasContent == -1)
18194 elemHasContent = xmlSchemaHasElemOrCharContent(elem);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018195
18196 /*
18197 * IDC: Register identity-constraint XPath matchers.
18198 */
18199#ifdef IDC_ENABLED
18200 if (elemDecl->idcs != NULL)
18201 xmlSchemaIDCRegisterMatchers(ctxt, elemDecl);
18202 /*
18203 * Evaluate IDCs.
18204 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018205 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018206 return (-1);
18207#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018208 /*
18209 * cvc-elt (3.3.4) : 5
18210 * The appropriate case among the following must be true:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018211 */
Daniel Veillard4255d502002-04-16 15:50:10 +000018212 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018213 * cvc-elt (3.3.4) : 5.1
18214 * If the declaration has a {value constraint},
18215 * the item has neither element nor character [children] and
18216 * clause 3.2 has not applied, then all of the following must be true:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018217 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018218 if ((elemHasContent == 0) && (nilled == 0) && (elemDecl->value != NULL)) {
18219 /*
18220 * cvc-elt (3.3.4) : 5.1.1
18221 * If the ·actual type definition· is a ·local type definition·
18222 * then the canonical lexical representation of the {value constraint}
18223 * value must be a valid default for the ·actual type definition· as
18224 * defined in Element Default Valid (Immediate) (§3.3.6).
18225 */
18226 /*
18227 * NOTE: 'local' above means types aquired by xsi:type.
18228 */
18229 ret = 0;
18230 if (actualType != elemDecl->subtypes) {
18231 xmlSchemaCreatePCtxtOnVCtxt(ctxt);
18232 ret = xmlSchemaCheckCOSValidDefault(ctxt->pctxt, ctxt, actualType,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018233 elemDecl->value, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018234 if (ret < 0) {
18235 xmlSchemaVCustomErr(ctxt,
18236 XML_SCHEMAV_INTERNAL,
18237 elem, actualType,
18238 "Internal error: xmlSchemaValidateElementByDeclaration, "
18239 "validating a default value", NULL);
18240 return (-1);
18241 }
18242 }
18243 /*
18244 * cvc-elt (3.3.4) : 5.1.2
18245 * The element information item with the canonical lexical
18246 * representation of the {value constraint} value used as its
18247 * ·normalized value· must be ·valid· with respect to the
18248 * ·actual type definition· as defined by Element Locally Valid (Type)
18249 * (§3.3.4).
18250 */
18251 /*
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018252 * Disable validation of the simple content, if it was already
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018253 * done above.
18254 */
18255 if (ret == 0) {
18256 if (actualType != elemDecl->subtypes)
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018257 ret = xmlSchemaValidateElementByType(ctxt, actualType, 0, 0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018258 else
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018259 ret = xmlSchemaValidateElementByType(ctxt, actualType, 0, 1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018260 ctxt->node = elem;
18261 if (ret < 0) {
18262 xmlSchemaVCustomErr(ctxt,
18263 XML_SCHEMAV_INTERNAL,
18264 elem, actualType,
18265 "Internal error: xmlSchemaValidateElementByDeclaration, "
18266 "validating against the type", NULL);
18267 return (-1);
18268 }
18269 /*
18270 * PSVI: Create a text node on the instance element.
18271 */
18272 if (ctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
18273 xmlNodePtr textChild;
18274
18275 textChild = xmlNewText(elemDecl->value);
18276 if (textChild == NULL) {
18277 xmlSchemaVCustomErr(ctxt,
18278 XML_SCHEMAV_INTERNAL,
18279 elem, actualType,
18280 "Internal error: xmlSchemaValidateElementByDeclaration, "
18281 "could not create a default text node for the instance",
18282 NULL);
18283 } else
18284 xmlAddChild(elem, textChild);
18285 }
18286 }
18287
18288 } else {
18289 /*
18290 * 5.2.1 The element information item must be ·valid· with respect
18291 * to the ·actual type definition· as defined by Element Locally
18292 * Valid (Type) (§3.3.4).
18293 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018294 ret = xmlSchemaValidateElementByType(ctxt, actualType, nilled, 1);
18295 /*
18296 * Consume the computed value for IDCs, ect. Note that default
18297 * values are not supported yet.
18298 */
18299#ifdef ELEM_INFO_ENABLED
18300 if (ctxt->value != NULL) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018301 ctxt->nodeInfo->value = ctxt->value;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018302 ctxt->value = NULL;
18303 }
18304#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018305 ctxt->node = elem;
18306 if (ret < 0) {
18307 xmlSchemaVCustomErr(ctxt,
18308 XML_SCHEMAV_INTERNAL,
18309 elem, actualType,
18310 "Internal error: xmlSchemaValidateElementByDeclaration, "
18311 "validating a default value", NULL);
18312 return (-1);
18313 }
18314 /*
18315 * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
18316 * not applied, all of the following must be true:
18317 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018318 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) && (nilled == 0)) {
18319 /*
18320 * 5.2.2.1 The element information item must have no element
18321 * information item [children].
18322 *
18323 * TODO REDUNDANT: If the actual type exists, the above call to
18324 * xmlSchemaValidateElementByType will already check for element
18325 * nodes.
18326 */
18327 if (xmlSchemaHasElemContent(elem)) {
18328 xmlSchemaVCustomErr(ctxt,
18329 XML_SCHEMAV_CVC_ELT_5_2_2_1,
18330 elem, (xmlSchemaTypePtr) elemDecl,
18331 "Elements in the content are not allowed if it is "
18332 "constrained by a fixed value", NULL);
18333 } else {
18334 /*
18335 * 5.2.2.2 The appropriate case among the following must
18336 * be true:
18337 */
18338
18339 if (actualType->contentType == XML_SCHEMA_CONTENT_MIXED) {
18340 xmlChar *value;
18341 /*
18342 * 5.2.2.2.1 If the {content type} of the ·actual type
18343 * definition· is mixed, then the *initial value* of the
18344 * item must match the canonical lexical representation
18345 * of the {value constraint} value.
18346 *
18347 * ... the *initial value* of an element information
18348 * item is the string composed of, in order, the
18349 * [character code] of each character information item in
18350 * the [children] of that element information item.
18351 */
18352 value = xmlNodeListGetString(elem->doc, elem->children, 1);
18353 if (! xmlStrEqual(BAD_CAST value, elemDecl->value)) {
18354 /*
18355 * TODO: Report invalid & expected values as well.
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018356 * TODO: Implement the canonical stuff.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018357 */
18358 xmlSchemaVCustomErr(ctxt,
18359 XML_SCHEMAV_CVC_ELT_5_2_2_2_1,
18360 elem, (xmlSchemaTypePtr) elemDecl,
18361 "The value does not match the cononical "
18362 "lexical representation of the fixed constraint",
18363 NULL);
18364 }
18365 if (value != NULL)
18366 xmlFree(value);
18367 } else if ((actualType->contentType ==
18368 XML_SCHEMA_CONTENT_SIMPLE) ||
18369 (actualType->contentType == XML_SCHEMA_CONTENT_BASIC)) {
18370 xmlChar *value;
18371
18372 /*
18373 * 5.2.2.2.2 If the {content type} of the ·actual type
18374 * definition· is a simple type definition, then the
18375 * *actual value* of the item must match the canonical
18376 * lexical representation of the {value constraint} value.
18377 */
18378 /*
18379 * TODO: *actual value* is the normalized value, impl. this.
18380 * TODO: Report invalid & expected values as well.
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018381 * TODO: Implement the canonical stuff.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018382 *
18383 */
18384 value = xmlNodeListGetString(elem->doc, elem->children, 1);
18385 if (! xmlStrEqual(BAD_CAST value, elemDecl->value)) {
18386 xmlSchemaVCustomErr(ctxt,
18387 XML_SCHEMAV_CVC_ELT_5_2_2_2_2,
18388 elem, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018389 "The normalized value does not match the canonical "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018390 "lexical representation of the fixed constraint",
18391 NULL);
18392 }
18393 if (value != NULL)
18394 xmlFree(value);
18395
18396 }
18397 /*
18398 * TODO: What if the content type is not 'mixed' or simple?
18399 */
18400
18401 }
18402
18403 }
18404 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018405 /*
18406 * TODO: 7 If the element information item is the ·validation root·, it must be
18407 * ·valid· per Validation Root Valid (ID/IDREF) (§3.3.4).
18408 */
18409
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018410 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000018411}
18412
Daniel Veillard4255d502002-04-16 15:50:10 +000018413/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018414 * xmlSchemaValidateElementByWildcardInternal:
Daniel Veillardc0826a72004-08-10 14:17:33 +000018415 * @ctxt: a schema validation context
18416 * @node: the top node.
18417 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018418 * Represents the recursive portion of xmlSchemaValidateElementByWildcard.
18419 * Not intended to be used by other functions.
Daniel Veillardc0826a72004-08-10 14:17:33 +000018420 *
18421 * Returns 0 if the element is valid, a positive error code
18422 * number otherwise and -1 in case of an internal error.
18423 */
18424static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018425xmlSchemaValidateElementByWildcardInternal(xmlSchemaValidCtxtPtr ctxt,
18426 xmlSchemaWildcardPtr wild,
18427 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +000018428{
18429 const xmlChar *uri;
18430 int ret = 0;
18431 xmlNodePtr child;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018432
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018433 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018434 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
18435 if (ret == -1) {
18436 xmlSchemaVCustomErr(ctxt,
18437 XML_SCHEMAV_INTERNAL,
18438 ctxt->node, NULL,
18439 "Internal error: xmlSchemaValidateElement, "
18440 "assembling schema by xsi", NULL);
18441 return (-1);
18442 }
18443 /*
18444 * NOTE: We won't react on schema parser errors here.
18445 * TODO: But a warning would be nice.
18446 */
18447 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000018448 if (wild->processContents != XML_SCHEMAS_ANY_SKIP) {
18449 xmlSchemaElementPtr decl = NULL;
18450
18451 if (node->ns != NULL)
18452 decl = xmlHashLookup3(ctxt->schema->elemDecl,
18453 node->name, node->ns->href, NULL);
18454 else
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018455 decl = xmlHashLookup3(ctxt->schema->elemDecl, node->name,
18456 NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018457 if (decl != NULL) {
18458 ctxt->node = node;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018459 ret = xmlSchemaValidateElementByDeclaration(ctxt, decl);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018460 if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018461 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000018462 "Internal error: xmlSchemaValidateAnyInternal, "
18463 "validating an element in the context of a wildcard.",
18464 NULL, NULL);
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +000018465 }
18466 return (ret);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018467 } else if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
18468 /* TODO: Change to proper error code. */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018469 xmlSchemaVWildcardErr(ctxt, XML_SCHEMAV_CVC_ELT_1,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018470 node, wild, "No matching global declaration available");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018471 /*
18472 * Evaluate IDCs even if a validation error occured.
18473 */
18474#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018475 if (xmlSchemaXPathEvaluate(ctxt,XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018476 return(-1);
18477#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +000018478 return (ctxt->err);
18479 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018480 /*
18481 * Evaluate IDCs; we need to know if an IDC field resolves to
18482 * such a node. This node has no type definition and will
18483 * definitely result in an IDC validation error if an IDC field
18484 * resolves.
18485 */
18486#ifdef IDC_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018487 if (xmlSchemaXPathEvaluate(ctxt, XML_ELEMENT_NODE) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018488 return(-1);
18489#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +000018490 }
18491 if (node->children != NULL) {
18492 child = node->children;
18493 do {
18494 if (child->type == XML_ELEMENT_NODE) {
18495 if (child->ns != NULL)
18496 uri = child->ns->href;
18497 else
18498 uri = NULL;
18499 if (xmlSchemaMatchesWildcardNs(wild, uri) == 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018500 /* TODO: error code. */
18501 xmlSchemaVWildcardErr(ctxt, XML_SCHEMAV_ELEMENT_CONTENT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000018502 child, wild,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018503 "The namespace of the element is not allowed");
Daniel Veillardc0826a72004-08-10 14:17:33 +000018504 return (ctxt->err);
18505 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018506#ifdef ELEM_INFO_ENABLED
18507 ctxt->node = child;
18508 xmlSchemaBeginElement(ctxt);
18509#endif
18510 /*
18511 * Recurse over the children.
18512 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018513 ret = xmlSchemaValidateElementByWildcardInternal(ctxt,
18514 wild, child);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018515 if (ret == -1)
18516 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018517#ifdef ELEM_INFO_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018518 if (xmlSchemaEndElement(ctxt) == -1)
18519 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018520#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +000018521 if (ret != 0)
18522 return (ret);
18523 }
18524 child = child->next;
18525 } while (child != NULL);
18526 }
18527 return (0);
18528}
18529
18530/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018531 * xmlSchemaValidateElementContByWildcard:
Daniel Veillardc0826a72004-08-10 14:17:33 +000018532 * @ctxt: a schema validation context
18533 *
18534 * Returns 0 if the element is valid, a positive error code
18535 * number otherwise and -1 in case of an internal or API error.
18536 */
18537static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018538xmlSchemaValidateElementByWildcard(xmlSchemaValidCtxtPtr ctxt,
18539 xmlSchemaTypePtr type)
Daniel Veillardc0826a72004-08-10 14:17:33 +000018540{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018541 if ((type == NULL) || (type->type != XML_SCHEMA_TYPE_ANY) ||
18542 (ctxt->node == NULL)) {
18543 xmlSchemaVCustomErr(ctxt,
18544 XML_SCHEMAV_INTERNAL, ctxt->node, NULL,
18545 "Internal error: xmlSchemaValidateElementByWildcard, "
18546 "bad arguments", NULL);
18547 return (-1);
18548 }
18549 return(xmlSchemaValidateElementByWildcardInternal(ctxt,
18550 type->attributeWildcard, ctxt->node));
Daniel Veillardc0826a72004-08-10 14:17:33 +000018551}
18552
18553/**
William M. Brack2f2a6632004-08-20 23:09:47 +000018554 * xmlSchemaValidateAnyTypeContent:
18555 * @ctxt: a schema validation context
18556 * @node: the current element
18557 *
18558 * This one validates the content of an element of the type
18559 * 'anyType'. The process contents of the wildcard of 'anyType' is "lax",
18560 * thus elements in the subtree will be validated, if a corresponding
18561 * declaration in the schema exists.
18562 *
18563 * Returns 0 if the element and its subtree is valid, a positive error code
18564 * otherwise and -1 in case of an internal or API error.
18565 */
18566static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018567xmlSchemaValidateElementByAnyType(xmlSchemaValidCtxtPtr ctxt,
18568 xmlSchemaTypePtr type)
William M. Brack2f2a6632004-08-20 23:09:47 +000018569{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018570 xmlSchemaTypePtr oldtype;
18571 xmlNodePtr top, cur;
18572 xmlSchemaElementPtr decl;
William M. Brack2f2a6632004-08-20 23:09:47 +000018573 int skipContent, ret;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018574
18575 if ((type == NULL) || (ctxt->node == NULL))
18576 return (-1);
18577
18578 if (ctxt->node->children == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +000018579 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018580
18581 oldtype = ctxt->type;
18582 top = ctxt->node;
18583 /*
18584 * STREAM: Child nodes are processed.
18585 */
18586 cur = ctxt->node->children;
18587 while (cur != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +000018588 skipContent = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018589 if (cur->type == XML_ELEMENT_NODE) {
William M. Brack2f2a6632004-08-20 23:09:47 +000018590 /*
18591 * The process contents of the wildcard is "lax", thus
18592 * we need to validate the element if a declaration
18593 * exists.
18594 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018595 if (cur->ns != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +000018596 decl = xmlHashLookup3(ctxt->schema->elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018597 cur->name, cur->ns->href, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000018598 else
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018599 decl = xmlHashLookup3(ctxt->schema->elemDecl, cur->name, NULL, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000018600 if (decl != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018601 ctxt->node = cur;
18602 ret = xmlSchemaValidateElementByDeclaration(ctxt, decl);
18603 ctxt->node = top;
William M. Brack2f2a6632004-08-20 23:09:47 +000018604 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018605 xmlSchemaVErr(ctxt, cur, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000018606 "Internal error: xmlSchemaValidateAnyTypeContent, "
18607 "validating an element in the context of a wildcard.",
18608 NULL, NULL);
18609 return (ret);
18610 } else if (ret > 0)
18611 return (ret);
18612 skipContent = 1;
18613 }
18614 }
18615 /*
18616 * Browse the full subtree, deep first.
18617 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018618 if ((skipContent == 0) && (cur->children != NULL)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000018619 /* deep first */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018620 cur = cur->children;
18621 } else if ((cur != top) && (cur->next != NULL)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000018622 /* then siblings */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018623 cur = cur->next;
18624 } else if (cur != top) {
William M. Brack2f2a6632004-08-20 23:09:47 +000018625 /* go up to parents->next if needed */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018626 while (cur != top) {
18627 if (cur->parent != NULL)
18628 cur = cur->parent;
18629 if ((cur != top) && (cur->next != NULL)) {
18630 cur = cur->next;
William M. Brack2f2a6632004-08-20 23:09:47 +000018631 break;
18632 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018633 if (cur->parent == NULL) {
18634 cur = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000018635 break;
18636 }
18637 }
18638 /* exit condition */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018639 if (cur == top)
18640 cur = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000018641 } else
18642 break;
18643 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018644 ctxt->type = oldtype;
William M. Brack2f2a6632004-08-20 23:09:47 +000018645 return (0);
18646}
18647
18648/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018649 * xmlSchemaValidateElementByComplexType:
Daniel Veillard4255d502002-04-16 15:50:10 +000018650 * @ctxt: a schema validation context
18651 * @node: the top node.
18652 *
18653 * Validate the content of an element expected to be a complex type type
18654 * xmlschema-1.html#cvc-complex-type
18655 * Validation Rule: Element Locally Valid (Complex Type)
18656 *
18657 * Returns 0 if the element is schemas valid, a positive error code
Daniel Veillard01fa6152004-06-29 17:04:39 +000018658 * number otherwise and -1 in case of internal or API error.
18659 * Note on reported errors: Although it might be nice to report
18660 * the name of the simple/complex type, used to validate the content
18661 * of a node, it is quite unnecessary: for global defined types
18662 * the local name of the element is equal to the NCName of the type,
18663 * for local defined types it makes no sense to output the internal
18664 * computed name of the type. TODO: Instead, one should attach the
18665 * struct of the type involved to the error handler - this allows
18666 * the report of any additional information by the user.
Daniel Veillard4255d502002-04-16 15:50:10 +000018667 */
18668static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018669xmlSchemaValidateElementByComplexType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018670 xmlSchemaTypePtr type,
18671 int valSimpleContent)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018672{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018673 xmlSchemaTypePtr oldtype;
18674 xmlNodePtr elem, child;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018675 int ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +000018676 const xmlChar *nsUri;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018677 xmlSchemaAttrStatePtr attrs = NULL, attrTop = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000018678
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018679 if ((ctxt == NULL) || (type->type != XML_SCHEMA_TYPE_COMPLEX))
18680 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000018681
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018682 oldtype = ctxt->type;
18683 ctxt->type = type;
18684 elem = ctxt->node;
18685
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018686 /*
18687 * Verify the attributes
18688 */
18689 /*
18690 * TODO: This "attrTop" thing is not needed any more.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018691 */
18692 /* NOTE: removed, since a check for abstract is
18693 * done in the cvc-type constraint.
18694 *
18695 *
18696 * if (type->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
18697 * xmlSchemaVComplexTypeErr(ctxt,
18698 * XML_SCHEMAV_CVC_COMPLEX_TYPE_1,
18699 * elem, type,
18700 * "The type definition is abstract");
18701 * return (XML_SCHEMAV_CVC_COMPLEX_TYPE_1);
18702 *}
18703 */
18704
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018705 attrs = ctxt->attr;
18706 attrTop = ctxt->attrTop;
18707 /*
18708 * STREAM: Attribute nodes are processed.
18709 */
18710 xmlSchemaRegisterAttributes(ctxt, elem->properties);
18711 xmlSchemaValidateAttributes(ctxt, elem, type);
18712 if (ctxt->attr != NULL)
18713 xmlSchemaFreeAttributeStates(ctxt->attr);
18714 ctxt->attr = attrs;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018715 ctxt->attrTop = attrTop;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018716
18717 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018718 * TODO: This one creates a regexp even if no content
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018719 * model was defined. Somehow ->contModel is always not NULL
18720 * for complex types, even if they are empty.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018721 * TODO: Check if the obove still occurs.
18722 */
Daniel Veillard4255d502002-04-16 15:50:10 +000018723 switch (type->contentType) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000018724 case XML_SCHEMA_CONTENT_EMPTY: {
18725 /*
18726 * 1 If the {content type} is empty, then the element information
18727 * item has no character or element information item [children].
Daniel Veillard3646d642004-06-02 19:19:14 +000018728 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000018729 /*
18730 * TODO: Is the entity stuff correct?
18731 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018732 if (xmlSchemaHasElemOrCharContent(elem) == 1) {
William M. Brack2f2a6632004-08-20 23:09:47 +000018733 xmlSchemaVComplexTypeErr(ctxt,
18734 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018735 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000018736 "Character or element content is not allowed, "
18737 "because the content type is empty");
Daniel Veillard01fa6152004-06-29 17:04:39 +000018738 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018739 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018740 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018741 case XML_SCHEMA_CONTENT_MIXED:
18742 if ((type->subtypes == NULL) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018743 (type->baseType->builtInType == XML_SCHEMAS_ANYTYPE)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018744 /*
18745 * The type has 'anyType' as its base and no content model
18746 * is defined -> use 'anyType' as the type to validate
18747 * against.
18748 */
18749 ret = xmlSchemaValidateElementByAnyType(ctxt, type->baseType);
18750 /* TODO: Handle -1. */
18751 break;
18752 }
18753 /* No break on purpose. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000018754 case XML_SCHEMA_CONTENT_ELEMENTS:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018755 {
18756 xmlRegExecCtxtPtr oldregexp = NULL;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000018757 xmlChar *values[10];
18758 int terminal, nbval = 10, nbneg;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018759
18760 /*
18761 * Content model check initialization.
18762 */
18763 if (type->contModel != NULL) {
18764 oldregexp = ctxt->regexp;
18765 ctxt->regexp = xmlRegNewExecCtxt(type->contModel,
18766 (xmlRegExecCallbacks)
18767 xmlSchemaValidateCallback, ctxt);
18768#ifdef DEBUG_AUTOMATA
18769 xmlGenericError(xmlGenericErrorContext, "====> %s\n", elem->name);
18770#endif
18771 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018772 /*
18773 * STREAM: Children are processed.
18774 */
18775 child = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018776 while (child != NULL) {
18777 if (child->type == XML_ELEMENT_NODE) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000018778 if (child->ns != NULL)
18779 nsUri = child->ns->href;
18780 else
18781 nsUri = NULL;
18782 ret = xmlRegExecPushString2(ctxt->regexp,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018783 child->name, nsUri, child);
18784 if (ctxt->err == XML_SCHEMAV_INTERNAL)
18785 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018786 /*
18787 * URGENT TODO: Could we anchor an error report
18788 * here to notify of invalid elements?
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000018789 * TODO: Perhaps it would be better to report
18790 * only the first erroneous element and then break.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018791 */
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000018792#ifdef DEBUG_AUTOMATA
Daniel Veillard01fa6152004-06-29 17:04:39 +000018793 if (ret < 0)
18794 xmlGenericError(xmlGenericErrorContext,
18795 " --> %s Error\n", child->name);
William M. Bracke7091952004-05-11 15:09:58 +000018796 else
18797 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard01fa6152004-06-29 17:04:39 +000018798 " --> %s\n", child->name);
18799#endif
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018800 if (ret < 0) {
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000018801 xmlRegExecErrInfo(ctxt->regexp, NULL, &nbval, &nbneg,
18802 &values[0], &terminal);
18803 xmlSchemaVComplexTypeElemErr(ctxt,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018804 XML_SCHEMAV_ELEMENT_CONTENT,
18805 child, NULL/* type */,
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000018806 "This element is not expected",
18807 nbval, nbneg, values);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018808 ret = 1;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000018809 /*
18810 * Note that this will skip further validation of the
18811 * content.
18812 */
18813 break;
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018814 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000018815 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) &&
18816 /*
18817 * TODO: Ask Daniel if this are all character nodes.
18818 */
18819 (((child->type == XML_TEXT_NODE) && (!IS_BLANK_NODE(child))) ||
18820 (child->type == XML_ENTITY_NODE) ||
18821 (child->type == XML_ENTITY_REF_NODE) ||
18822 (child->type == XML_CDATA_SECTION_NODE))) {
18823 /*
18824 * 2.3 If the {content type} is element-only, then the
18825 * element information item has no character information
18826 * item [children] other than those whose [character
18827 * code] is defined as a white space in [XML 1.0 (Second
18828 * Edition)].
18829 */
William M. Brack2f2a6632004-08-20 23:09:47 +000018830 xmlSchemaVComplexTypeErr(ctxt,
18831 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018832 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000018833 "Character content is not allowed, "
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018834 "because the content type is element-only");
18835 ret = 1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018836 break;
18837 }
18838 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018839 }
18840 /*
18841 * Content model check finalization.
18842 */
18843 if (type->contModel != NULL) {
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000018844 if (ret == 0) {
18845 xmlRegExecNextValues(ctxt->regexp, &nbval, &nbneg,
18846 &values[0], &terminal);
18847 if (nbval + nbneg != 0) {
18848 /*
18849 * If a next value still exists, I does not have to
18850 * mean that there's an element missing, since it
18851 * might be an optional element. So double check it.
18852 */
18853 ret = xmlRegExecPushString(ctxt->regexp,
18854 NULL, NULL);
18855 if (ret <= 0) {
18856 ret = 1;
18857 xmlSchemaVComplexTypeElemErr(ctxt,
18858 XML_SCHEMAV_ELEMENT_CONTENT,
18859 elem, type, "Missing child element(s)",
18860 nbval, nbneg, values);
18861 } else
18862 ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018863#ifdef DEBUG_AUTOMATA
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000018864 xmlGenericError(xmlGenericErrorContext,
18865 "====> %s : %d\n", elem->name, ret);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018866#endif
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000018867 }
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018868#ifdef DEBUG_CONTENT
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000018869 if (ret == 0)
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018870 xmlGenericError(xmlGenericErrorContext,
18871 "Element %s content check succeeded\n",
18872 elem->name);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018873#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018874 }
18875 xmlRegFreeExecCtxt(ctxt->regexp);
18876 ctxt->regexp = oldregexp;
18877 }
18878 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000018879 break;
18880 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018881 case XML_SCHEMA_CONTENT_BASIC:
18882 /*
18883 * If the simple content was already validated
18884 * (e.g. a default value), the content need not
18885 * to be validated again.
18886 */
18887 if (valSimpleContent == 1) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000018888 xmlChar *value = NULL;
18889 /*
18890 * We hit a complexType with a simpleContent resolving
18891 * to a user derived or built-in simple type.
William M. Brack2f2a6632004-08-20 23:09:47 +000018892 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000018893 /*
18894 * 2.2 If the {content type} is a simple type definition,
18895 * then the element information item has no element
18896 * information item [children], and the ·normalized value·
18897 * of the element information item is ·valid· with respect
18898 * to that simple type definition as defined by String
18899 * Valid (§3.14.4).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018900 */
18901 /*
18902 * STREAM: Children are processed.
18903 */
18904 child = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018905 while (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018906 /*
18907 * TODO: Could the entity stuff produce elements
18908 * as well?
18909 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000018910 if (child->type == XML_ELEMENT_NODE) {
William M. Brack2f2a6632004-08-20 23:09:47 +000018911 xmlSchemaVComplexTypeErr(ctxt,
18912 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018913 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000018914 "Element content is not allowed, because "
18915 "the content type is a simple type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000018916 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
18917 break;
18918 }
18919 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018920 }
18921 ctxt->node = elem;
18922 ctxt->cur = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018923 if (ret == 0) {
18924 /*
18925 * Validate the character content against a simple type.
Daniel Veillard3646d642004-06-02 19:19:14 +000018926 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018927 /*
18928 * STREAM: Children are processed.
18929 */
18930 if (elem->children == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000018931 value = NULL;
18932 else
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018933 value = xmlNodeGetContent(elem);
18934 /*
18935 * URGENT TODO: Should facets for the simple type validation be
18936 * disabled, if the derivation of facets for complex types
18937 * is implemented?
18938 */
18939 /*
18940 * NOTE: This call won't check the correct types of the
18941 * content nodes, since this should be done here.
18942 */
18943 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type, value, 1, 1, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000018944 if (ret > 0) {
18945 /*
18946 * NOTE: Although an error will be reported by
18947 * xmlSchemaValidateSimpleTypeValue, the spec wants
18948 * a specific complex type error to be reported
18949 * additionally.
18950 */
18951 xmlSchemaVComplexTypeErr(ctxt,
18952 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018953 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000018954 "The character content is not valid");
Daniel Veillard01fa6152004-06-29 17:04:39 +000018955 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
18956 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018957 xmlSchemaVErr(ctxt, elem, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000018958 "Internal error: xmlSchemaValidateComplexType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000018959 "Element '%s': Error while validating character "
18960 "content against complex type '%s'.\n",
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018961 elem->name, type->name);
18962 if (value != NULL)
18963 xmlFree(value);
18964 ctxt->type = oldtype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018965 return (-1);
18966 }
William M. Brack2f2a6632004-08-20 23:09:47 +000018967 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000018968 if (ret == 0) {
18969 /*
18970 * Apply facets of the complexType. Be sure to pass the
18971 * built-in type to xmlSchemaValidateFacetsInternal.
18972 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018973 /* URGENT TODO: I don't know yet if the facets of the simple type
Daniel Veillard01fa6152004-06-29 17:04:39 +000018974 * are used, or if the facets, defined by this complex type,
18975 * are to be used only. This here applies both facet sets.
18976 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000018977
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018978 ret = xmlSchemaValidateFacetsInternal(ctxt,
18979 type, value, 0, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000018980 if (ret > 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +000018981 xmlSchemaVComplexTypeErr(ctxt,
18982 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018983 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000018984 "The character content is not valid");
Daniel Veillard01fa6152004-06-29 17:04:39 +000018985 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
18986 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018987 xmlSchemaVErr(ctxt, elem, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000018988 "Internal error: xmlSchemaValidateComplexType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000018989 "Element '%s': Error while validating character "
18990 "content against complex type '%s'; failed to "
Daniel Veillard01fa6152004-06-29 17:04:39 +000018991 "apply facets.\n",
18992 type->name, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018993 if (value != NULL)
18994 xmlFree(value);
18995 ctxt->type = oldtype;
18996 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000018997 }
18998 }
18999 if (value != NULL)
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019000 xmlFree(value);
19001
Daniel Veillard01fa6152004-06-29 17:04:39 +000019002 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019003 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019004 default:
19005 TODO xmlGenericError(xmlGenericErrorContext,
19006 "unimplemented content type %d\n",
19007 type->contentType);
Daniel Veillard4255d502002-04-16 15:50:10 +000019008 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019009 ctxt->type = oldtype;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019010 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000019011}
19012
19013/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019014 * xmlSchemaValidateElementByType:
Daniel Veillard4255d502002-04-16 15:50:10 +000019015 * @ctxt: a schema validation context
19016 * @elem: an element
19017 * @type: the list of type declarations
19018 *
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019019 * Validation Rule: Element Locally Valid (Type).
Daniel Veillard4255d502002-04-16 15:50:10 +000019020 *
19021 * Returns 0 if the element is schemas valid, a positive error code
19022 * number otherwise and -1 in case of internal or API error.
19023 */
19024static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019025xmlSchemaValidateElementByType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019026 xmlSchemaTypePtr type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019027 int isNil,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019028 int valSimpleContent)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019029{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019030 int ret;
Daniel Veillard4255d502002-04-16 15:50:10 +000019031
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019032
19033 if ((ctxt == NULL) || (type == NULL)) {
19034 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_INTERNAL, NULL, NULL,
19035 "Internal error: xmlSchemaValidateElementByType, "
19036 "bad arguments", NULL);
19037 return (-1);
19038 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019039 /*
19040 * This one is called by "xmlSchemaValidateElementByDeclaration".
19041 * It will forward to the proper validation
19042 * procedures for the given type.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019043 */
19044 if (type == NULL) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019045 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019046 XML_SCHEMAV_CVC_TYPE_1,
19047 ctxt->node, NULL,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019048 "The type definition is absent", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019049 return (XML_SCHEMAV_CVC_TYPE_1);
19050 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019051
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019052 if (type->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019053 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019054 XML_SCHEMAV_CVC_TYPE_2,
19055 ctxt->node, type,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019056 "The type definition is abstract", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019057 return (XML_SCHEMAV_CVC_TYPE_2);
19058 }
19059
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019060 switch (type->type) {
19061 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019062 ret = xmlSchemaValidateElementByComplexType(ctxt, type,
19063 valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019064 break;
19065 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019066 ret = xmlSchemaValidateElementBySimpleType(ctxt, type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019067 isNil, valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019068 break;
19069 case XML_SCHEMA_TYPE_BASIC:
19070 if (type->builtInType == XML_SCHEMAS_ANYTYPE)
19071 ret = xmlSchemaValidateElementByAnyType(ctxt, type);
19072 else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019073 ret = xmlSchemaValidateElementBySimpleType(ctxt, type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019074 isNil, valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019075 break;
19076 default:
19077 ret = -1;
19078 break;
19079 }
19080 if (ret == -1)
19081 return (-1);
19082 else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019083 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000019084}
19085
19086
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019087static int
19088xmlSchemaCheckAttrLocallyValid(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019089 xmlSchemaAttrStatePtr state)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019090{
19091 xmlChar *value;
19092 const xmlChar *defValue;
19093 xmlSchemaValPtr defVal;
19094 int fixed;
19095 int ret;
19096
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019097 if (ctxt->attrInfo->typeDef == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019098 state->state = XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED;
19099 return (XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED);
19100 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019101 ctxt->node = ctxt->attrInfo->node;
19102 ctxt->cur = ctxt->node->children;
19103 value = xmlNodeListGetString(ctxt->node->doc, ctxt->cur, 1);
19104
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019105 /*
19106 * NOTE: This call also checks the content nodes for correct type.
19107 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019108 ret = xmlSchemaValidateSimpleTypeValue(ctxt, ctxt->attrInfo->typeDef,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019109 value, 1, 1, 1, 1);
19110
19111 /*
19112 * Handle 'fixed' attributes.
19113 */
19114 if (ret > 0) {
19115 state->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
19116 /*
19117 * NOTE: Fixed value constraints will be not
19118 * applied if the value was invalid, because:
19119 * 1. The validation process does not return a precomputed
19120 * value.
19121 * 2. An invalid value implies a violation of a fixed
19122 * value constraint.
19123 */
19124 } else if (ret == 0) {
19125 state->state = XML_SCHEMAS_ATTR_CHECKED;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019126 if (xmlSchemaGetEffectiveValueConstraint(
19127 (xmlSchemaAttributePtr) ctxt->attrInfo->decl,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019128 &fixed, &defValue, &defVal) && (fixed == 1)) {
19129 /*
19130 * cvc-au : Attribute Locally Valid (Use)
19131 * For an attribute information item to be·valid·
19132 * with respect to an attribute use its ·normalized
19133 * value· must match the canonical lexical representation
19134 * of the attribute use's {value constraint} value, if it
19135 * is present and fixed.
19136 */
19137 /*
19138 * NOTE: the validation context holds in ctxt->value the
19139 * precomputed value of the attribute; well for some types,
19140 * fallback to string comparison if no computed value
19141 * exists.
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019142 * TODO: Use the *normalized* value and the *canonical* fixed
19143 * value.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019144 */
19145 if (((ctxt->value != NULL) &&
19146 (xmlSchemaCompareValues(ctxt->value, defVal) != 0)) ||
19147 ((ctxt->value == NULL) &&
19148 (! xmlStrEqual(defValue, BAD_CAST value)))) {
19149 state->state =
19150 XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE;
19151 }
19152 }
19153 }
19154 if (value != NULL) {
19155 xmlFree(value);
19156 }
19157 return (ret);
19158}
19159
Daniel Veillard4255d502002-04-16 15:50:10 +000019160/**
19161 * xmlSchemaValidateAttributes:
19162 * @ctxt: a schema validation context
19163 * @elem: an element
Daniel Veillard3646d642004-06-02 19:19:14 +000019164 * @type: the complexType holding the attribute uses
Daniel Veillard4255d502002-04-16 15:50:10 +000019165 *
19166 * Validate the attributes of an element.
19167 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000019168 * 1. Existent, invalid attributes are reported in the form
19169 * "prefix:localName".
19170 * Reason: readability - it is easier to find the actual XML
19171 * representation of the attributes QName.
19172 * 2. Missing attributes are reported in the form
19173 * {"URI", "localName"}.
19174 * This is necessary, since the the prefix need not to be declared
19175 * at all, and thus is not computable.
19176 *
Daniel Veillard4255d502002-04-16 15:50:10 +000019177 * Returns 0 if the element is schemas valid, a positive error code
19178 * number otherwise and -1 in case of internal or API error.
19179 */
19180static int
Daniel Veillard3646d642004-06-02 19:19:14 +000019181xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem, xmlSchemaTypePtr type)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019182{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019183 const xmlChar *nsURI;
Daniel Veillard3646d642004-06-02 19:19:14 +000019184 int ret;
19185 xmlAttrPtr attr; /* An attribute on the element. */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019186 const xmlChar *defValue;
19187 xmlSchemaValPtr defVal;
19188 int fixed;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019189 xmlSchemaAttributeLinkPtr attrUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000019190 xmlSchemaAttributePtr attrDecl;
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000019191 int found;
William M. Brack803812b2004-06-03 02:11:24 +000019192 xmlSchemaAttrStatePtr curState, reqAttrStates = NULL, reqAttrStatesTop = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019193 xmlSchemaAttrStatePtr defAttrStates = NULL, defAttrStatesTop = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019194 xmlNodePtr oldnode;
Daniel Veillard3646d642004-06-02 19:19:14 +000019195#ifdef DEBUG_ATTR_VALIDATION
19196 int redundant = 0;
19197#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000019198
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019199
Daniel Veillardc0826a72004-08-10 14:17:33 +000019200 /*
19201 * Allow all attributes if the type is anyType.
19202 */
19203 if (type == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE))
19204 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019205
19206 oldnode = ctxt->node;
19207 if (type != NULL)
19208 attrUse = type->attributeUses;
Daniel Veillard3646d642004-06-02 19:19:14 +000019209 while (attrUse != NULL) {
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000019210 found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000019211 attrDecl = attrUse->attr;
19212#ifdef DEBUG_ATTR_VALIDATION
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019213 printf("attr use - name: %s\n", xmlSchemaGetAttrName(attrDecl));
Daniel Veillard3646d642004-06-02 19:19:14 +000019214 printf("attr use - use: %d\n", attrDecl->occurs);
19215#endif
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019216 for (curState = ctxt->attr; curState != NULL; curState = curState->next) {
Daniel Veillard3646d642004-06-02 19:19:14 +000019217
19218 if (curState->decl == attrUse->attr) {
19219#ifdef DEBUG_ATTR_VALIDATION
19220 redundant = 1;
19221#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019222 }
Daniel Veillard3646d642004-06-02 19:19:14 +000019223 attr = curState->attr;
19224#ifdef DEBUG_ATTR_VALIDATION
19225 printf("attr - name: %s\n", attr->name);
19226 if (attr->ns != NULL)
19227 printf("attr - ns: %s\n", attr->ns->href);
19228 else
19229 printf("attr - ns: none\n");
19230#endif
19231 /* TODO: Can this ever happen? */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019232 if (attr == NULL)
19233 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000019234 if (attrDecl->ref != NULL) {
19235 if (!xmlStrEqual(attr->name, attrDecl->ref))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019236 continue;
19237 if (attr->ns != NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000019238 if ((attrDecl->refNs == NULL) ||
19239 (!xmlStrEqual(attr->ns->href, attrDecl->refNs)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019240 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000019241 } else if (attrDecl->refNs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019242 continue;
19243 }
19244 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000019245 if (!xmlStrEqual(attr->name, attrDecl->name))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019246 continue;
19247 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +000019248 * handle the namespaces checks here
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019249 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000019250 if (attr->ns == NULL) {
19251 /*
William M. Bracke7091952004-05-11 15:09:58 +000019252 * accept an unqualified attribute only if the target
19253 * namespace of the declaration is absent.
Daniel Veillardbe9c6322003-11-22 20:37:51 +000019254 */
Daniel Veillard3646d642004-06-02 19:19:14 +000019255 if (attrDecl->targetNamespace != NULL)
William M. Bracke7091952004-05-11 15:09:58 +000019256 /*
19257 * This check was removed, since the target namespace
19258 * was evaluated during parsing and already took
19259 * "attributeFormDefault" into account.
19260 */
19261 /* ((attributes->flags & XML_SCHEMAS_ATTR_NSDEFAULT) == 0)) */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000019262 continue;
19263 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000019264 if (attrDecl->targetNamespace == NULL)
Daniel Veillardbe9c6322003-11-22 20:37:51 +000019265 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000019266 if (!xmlStrEqual(attrDecl->targetNamespace,
Daniel Veillardbe9c6322003-11-22 20:37:51 +000019267 attr->ns->href))
19268 continue;
19269 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019270 }
Daniel Veillard3646d642004-06-02 19:19:14 +000019271#ifdef DEBUG_ATTR_VALIDATION
19272 printf("found\n");
19273#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019274 found = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +000019275 curState->decl = attrDecl;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019276 curState->state = XML_SCHEMAS_ATTR_VALIDATE_VALUE;
19277 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019278 ret = xmlSchemaCheckAttrLocallyValid(ctxt, attrDecl, curState, attr);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019279 */
Daniel Veillard3646d642004-06-02 19:19:14 +000019280 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019281 if (!found) {
19282 if (attrDecl->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
19283 xmlSchemaAttrStatePtr tmp;
19284
Daniel Veillard3646d642004-06-02 19:19:14 +000019285#ifdef DEBUG_ATTR_VALIDATION
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019286 printf("required attr not found\n");
Daniel Veillard3646d642004-06-02 19:19:14 +000019287#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019288 /*
19289 * Add a new dummy attribute state.
19290 */
19291 tmp = (xmlSchemaAttrStatePtr) xmlMalloc(sizeof(xmlSchemaAttrState));
19292 if (tmp == NULL) {
19293 xmlSchemaVErrMemory(ctxt, "registering required attributes", NULL);
19294 ctxt->node = oldnode;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019295 goto fatal_exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019296 }
19297 tmp->attr = NULL;
19298 tmp->state = XML_SCHEMAS_ATTR_MISSING;
19299 tmp->decl = attrDecl;
19300 tmp->next = NULL;
19301
19302 if (reqAttrStates == NULL) {
19303 reqAttrStates = tmp;
19304 reqAttrStatesTop = tmp;
19305 } else {
19306 reqAttrStatesTop->next = tmp;
19307 reqAttrStatesTop = tmp;
19308 }
19309 } else if ((attrDecl->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
19310 (xmlSchemaGetEffectiveValueConstraint(attrDecl,
19311 &fixed, &defValue, &defVal))) {
19312 xmlSchemaAttrStatePtr tmp;
19313 /*
19314 * Handle non existent default/fixed attributes.
19315 */
19316 tmp = (xmlSchemaAttrStatePtr)
19317 xmlMalloc(sizeof(xmlSchemaAttrState));
19318 if (tmp == NULL) {
19319 xmlSchemaVErrMemory(ctxt,
19320 "registering schema specified attributes", NULL);
19321 ctxt->node = oldnode;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019322 goto fatal_exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019323 }
19324 tmp->attr = NULL;
19325 tmp->state = XML_SCHEMAS_ATTR_DEFAULT;
19326 tmp->decl = attrDecl;
19327 tmp->value = defValue;
19328 tmp->next = NULL;
19329
19330 if (defAttrStates == NULL) {
19331 defAttrStates = tmp;
19332 defAttrStates = tmp;
19333 } else {
19334 defAttrStates->next = tmp;
19335 defAttrStatesTop = tmp;
19336 }
19337 }
Daniel Veillard3646d642004-06-02 19:19:14 +000019338 }
19339 attrUse = attrUse->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000019340 }
Daniel Veillard3646d642004-06-02 19:19:14 +000019341 /*
19342 * Add required attributes to the attribute states of the context.
19343 */
19344 if (reqAttrStates != NULL) {
19345 if (ctxt->attr == NULL) {
19346 ctxt->attr = reqAttrStates;
19347 } else {
19348 ctxt->attrTop->next = reqAttrStates;
19349 }
19350 ctxt->attrTop = reqAttrStatesTop;
Daniel Veillardc0826a72004-08-10 14:17:33 +000019351 }
Daniel Veillard3646d642004-06-02 19:19:14 +000019352 /*
19353 * Process wildcards.
19354 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019355
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019356 if ((type != NULL) && (type->attributeWildcard != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000019357#ifdef DEBUG_ATTR_VALIDATION
19358 xmlSchemaWildcardNsPtr ns;
19359 printf("matching wildcard: [%d] of complexType: %s\n", type->attributeWildcard, type->name);
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019360 if (type->attributeWildcard->processContents ==
19361 XML_SCHEMAS_ANY_LAX)
19362 printf("processContents: lax\n");
19363 else if (type->attributeWildcard->processContents ==
19364 XML_SCHEMAS_ANY_STRICT)
19365 printf("processContents: strict\n");
19366 else
19367 printf("processContents: skip\n");
Daniel Veillard3646d642004-06-02 19:19:14 +000019368 if (type->attributeWildcard->any)
19369 printf("type: any\n");
19370 else if (type->attributeWildcard->negNsSet != NULL) {
19371 printf("type: negated\n");
19372 if (type->attributeWildcard->negNsSet->value == NULL)
19373 printf("ns: (absent)\n");
19374 else
19375 printf("ns: %s\n", type->attributeWildcard->negNsSet->value);
19376 } else if (type->attributeWildcard->nsSet != NULL) {
19377 printf("type: set\n");
19378 ns = type->attributeWildcard->nsSet;
19379 while (ns != NULL) {
19380 if (ns->value == NULL)
19381 printf("ns: (absent)\n");
19382 else
19383 printf("ns: %s\n", ns->value);
19384 ns = ns->next;
19385 }
19386 } else
19387 printf("empty\n");
19388
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019389
19390#endif
Daniel Veillard3646d642004-06-02 19:19:14 +000019391 curState = ctxt->attr;
19392 while (curState != NULL) {
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019393 if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
19394 if (curState->attr->ns != NULL)
19395 nsURI = curState->attr->ns->href;
19396 else
19397 nsURI = NULL;
19398 if (xmlSchemaMatchesWildcardNs(type->attributeWildcard,
19399 nsURI)) {
19400 /*
19401 * Handle processContents.
19402 */
19403 if ((type->attributeWildcard->processContents ==
19404 XML_SCHEMAS_ANY_LAX) ||
19405 (type->attributeWildcard->processContents ==
19406 XML_SCHEMAS_ANY_STRICT)) {
19407
19408 attr = curState->attr;
19409 attrDecl = xmlSchemaGetAttribute(ctxt->schema,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019410 attr->name, nsURI);
19411 curState->decl = attrDecl;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019412 if (attrDecl != NULL) {
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019413 curState->decl = attrDecl;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019414 curState->state = XML_SCHEMAS_ATTR_VALIDATE_VALUE;
19415 /* TODO
19416 ret = xmlSchemaCheckAttrLocallyValid(ctxt, attrDecl, curState, attr);
19417 */
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019418 } else if (type->attributeWildcard->processContents ==
19419 XML_SCHEMAS_ANY_LAX) {
19420 curState->state = XML_SCHEMAS_ATTR_CHECKED;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019421 } else
19422 curState->state = XML_SCHEMAS_ATTR_WILD_NO_DECL;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019423 } else
Daniel Veillard3646d642004-06-02 19:19:14 +000019424 curState->state = XML_SCHEMAS_ATTR_CHECKED;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019425 }
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019426 }
Daniel Veillard3646d642004-06-02 19:19:14 +000019427 curState = curState->next;
19428 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019429 }
19430
Daniel Veillardc0826a72004-08-10 14:17:33 +000019431 if (ctxt->attr != NULL) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019432 int valueNeeded;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019433
19434 /*
19435 * Validate the value of the attribute.
19436 */
19437 if (ctxt->value != NULL) {
19438 xmlSchemaFreeValue(ctxt->value);
19439 ctxt->value = NULL;
19440 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000019441 curState = ctxt->attr;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019442 while ((curState != NULL) && (curState != ctxt->attrTop->next)) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019443 valueNeeded = 0;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019444 switch (curState->state) {
19445 case XML_SCHEMAS_ATTR_VALIDATE_VALUE:
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019446
19447 /*
19448 * Create an attribute info if needed.
19449 */
19450 if (ctxt->attrInfo == NULL) {
19451 ctxt->attrInfo = (xmlSchemaElemInfoPtr)
19452 xmlMalloc(sizeof(xmlSchemaElemInfo));
19453 if (ctxt->attrInfo == NULL) {
19454 xmlSchemaVErrMemory(ctxt,
19455 "allocating an attribute info", NULL);
19456 goto fatal_exit;
19457 }
19458 }
19459 /*
19460 * Init the attribute info.
19461 */
19462 ctxt->attrInfo->flags = 0;
19463 ctxt->attrInfo->node = (xmlNodePtr) curState->attr;
19464 ctxt->attrInfo->decl = (xmlSchemaTypePtr) curState->decl;
19465 ctxt->attrInfo->value = NULL;
19466 if (curState->decl != NULL)
19467 ctxt->attrInfo->typeDef = curState->decl->subtypes;
19468 else
19469 ctxt->attrInfo->typeDef = NULL;
19470 if (curState->attr->ns != NULL)
19471 ctxt->attrInfo->namespaceName =
19472 curState->attr->ns->href;
19473 else
19474 ctxt->attrInfo->namespaceName = NULL;
19475 ctxt->attrInfo->localName = curState->attr->name;
19476
19477 ctxt->nodeInfo = ctxt->attrInfo;
19478
19479#ifdef IDC_ENABLED
19480 /*
19481 * Evaluate IDCs.
19482 */
19483 if (ctxt->xpathStates != NULL) {
19484 ret = xmlSchemaXPathEvaluate(ctxt,
19485 XML_ATTRIBUTE_NODE);
19486 if (ret == -1)
19487 goto fatal_exit;
19488 }
19489
19490#endif
19491 ret = xmlSchemaCheckAttrLocallyValid(ctxt, curState);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019492 if (ret == -1)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019493 goto fatal_exit;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019494 if ((ret != 0) && (ctxt->value != NULL)) {
19495 xmlSchemaFreeValue(ctxt->value);
19496 ctxt->value = NULL;
19497 }
19498 /* No break on purpose. */
19499 case XML_SCHEMAS_ATTR_CHECKED:
19500#ifdef IDC_ENABLED
19501 if (ctxt->xpathStates != NULL) {
19502 /*
19503 * Evaluate IDCs.
19504 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019505 if (ctxt->value != NULL) {
19506 ctxt->attrInfo->value = ctxt->value;
19507 ctxt->value = NULL;
19508 }
19509 if (xmlSchemaXPathProcessHistory(ctxt, ctxt->depth +1) == -1)
19510 goto fatal_exit;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019511 }
19512 break;
19513#endif
19514 default:
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019515 break;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019516 }
19517 curState = curState->next;
19518 }
19519
19520 /*
19521 * Report missing and illegal attributes.
19522 */
19523 curState = ctxt->attr;
19524 while ((curState != NULL) && (curState != ctxt->attrTop->next)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000019525 if (curState->state != XML_SCHEMAS_ATTR_CHECKED) {
19526 attr = curState->attr;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019527 if (curState->decl != NULL) {
19528 if (curState->decl->ref != NULL)
19529 attrDecl = curState->decl->refDecl;
19530 else
19531 attrDecl = curState->decl;
19532 } else
19533 attrDecl = NULL;
19534 if (curState->state == XML_SCHEMAS_ATTR_MISSING) {
19535 xmlSchemaVMissingAttrErr(ctxt, elem, attrDecl);
19536 } else if (curState->state ==
19537 XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED) {
19538 xmlSchemaVCustomErr(ctxt,
19539 XML_SCHEMAV_CVC_ATTRIBUTE_2,
19540 (xmlNodePtr) attr,
19541 (xmlSchemaTypePtr) attrDecl,
19542 "The type definition is absent",
19543 NULL);
19544 } else if (curState->state ==
19545 XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE) {
19546 xmlSchemaVCustomErr(ctxt,
19547 XML_SCHEMAV_CVC_AU,
19548 (xmlNodePtr) attr, (xmlSchemaTypePtr) attrDecl,
19549 "The value does not match the fixed value "
19550 "constraint", NULL);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019551 } else if (curState->state == XML_SCHEMAS_ATTR_WILD_NO_DECL) {
19552 xmlSchemaVWildcardErr(ctxt,
19553 XML_SCHEMAV_CVC_WILDCARD,
19554 (xmlNodePtr) attr,
19555 type->attributeWildcard,
19556 "No global attribute declaration found, but "
19557 "stipulated by the strict processContents of "
19558 "the wildcard");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019559 } else if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000019560 /* TODO: "prohibited" won't ever be touched here!.
19561 (curState->state == XML_SCHEMAS_ATTR_PROHIBITED))
19562 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019563 /*
19564 * TODO: One might report different error messages
19565 * for the following errors.
19566 */
19567 if ((type == NULL) || (type->attributeWildcard == NULL)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000019568 xmlSchemaVIllegalAttrErr(ctxt,
19569 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, attr);
19570 } else {
19571 xmlSchemaVIllegalAttrErr(ctxt,
19572 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, attr);
19573 }
19574 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000019575 }
19576 curState = curState->next;
19577 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019578 }
19579
19580 /*
19581 * Add missing default/fixed attributes.
19582 */
19583 if (ctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
19584 curState = defAttrStates;
19585 while (curState != NULL) {
19586 attrDecl = curState->decl;
19587 if (attrDecl->ref != NULL)
19588 attrDecl = attrDecl->refDecl;
19589 /*
19590 * PSVI: Add a new attribute node to the current element.
19591 */
19592 if (attrDecl->targetNamespace == NULL) {
19593 xmlNewProp(elem, attrDecl->name, curState->value);
19594 } else {
19595 xmlNsPtr ns;
19596
19597 ns = xmlSearchNsByHref(elem->doc, elem,
19598 attrDecl->targetNamespace);
19599 if (ns == NULL) {
19600 xmlChar prefix[12];
19601 int counter = 1;
19602
19603 attr = curState->attr;
19604 /*
19605 * Create a namespace declaration on the validation
19606 * root node if no namespace declaration is in scope.
19607 */
19608 snprintf((char *) prefix, sizeof(prefix), "p");
19609 /*
19610 * This is somehow not performant, since the ancestor
19611 * axis beyond @elem will be searched as well.
19612 */
19613 ns = xmlSearchNs(elem->doc, elem, BAD_CAST prefix);
19614 while (ns != NULL) {
19615 if (counter > 1000) {
19616 xmlSchemaVErr(ctxt, (xmlNodePtr) attr,
19617 XML_SCHEMAV_INTERNAL,
19618 "Internal error: xmlSchemaValidateAttributes, "
19619 "could not compute a ns prefix for "
19620 "default/fixed attribute '%s'.\n",
19621 attrDecl->name, NULL);
19622
19623 break;
19624 }
19625 snprintf((char *) prefix,
19626 sizeof(prefix), "p%d", counter++);
19627 ns = xmlSearchNs(elem->doc, elem,
19628 BAD_CAST prefix);
19629 }
19630 if (ns == NULL) {
19631 ns = xmlNewNs(ctxt->validationRoot,
19632 attrDecl->targetNamespace, BAD_CAST prefix);
19633 xmlNewNsProp(elem, ns, attrDecl->name,
19634 curState->value);
19635 }
19636 } else {
19637 xmlNewNsProp(elem, ns, attrDecl->name,
19638 curState->value);
19639 }
19640 }
19641 curState = curState->next;
19642 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000019643 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019644 ret = ctxt->err;
19645 goto exit;
19646
19647fatal_exit:
19648 ret = -1;
19649
19650exit:
19651
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019652 if (defAttrStates != NULL)
19653 xmlSchemaFreeAttributeStates(defAttrStates);
19654
Daniel Veillard3646d642004-06-02 19:19:14 +000019655#ifdef DEBUG_ATTR_VALIDATION
19656 if (redundant)
19657 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019658 "xmlSchemaValidateAttributes: redundant call by "
19659 "type: %s\n", type->name);
Daniel Veillard3646d642004-06-02 19:19:14 +000019660#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019661 ctxt->nodeInfo = ctxt->elemInfos[ctxt->depth];
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019662 ctxt->node = oldnode;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019663 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000019664}
19665
19666/**
19667 * xmlSchemaValidateElement:
19668 * @ctxt: a schema validation context
19669 * @elem: an element
19670 *
19671 * Validate an element in a tree
19672 *
19673 * Returns 0 if the element is schemas valid, a positive error code
19674 * number otherwise and -1 in case of internal or API error.
19675 */
19676static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019677xmlSchemaValidateElement(xmlSchemaValidCtxtPtr ctxt)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019678{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019679 xmlSchemaElementPtr elemDecl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019680 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000019681
Daniel Veillardc0826a72004-08-10 14:17:33 +000019682 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019683 * This one is called by xmlSchemaValidateDocument and
19684 * xmlSchemaValidateOneElement.
19685 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019686 if (ctxt->schema == NULL) {
19687 /*
19688 * No schema was specified at time of creation of the validation
19689 * context. Use xsi:schemaLocation and xsi:noNamespaceSchemaLocation
19690 * of the instance to build a schema.
19691 */
19692 if (ctxt->pctxt == NULL)
19693 ctxt->pctxt = xmlSchemaNewParserCtxt("*");
19694 if (ctxt->pctxt == NULL)
19695 return (-1);
19696 ctxt->schema = xmlSchemaNewSchema(ctxt->pctxt);
19697 if (ctxt->schema == NULL)
19698 return (-1);
19699 /* TODO: assign user data. */
19700 ctxt->pctxt->error = ctxt->error;
19701 ctxt->pctxt->warning = ctxt->warning;
19702 ctxt->xsiAssemble = 1;
19703 } else
19704 ctxt->xsiAssemble = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019705 /*
19706 * Assemble new schemata using xsi.
Daniel Veillardc0826a72004-08-10 14:17:33 +000019707 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019708 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019709 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
19710 if (ret == -1) {
19711 xmlSchemaVCustomErr(ctxt,
19712 XML_SCHEMAV_INTERNAL,
19713 ctxt->node, NULL,
19714 "Internal error: xmlSchemaValidateElement, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019715 "assembling schema by xsi", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019716 }
19717 /*
19718 * NOTE: We won't react on schema parser errors here.
19719 * TODO: But a warning would be nice.
19720 */
19721 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019722 if (ret != -1) {
19723 if (ctxt->node->ns != NULL)
19724 elemDecl = xmlSchemaGetElem(ctxt->schema, ctxt->node->name,
19725 ctxt->node->ns->href);
19726 else
19727 elemDecl = xmlSchemaGetElem(ctxt->schema, ctxt->node->name, NULL);
19728
19729 if (elemDecl == NULL) {
19730 xmlSchemaVCustomErr(ctxt,
19731 XML_SCHEMAV_CVC_ELT_1,
19732 ctxt->node, NULL,
19733 "No matching global declaration available", NULL);
19734 ret = XML_SCHEMAV_CVC_ELT_1;
19735 } else {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019736#ifdef IDC_ENABLED
19737 /*
19738 * Augment the IDC definitions.
19739 */
19740 if (ctxt->schema->idcDef != NULL) {
19741 xmlHashScan(ctxt->schema->idcDef,
19742 (xmlHashScanner) xmlSchemaAugmentIDC, ctxt);
19743 }
19744#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019745#ifdef ELEM_INFO_ENABLED
19746 ctxt->depth = -1;
19747 xmlSchemaBeginElement(ctxt);
19748#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019749 ret = xmlSchemaValidateElementByDeclaration(ctxt, elemDecl);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019750#ifdef ELEM_INFO_ENABLED
19751 xmlSchemaEndElement(ctxt);
19752#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019753 if (ret < 0) {
19754 xmlSchemaVCustomErr(ctxt,
19755 XML_SCHEMAV_INTERNAL, ctxt->node, NULL,
19756 "Internal error: xmlSchemaValidateElement, "
19757 "calling validation by declaration", NULL);
19758 }
19759 }
19760 }
19761 /* ctxt->xsiAssemble = 0; */
19762 if (ctxt->xsiAssemble) {
19763 if (ctxt->schema != NULL) {
19764 xmlSchemaFree(ctxt->schema);
19765 ctxt->schema = NULL;
19766 }
Daniel Veillard4255d502002-04-16 15:50:10 +000019767 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019768 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000019769}
19770
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019771
Daniel Veillard4255d502002-04-16 15:50:10 +000019772/**
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000019773 * xmlSchemaValidateOneElement:
19774 * @ctxt: a schema validation context
19775 * @elem: an element node
19776 *
19777 * Validate a branch of a tree, starting with the given @elem.
19778 *
19779 * Returns 0 if the element and its subtree is valid, a positive error
19780 * code number otherwise and -1 in case of an internal or API error.
19781 */
19782int
19783xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
19784{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019785 if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000019786 return (-1);
19787
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019788 if (ctxt->schema == NULL) {
19789 xmlSchemaVErr(ctxt, NULL,
19790 XML_SCHEMAV_INTERNAL,
19791 "API error: xmlSchemaValidateOneElement, "
19792 "no schema specified.\n", NULL, NULL);
19793 return (-1);
19794 }
19795
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000019796 ctxt->doc = elem->doc;
19797 ctxt->err = 0;
19798 ctxt->nberrors = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019799 ctxt->node = elem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019800 ctxt->validationRoot = elem;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019801 return (xmlSchemaValidateElement(ctxt));
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000019802}
19803
19804/**
Daniel Veillard4255d502002-04-16 15:50:10 +000019805 * xmlSchemaValidateDocument:
19806 * @ctxt: a schema validation context
19807 * @doc: a parsed document tree
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019808 * @xsiAssemble: should schemata be added if requested by the instance?
Daniel Veillard4255d502002-04-16 15:50:10 +000019809 *
19810 * Validate a document tree in memory.
19811 *
19812 * Returns 0 if the document is schemas valid, a positive error code
19813 * number otherwise and -1 in case of internal or API error.
19814 */
19815static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019816xmlSchemaValidateDocument(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
19817{
Daniel Veillard4255d502002-04-16 15:50:10 +000019818 xmlNodePtr root;
Daniel Veillard01fa6152004-06-29 17:04:39 +000019819
Daniel Veillard4255d502002-04-16 15:50:10 +000019820 root = xmlDocGetRootElement(doc);
19821 if (root == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000019822 xmlSchemaVCustomErr(ctxt,
19823 XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
19824 (xmlNodePtr) doc, NULL,
19825 "The document has no document element", NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019826 return (ctxt->err);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019827 }
Daniel Veillard4255d502002-04-16 15:50:10 +000019828 /*
19829 * Okay, start the recursive validation
19830 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019831 ctxt->node = root;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019832 ctxt->validationRoot = root;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019833 xmlSchemaValidateElement(ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000019834
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019835 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000019836}
19837
19838/************************************************************************
19839 * *
19840 * SAX Validation code *
19841 * *
19842 ************************************************************************/
19843
19844/************************************************************************
19845 * *
19846 * Validation interfaces *
19847 * *
19848 ************************************************************************/
19849
19850/**
19851 * xmlSchemaNewValidCtxt:
19852 * @schema: a precompiled XML Schemas
19853 *
19854 * Create an XML Schemas validation context based on the given schema
19855 *
19856 * Returns the validation context or NULL in case of error
19857 */
19858xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019859xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
19860{
Daniel Veillard4255d502002-04-16 15:50:10 +000019861 xmlSchemaValidCtxtPtr ret;
19862
19863 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
19864 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019865 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000019866 return (NULL);
19867 }
19868 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
Daniel Veillardc0826a72004-08-10 14:17:33 +000019869 ret->schema = schema;
Daniel Veillard3646d642004-06-02 19:19:14 +000019870 ret->attrTop = NULL;
19871 ret->attr = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000019872 return (ret);
19873}
19874
19875/**
19876 * xmlSchemaFreeValidCtxt:
19877 * @ctxt: the schema validation context
19878 *
19879 * Free the resources associated to the schema validation context
19880 */
19881void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019882xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
19883{
Daniel Veillard4255d502002-04-16 15:50:10 +000019884 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019885 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000019886 if (ctxt->attr != NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000019887 xmlSchemaFreeAttributeStates(ctxt->attr);
Daniel Veillard88c58912002-04-23 07:12:20 +000019888 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019889 xmlSchemaFreeValue(ctxt->value);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019890 if (ctxt->pctxt != NULL) {
19891 xmlSchemaFreeParserCtxt(ctxt->pctxt);
19892 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019893
19894#ifdef IDC_ENABLED
19895 if (ctxt->idcNodes != NULL) {
19896 int i;
19897 xmlSchemaPSVIIDCNodePtr item;
19898
19899 for (i = 0; i < ctxt->nbIdcNodes; i++) {
19900 item = ctxt->idcNodes[i];
19901 xmlFree(item->keys);
19902 xmlFree(item);
19903 }
19904 xmlFree(ctxt->idcNodes);
19905 }
19906
19907 if (ctxt->idcKeys != NULL) {
19908 int i;
19909 for (i = 0; i < ctxt->nbIdcKeys; i++)
19910 xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
19911 xmlFree(ctxt->idcKeys);
19912 }
19913
19914 if (ctxt->xpathStates != NULL)
19915 xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
19916 if (ctxt->xpathStatePool != NULL)
19917 xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
19918
19919 /*
19920 * Augmented IDC information.
19921 */
19922 if (ctxt->aidcs != NULL) {
19923 xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
19924 do {
19925 next = cur->next;
19926 xmlFree(cur);
19927 cur = next;
19928 } while (cur != NULL);
19929 }
19930#endif /* IDC_ENABLED */
19931#ifdef ELEM_INFO_ENABLED
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019932 if (ctxt->attrInfo != NULL) {
19933 if (ctxt->attrInfo->value != NULL)
19934 xmlSchemaFreeValue(ctxt->attrInfo->value);
19935 xmlFree(ctxt->attrInfo);
19936 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019937 if (ctxt->elemInfos != NULL) {
19938 int i;
19939 xmlSchemaElemInfoPtr info;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019940
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019941 for (i = 0; i < ctxt->sizeElemInfos; i++) {
19942 info = ctxt->elemInfos[i];
19943 if (info == NULL)
19944 continue;
19945 if (info->value != NULL)
19946 xmlSchemaFreeValue(info->value);
19947#ifdef IDC_ENABLED
19948 if (info->idcMatchers != NULL)
19949 xmlSchemaIDCFreeMatcherList(info->idcMatchers);
19950#endif
19951 /*
19952 * TODO: Free the IDC table if still existent.
19953 */
19954
19955 /*
19956 xmlFree(info->localName);
19957 if (info->namespaceName != NULL)
19958 xmlFree(info->namespaceName);
19959 */
19960 xmlFree(info);
19961 }
19962 xmlFree(ctxt->elemInfos);
19963 }
19964#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000019965 xmlFree(ctxt);
19966}
19967
19968/**
19969 * xmlSchemaSetValidErrors:
19970 * @ctxt: a schema validation context
19971 * @err: the error function
19972 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +000019973 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +000019974 *
William M. Brack2f2a6632004-08-20 23:09:47 +000019975 * Set the error and warning callback informations
Daniel Veillard4255d502002-04-16 15:50:10 +000019976 */
19977void
19978xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019979 xmlSchemaValidityErrorFunc err,
19980 xmlSchemaValidityWarningFunc warn, void *ctx)
19981{
Daniel Veillard4255d502002-04-16 15:50:10 +000019982 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019983 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000019984 ctxt->error = err;
19985 ctxt->warning = warn;
19986 ctxt->userData = ctx;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019987 if (ctxt->pctxt != NULL)
19988 xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
Daniel Veillard4255d502002-04-16 15:50:10 +000019989}
19990
19991/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000019992 * xmlSchemaGetValidErrors:
19993 * @ctxt: a XML-Schema validation context
19994 * @err: the error function result
19995 * @warn: the warning function result
19996 * @ctx: the functions context result
19997 *
19998 * Get the error and warning callback informations
19999 *
20000 * Returns -1 in case of error and 0 otherwise
20001 */
20002int
20003xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
20004 xmlSchemaValidityErrorFunc * err,
20005 xmlSchemaValidityWarningFunc * warn, void **ctx)
20006{
20007 if (ctxt == NULL)
20008 return (-1);
20009 if (err != NULL)
20010 *err = ctxt->error;
20011 if (warn != NULL)
20012 *warn = ctxt->warning;
20013 if (ctx != NULL)
20014 *ctx = ctxt->userData;
20015 return (0);
20016}
20017
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020018
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020019/**
Daniel Veillard6927b102004-10-27 17:29:04 +000020020 * xmlSchemaSetValidOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020021 * @ctxt: a schema validation context
20022 * @options: a combination of xmlSchemaValidOption
20023 *
20024 * Sets the options to be used during the validation.
20025 *
20026 * Returns 0 in case of success, -1 in case of an
20027 * API error.
20028 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020029int
20030xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
20031 int options)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020032
20033{
20034 int i;
20035
20036 if (ctxt == NULL)
20037 return (-1);
20038 /*
20039 * WARNING: Change the start value if adding to the
20040 * xmlSchemaValidOption.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020041 * TODO: Is there an other, more easy to maintain,
20042 * way?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020043 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020044 for (i = 1; i < (int) sizeof(int) * 8; i++) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020045 if (options & 1<<i) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020046 xmlSchemaVErr(ctxt, NULL,
20047 XML_SCHEMAV_INTERNAL,
20048 "Internal error: xmlSchemaSetValidOptions, "
20049 "invalid option argument.\n", NULL, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020050 return (-1);
20051 }
20052 }
20053 ctxt->options = options;
20054 return (0);
20055}
20056
20057/**
Daniel Veillard6927b102004-10-27 17:29:04 +000020058 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020059 * @ctxt: a schema validation context
20060 *
William M. Brack21e4ef22005-01-02 09:53:13 +000020061 * Get the validation context options.
20062 *
20063 * Returns the option combination or -1 on error.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020064 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020065int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020066xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
20067
20068{
20069 if (ctxt == NULL)
20070 return (-1);
20071 else
20072 return (ctxt->options);
20073}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020074
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000020075
Daniel Veillard259f0df2004-08-18 09:13:18 +000020076/**
Daniel Veillard4255d502002-04-16 15:50:10 +000020077 * xmlSchemaValidateDoc:
20078 * @ctxt: a schema validation context
20079 * @doc: a parsed document tree
20080 *
20081 * Validate a document tree in memory.
20082 *
20083 * Returns 0 if the document is schemas valid, a positive error code
20084 * number otherwise and -1 in case of internal or API error.
20085 */
20086int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020087xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
20088{
Daniel Veillard4255d502002-04-16 15:50:10 +000020089 int ret;
20090
20091 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020092 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000020093
20094 ctxt->doc = doc;
William M. Brack2f2a6632004-08-20 23:09:47 +000020095 ctxt->err = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020096 ctxt->nberrors = 0;
20097
20098 /*
20099 if (ctxt->schema == NULL) {
20100 xmlSchemaVErr(ctxt, NULL,
20101 XML_SCHEMAV_INTERNAL,
20102 "API error: xmlSchemaValidateDoc, "
20103 "no schema specified and assembling of schemata "
20104 "using xsi:schemaLocation and xsi:noNamespaceSchemaLocation "
20105 "is not enabled.\n", NULL, NULL);
20106 return (-1);
20107 }
20108 */
Daniel Veillard4255d502002-04-16 15:50:10 +000020109 ret = xmlSchemaValidateDocument(ctxt, doc);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020110 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000020111}
20112
20113/**
20114 * xmlSchemaValidateStream:
20115 * @ctxt: a schema validation context
20116 * @input: the input to use for reading the data
20117 * @enc: an optional encoding information
20118 * @sax: a SAX handler for the resulting events
20119 * @user_data: the context to provide to the SAX handler.
20120 *
20121 * Validate a document tree in memory.
20122 *
20123 * Returns 0 if the document is schemas valid, a positive error code
20124 * number otherwise and -1 in case of internal or API error.
20125 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020126int
Daniel Veillard4255d502002-04-16 15:50:10 +000020127xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020128 xmlParserInputBufferPtr input, xmlCharEncoding enc,
20129 xmlSAXHandlerPtr sax, void *user_data)
20130{
Daniel Veillard4255d502002-04-16 15:50:10 +000020131 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020132 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000020133 ctxt->input = input;
20134 ctxt->enc = enc;
20135 ctxt->sax = sax;
20136 ctxt->user_data = user_data;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020137 TODO return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000020138}
20139
20140#endif /* LIBXML_SCHEMAS_ENABLED */