blob: 8e291d0011127b82a68059816910f78b40b0bbf7 [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. Buchcike8a550b2005-01-27 12:49:31 +000055#define ELEM_INFO_ENABLED 1
56
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
Daniel Veillard4255d502002-04-16 15:50:10 +0000221
222typedef struct _xmlSchemaAttrState xmlSchemaAttrState;
223typedef xmlSchemaAttrState *xmlSchemaAttrStatePtr;
224struct _xmlSchemaAttrState {
Daniel Veillard3646d642004-06-02 19:19:14 +0000225 xmlSchemaAttrStatePtr next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000226 xmlAttrPtr attr;
227 int state;
Daniel Veillard3646d642004-06-02 19:19:14 +0000228 xmlSchemaAttributePtr decl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000229 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000230};
231
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000232typedef struct _xmlSchemaBasicItem xmlSchemaBasicItem;
233typedef xmlSchemaBasicItem *xmlSchemaBasicItemPtr;
234struct _xmlSchemaBasicItem {
235 xmlSchemaTypeType type;
236 xmlSchemaAnnotPtr annot;
237};
238
239typedef struct _xmlSchemaItemQNRef xmlSchemaItemQNRef;
240typedef xmlSchemaItemQNRef *xmlSchemaItemQNRefPtr;
241struct _xmlSchemaItemQNRef {
242 xmlSchemaBasicItemPtr item;
243 const xmlChar *name;
244 const xmlChar *targetNamespace;
245};
246
247typedef struct _xmlSchemaIDC xmlSchemaIDC;
248typedef xmlSchemaIDC *xmlSchemaIDCPtr;
249
250/**
251 * xmlSchemaIDCSelect:
252 *
253 * The identity-constraint "field" and "selector" item, holding the
254 * XPath expression.
255 */
256typedef struct _xmlSchemaIDCSelect xmlSchemaIDCSelect;
257typedef xmlSchemaIDCSelect *xmlSchemaIDCSelectPtr;
258struct _xmlSchemaIDCSelect {
259 xmlSchemaIDCSelectPtr next;
260 xmlSchemaIDCPtr idc;
261 int index; /* an index position if significant for IDC key-sequences */
262 const xmlChar *xpath; /* the XPath expression */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000263 void *xpathComp; /* the compiled XPath expression */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000264};
265
266/**
267 * xmlSchemaIDC:
268 *
269 * The identity-constraint definition component.
270 */
271
272struct _xmlSchemaIDC {
273 xmlSchemaTypeType type;
274 xmlSchemaAnnotPtr annot;
275 xmlSchemaIDCPtr next;
276 xmlNodePtr node;
277 const xmlChar *name;
278 const xmlChar *targetNamespace;
279 xmlSchemaIDCSelectPtr selector;
280 xmlSchemaIDCSelectPtr fields;
281 int nbFields;
282 xmlSchemaItemQNRefPtr ref;
283};
284
285/**
286 * xmlSchemaIDCAug:
287 *
288 * The augmented IDC information used for validation.
289 */
290typedef struct _xmlSchemaIDCAug xmlSchemaIDCAug;
291typedef xmlSchemaIDCAug *xmlSchemaIDCAugPtr;
292struct _xmlSchemaIDCAug {
293 xmlSchemaIDCAugPtr next; /* next in a list */
294 xmlSchemaIDCPtr def; /* the IDC definition */
295 int bubbleDepth; /* the lowest level to which IDC
296 tables need to be bubbled upwards */
297};
298
299/**
300 * xmlSchemaPSVIIDCKeySequence:
301 *
302 * The key sequence of a node table item.
303 */
304typedef struct _xmlSchemaPSVIIDCKey xmlSchemaPSVIIDCKey;
305typedef xmlSchemaPSVIIDCKey *xmlSchemaPSVIIDCKeyPtr;
306struct _xmlSchemaPSVIIDCKey {
307 xmlSchemaTypePtr type;
308 xmlSchemaValPtr compValue;
309};
310
311/**
312 * xmlSchemaPSVIIDCNode:
313 *
314 * The node table item of a node table.
315 */
316typedef struct _xmlSchemaPSVIIDCNode xmlSchemaPSVIIDCNode;
317typedef xmlSchemaPSVIIDCNode *xmlSchemaPSVIIDCNodePtr;
318struct _xmlSchemaPSVIIDCNode {
319 xmlNodePtr node;
320 xmlSchemaPSVIIDCKeyPtr *keys;
321};
322
323/**
324 * xmlSchemaPSVIIDCBinding:
325 *
326 * The identity-constraint binding item of the [identity-constraint table].
327 */
328typedef struct _xmlSchemaPSVIIDCBinding xmlSchemaPSVIIDCBinding;
329typedef xmlSchemaPSVIIDCBinding *xmlSchemaPSVIIDCBindingPtr;
330struct _xmlSchemaPSVIIDCBinding {
331 xmlSchemaPSVIIDCBindingPtr next; /* next binding of a specific node */
332 xmlSchemaIDCPtr definition; /* the IDC definition */
333 xmlSchemaPSVIIDCNodePtr *nodeTable; /* array of key-sequences */
334 int nbNodes; /* number of entries in the node table */
335 int sizeNodes; /* size of the node table */
336 int nbDupls; /* number of already identified duplicates in the node
337 table */
338 /* int nbKeys; number of keys in each key-sequence */
339};
340
341#define XPATH_STATE_OBJ_TYPE_IDC_SELECTOR 1
342#define XPATH_STATE_OBJ_TYPE_IDC_FIELD 2
343
344#define XPATH_STATE_OBJ_MATCHES -2
345#define XPATH_STATE_OBJ_BLOCKED -3
346
347typedef struct _xmlSchemaIDCMatcher xmlSchemaIDCMatcher;
348typedef xmlSchemaIDCMatcher *xmlSchemaIDCMatcherPtr;
349
350/**
351 * xmlSchemaIDCStateObj:
352 *
353 * The state object used to evaluate XPath expressions.
354 */
355typedef struct _xmlSchemaIDCStateObj xmlSchemaIDCStateObj;
356typedef xmlSchemaIDCStateObj *xmlSchemaIDCStateObjPtr;
357struct _xmlSchemaIDCStateObj {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000358 int type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000359 xmlSchemaIDCStateObjPtr next; /* next if in a list */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000360 int depth; /* depth of creation */
361 int *history; /* list of (depth, state-id) tuples */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000362 int nbHistory;
363 int sizeHistory;
364 xmlSchemaIDCMatcherPtr matcher; /* the correspondent field/selector
365 matcher */
366 xmlSchemaIDCSelectPtr sel;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000367 void *xpathCtxt;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000368};
369
370#define IDC_MATCHER 0
371
372/**
373 * xmlSchemaIDCMatcher:
374 *
375 * Used to IDC selectors (and fields) successively.
376 */
377struct _xmlSchemaIDCMatcher {
378 int type;
379 int depth; /* the tree depth at creation time */
380 xmlSchemaIDCMatcherPtr next; /* next in the list */
381 xmlSchemaIDCAugPtr aidc; /* the augmented IDC item */
382 xmlSchemaPSVIIDCKeyPtr **keySeqs; /* the key-sequences of the target
383 elements */
384 int sizeKeySeqs;
385 xmlSchemaPSVIIDCKeyPtr **refKeySeqs;
386 int nbRefKeySeqs;
387 int sizeRefKeySeqs;
388 int targetDepth;
389};
390
391/*
392* Element info flags.
393*/
394#define XML_SCHEMA_ELEM_INFO_VALUE_NEEDED 1<<0
395
396/**
397 * xmlSchemaElemInfo:
398 *
399 * Holds information of an element node.
400 */
401typedef struct _xmlSchemaElemInfo xmlSchemaElemInfo;
402typedef xmlSchemaElemInfo *xmlSchemaElemInfoPtr;
403struct _xmlSchemaElemInfo {
404 int depth;
405 int flags; /* combination of element info flags */
406 xmlNodePtr node;
407 const xmlChar *localName;
408 const xmlChar *namespaceName;
409 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
410 xmlSchemaValPtr value; /* the pre-computed value if any */
411 xmlSchemaPSVIIDCBindingPtr idcTable; /* the table of PSVI IDC bindings
412 for the scope element*/
413 xmlSchemaIDCMatcherPtr idcMatchers; /* the IDC matchers for the scope
414 element */
415};
416
Daniel Veillard4255d502002-04-16 15:50:10 +0000417/**
418 * xmlSchemaValidCtxt:
419 *
420 * A Schemas validation context
421 */
422
423struct _xmlSchemaValidCtxt {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000424 void *userData; /* user specific data block */
425 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000426 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000427 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000428
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000429 xmlSchemaPtr schema; /* The schema in use */
430 xmlDocPtr doc;
Daniel Veillard4255d502002-04-16 15:50:10 +0000431 xmlParserInputBufferPtr input;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000432 xmlCharEncoding enc;
433 xmlSAXHandlerPtr sax;
434 void *user_data;
Daniel Veillard4255d502002-04-16 15:50:10 +0000435
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000436 xmlDocPtr myDoc;
437 int err;
438 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +0000439
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000440 xmlNodePtr node;
441 xmlNodePtr cur;
442 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +0000443
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000444 xmlRegExecCtxtPtr regexp;
445 xmlSchemaValPtr value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000446
Daniel Veillard3646d642004-06-02 19:19:14 +0000447 xmlSchemaAttrStatePtr attrTop;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000448 xmlSchemaAttrStatePtr attr;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000449 /* xmlNodePtr scope; not used */
Daniel Veillardc0826a72004-08-10 14:17:33 +0000450 int valueWS;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000451 int options;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000452 xmlNodePtr validationRoot;
453 xmlSchemaParserCtxtPtr pctxt;
454 int xsiAssemble;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000455#ifdef ELEM_INFO_ENABLED
456 int depth;
457 xmlSchemaElemInfoPtr *elemInfos; /* array of element informations */
458 int sizeElemInfos;
459 xmlSchemaElemInfoPtr elemInfo; /* the current element information */
460#endif
461#ifdef IDC_ENABLED
462 xmlSchemaIDCAugPtr aidcs; /* a list of augmented IDC informations */
463
464 xmlSchemaIDCStateObjPtr xpathStates; /* first active state object. */
465 xmlSchemaIDCStateObjPtr xpathStatePool; /* first stored state object. */
466
467 xmlSchemaPSVIIDCNodePtr *idcNodes; /* list of all IDC node-table entries*/
468 int nbIdcNodes;
469 int sizeIdcNodes;
470
471 xmlSchemaPSVIIDCKeyPtr *idcKeys; /* list of all IDC node-table entries */
472 int nbIdcKeys;
473 int sizeIdcKeys;
474#endif
Daniel Veillard4255d502002-04-16 15:50:10 +0000475};
476
Daniel Veillard1d913862003-11-21 00:28:39 +0000477/*
478 * These are the entries in the schemas importSchemas hash table
479 */
480typedef struct _xmlSchemaImport xmlSchemaImport;
481typedef xmlSchemaImport *xmlSchemaImportPtr;
482struct _xmlSchemaImport {
483 const xmlChar *schemaLocation;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000484 xmlSchemaPtr schema; /* not used any more */
William M. Brack2f2a6632004-08-20 23:09:47 +0000485 xmlDocPtr doc;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000486 int isMain;
Daniel Veillard1d913862003-11-21 00:28:39 +0000487};
Daniel Veillard4255d502002-04-16 15:50:10 +0000488
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000489/*
490 * These are the entries associated to includes in a schemas
491 */
492typedef struct _xmlSchemaInclude xmlSchemaInclude;
493typedef xmlSchemaInclude *xmlSchemaIncludePtr;
494struct _xmlSchemaInclude {
495 xmlSchemaIncludePtr next;
496
497 const xmlChar *schemaLocation;
498 xmlDocPtr doc;
499};
500
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000501typedef struct _xmlSchemaParticle xmlSchemaParticle;
502typedef xmlSchemaParticle *xmlSchemaParticlePtr;
503struct _xmlSchemaParticle {
504 xmlSchemaTypeType type;
505 xmlSchemaParticlePtr next; /* the next particle if in a list */
506 int minOccurs;
507 int maxOccurs;
508 xmlSchemaTypePtr term;
509};
510
511
512typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup;
513typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr;
514struct _xmlSchemaModelGroup {
515 xmlSchemaTypeType type;
516 int compositor; /* one of all, choice or sequence */
517 xmlSchemaParticlePtr particles; /* list of particles */
518 xmlSchemaAnnotPtr annot;
519};
520
521typedef struct _xmlSchemaModelGroupDef xmlSchemaModelGroupDef;
522typedef xmlSchemaModelGroupDef *xmlSchemaModelGroupDefPtr;
523struct _xmlSchemaModelGroupDef {
524 xmlSchemaTypeType type;
525 const xmlChar *name;
526 const xmlChar *targetNamespace;
527 xmlSchemaModelGroupPtr modelGroup;
528 xmlSchemaAnnotPtr annot;
529};
530
Daniel Veillard4255d502002-04-16 15:50:10 +0000531/************************************************************************
532 * *
533 * Some predeclarations *
534 * *
535 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000536
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000537static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
538 xmlSchemaPtr schema,
539 xmlNodePtr node);
Daniel Veillard01fa6152004-06-29 17:04:39 +0000540static void
541xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
542 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name);
543static const char *
544xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
545static int
546xmlSchemaValidateSimpleTypeValue(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000547 xmlSchemaTypePtr type,
Daniel Veillard01fa6152004-06-29 17:04:39 +0000548 const xmlChar *value,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000549 int fireErrors,
Daniel Veillardc0826a72004-08-10 14:17:33 +0000550 int applyFacets,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000551 int normalize,
552 int checkNodes);
553static int
554xmlSchemaValidateElementByDeclaration(xmlSchemaValidCtxtPtr ctxt,
555 xmlSchemaElementPtr elemDecl);
556static int
557xmlSchemaValidateElementByWildcard(xmlSchemaValidCtxtPtr ctxt,
558 xmlSchemaTypePtr type);
559static int
560xmlSchemaHasElemOrCharContent(xmlNodePtr node);
William M. Brack2f2a6632004-08-20 23:09:47 +0000561static int
562xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
563 xmlNodePtr node);
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +0000564static void
565xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
566 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name);
William M. Brack87640d52004-04-17 14:58:15 +0000567
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000568/************************************************************************
569 * *
570 * Datatype error handlers *
571 * *
572 ************************************************************************/
573
574/**
575 * xmlSchemaPErrMemory:
576 * @node: a context node
577 * @extra: extra informations
578 *
579 * Handle an out of memory condition
580 */
581static void
582xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
583 const char *extra, xmlNodePtr node)
584{
585 if (ctxt != NULL)
586 ctxt->nberrors++;
587 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
588 extra);
589}
590
591/**
592 * xmlSchemaPErr:
593 * @ctxt: the parsing context
594 * @node: the context node
595 * @error: the error code
596 * @msg: the error message
597 * @str1: extra data
598 * @str2: extra data
599 *
600 * Handle a parser error
601 */
602static void
603xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
604 const char *msg, const xmlChar * str1, const xmlChar * str2)
605{
606 xmlGenericErrorFunc channel = NULL;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000607 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000608 void *data = NULL;
609
610 if (ctxt != NULL) {
611 ctxt->nberrors++;
612 channel = ctxt->error;
613 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000614 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000615 }
Daniel Veillard659e71e2003-10-10 14:10:40 +0000616 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000617 error, XML_ERR_ERROR, NULL, 0,
618 (const char *) str1, (const char *) str2, NULL, 0, 0,
619 msg, str1, str2);
620}
621
622/**
623 * xmlSchemaPErr2:
624 * @ctxt: the parsing context
625 * @node: the context node
626 * @node: the current child
627 * @error: the error code
628 * @msg: the error message
629 * @str1: extra data
630 * @str2: extra data
631 *
632 * Handle a parser error
633 */
634static void
635xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
636 xmlNodePtr child, int error,
637 const char *msg, const xmlChar * str1, const xmlChar * str2)
638{
639 if (child != NULL)
640 xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
641 else
642 xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
643}
644
Daniel Veillard01fa6152004-06-29 17:04:39 +0000645
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000646/**
Daniel Veillard3646d642004-06-02 19:19:14 +0000647 * xmlSchemaPErrExt:
648 * @ctxt: the parsing context
649 * @node: the context node
650 * @error: the error code
651 * @strData1: extra data
652 * @strData2: extra data
653 * @strData3: extra data
654 * @msg: the message
655 * @str1: extra parameter for the message display
656 * @str2: extra parameter for the message display
657 * @str3: extra parameter for the message display
658 * @str4: extra parameter for the message display
659 * @str5: extra parameter for the message display
660 *
661 * Handle a parser error
662 */
663static void
664xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
665 const xmlChar * strData1, const xmlChar * strData2,
666 const xmlChar * strData3, const char *msg, const xmlChar * str1,
667 const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
668 const xmlChar * str5)
669{
670
671 xmlGenericErrorFunc channel = NULL;
672 xmlStructuredErrorFunc schannel = NULL;
673 void *data = NULL;
674
675 if (ctxt != NULL) {
676 ctxt->nberrors++;
677 channel = ctxt->error;
678 data = ctxt->userData;
679 schannel = ctxt->serror;
680 }
681 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
682 error, XML_ERR_ERROR, NULL, 0,
683 (const char *) strData1, (const char *) strData2,
William M. Brack803812b2004-06-03 02:11:24 +0000684 (const char *) strData3, 0, 0, msg, str1, str2,
685 str3, str4, str5);
Daniel Veillard3646d642004-06-02 19:19:14 +0000686}
Daniel Veillard01fa6152004-06-29 17:04:39 +0000687
Daniel Veillard3646d642004-06-02 19:19:14 +0000688
689/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000690 * xmlSchemaVTypeErrMemory:
691 * @node: a context node
692 * @extra: extra informations
693 *
694 * Handle an out of memory condition
695 */
696static void
697xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
698 const char *extra, xmlNodePtr node)
699{
700 if (ctxt != NULL) {
701 ctxt->nberrors++;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000702 ctxt->err = XML_SCHEMAV_INTERNAL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000703 }
704 __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
705 extra);
706}
707
708/**
709 * xmlSchemaVErr3:
710 * @ctxt: the validation context
711 * @node: the context node
712 * @error: the error code
713 * @msg: the error message
714 * @str1: extra data
715 * @str2: extra data
716 * @str3: extra data
717 *
718 * Handle a validation error
719 */
720static void
721xmlSchemaVErr3(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
722 const char *msg, const xmlChar *str1, const xmlChar *str2,
723 const xmlChar *str3)
724{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000725 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000726 xmlGenericErrorFunc channel = NULL;
727 void *data = NULL;
728
729 if (ctxt != NULL) {
730 ctxt->nberrors++;
731 ctxt->err = error;
732 channel = ctxt->error;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000733 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000734 data = ctxt->userData;
735 }
736 /* reajust to global error numbers */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000737 /* Removed, since the old schema error codes have been
738 * substituted for the global error codes.
739 *
740 * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
741 */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000742 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000743 error, XML_ERR_ERROR, NULL, 0,
744 (const char *) str1, (const char *) str2,
745 (const char *) str3, 0, 0,
746 msg, str1, str2, str3);
747}
Daniel Veillardc0826a72004-08-10 14:17:33 +0000748
749/**
750 * xmlSchemaVErrExt:
751 * @ctxt: the validation context
752 * @node: the context node
753 * @error: the error code
754 * @msg: the message
755 * @str1: extra parameter for the message display
756 * @str2: extra parameter for the message display
757 * @str3: extra parameter for the message display
758 * @str4: extra parameter for the message display
759 * @str5: extra parameter for the message display
760 *
761 * Handle a validation error
762 */
763static void
764xmlSchemaVErrExt(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
765 const char *msg, const xmlChar * str1,
766 const xmlChar * str2, const xmlChar * str3,
767 const xmlChar * str4, const xmlChar * str5)
768{
769 xmlStructuredErrorFunc schannel = NULL;
770 xmlGenericErrorFunc channel = NULL;
771 void *data = NULL;
772
773 if (ctxt != NULL) {
774 ctxt->nberrors++;
775 ctxt->err = error;
776 channel = ctxt->error;
777 schannel = ctxt->serror;
778 data = ctxt->userData;
779 }
780 /* reajust to global error numbers */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000781 /* Removed, since the old schema error codes have been
782 * substituted for the global error codes.
783 *
784 * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
785 */
Daniel Veillardc0826a72004-08-10 14:17:33 +0000786 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
787 error, XML_ERR_ERROR, NULL, 0, NULL, NULL, NULL, 0, 0,
788 msg, str1, str2, str3, str4, str5);
789}
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000790/**
791 * xmlSchemaVErr:
792 * @ctxt: the validation context
793 * @node: the context node
794 * @error: the error code
795 * @msg: the error message
796 * @str1: extra data
797 * @str2: extra data
798 *
799 * Handle a validation error
800 */
801static void
802xmlSchemaVErr(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
803 const char *msg, const xmlChar * str1, const xmlChar * str2)
804{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000805 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000806 xmlGenericErrorFunc channel = NULL;
807 void *data = NULL;
808
809 if (ctxt != NULL) {
810 ctxt->nberrors++;
811 ctxt->err = error;
812 channel = ctxt->error;
813 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000814 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000815 }
816 /* reajust to global error numbers */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000817 /* Removed, since the old schema error codes have been
818 * substituted for the global error codes.
819 *
820 * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
821 */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000822 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000823 error, XML_ERR_ERROR, NULL, 0,
824 (const char *) str1, (const char *) str2, NULL, 0, 0,
825 msg, str1, str2);
826}
Daniel Veillard4255d502002-04-16 15:50:10 +0000827
Daniel Veillardc0826a72004-08-10 14:17:33 +0000828/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000829 * xmlSchemaGetAttrName:
Daniel Veillardc0826a72004-08-10 14:17:33 +0000830 * @attr: the attribute declaration/use
831 *
832 * Returns the name of the attribute; if the attribute
833 * is a reference, the name of the referenced global type will be returned.
834 */
835static const xmlChar *
836xmlSchemaGetAttrName(xmlSchemaAttributePtr attr)
837{
838 if (attr->ref != NULL)
839 return(attr->ref);
840 else
841 return(attr->name);
842}
843
844/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000845 * xmlSchemaGetAttrTargetNsURI:
Daniel Veillardc0826a72004-08-10 14:17:33 +0000846 * @type: the type (element or attribute)
847 *
848 * Returns the target namespace URI of the type; if the type is a reference,
849 * the target namespace of the referenced type will be returned.
850 */
851static const xmlChar *
852xmlSchemaGetAttrTargetNsURI(xmlSchemaAttributePtr attr)
853{
854 if (attr->ref != NULL)
855 return (attr->refNs);
856 else
857 return(attr->targetNamespace);
858}
859
860/**
861 * xmlSchemaFormatNsUriLocal:
862 * @buf: the string buffer
863 * @uri: the namespace URI
864 * @local: the local name
865 *
866 * Returns a representation of the given URI used
867 * for error reports.
868 *
869 * Returns an empty string, if @ns is NULL, a formatted
870 * string otherwise.
871 */
872static const xmlChar*
873xmlSchemaFormatNsUriLocal(xmlChar **buf,
874 const xmlChar *uri, const xmlChar *local)
875{
876 if (*buf != NULL)
877 xmlFree(*buf);
878 if (uri == NULL) {
879 *buf = xmlStrdup(BAD_CAST "{'");
880 *buf = xmlStrcat(*buf, local);
881 } else {
882 *buf = xmlStrdup(BAD_CAST "{'");
883 *buf = xmlStrcat(*buf, uri);
884 *buf = xmlStrcat(*buf, BAD_CAST "', '");
885 *buf = xmlStrcat(*buf, local);
886 }
887 *buf = xmlStrcat(*buf, BAD_CAST "'}");
888 return ((const xmlChar *) *buf);
889}
890
891/**
892 * xmlSchemaFormatNsPrefixLocal:
893 * @buf: the string buffer
894 * @ns: the namespace
895 * @local: the local name
896 *
897 * Returns a representation of the given URI used
898 * for error reports.
899 *
900 * Returns an empty string, if @ns is NULL, a formatted
901 * string otherwise.
902 */
903static const xmlChar*
904xmlSchemaFormatNsPrefixLocal(xmlChar **buf,
905 xmlNsPtr ns, const xmlChar *local)
906{
907 if (*buf != NULL) {
908 xmlFree(*buf);
909 *buf = NULL;
910 }
911 if ((ns == NULL) || (ns->prefix == NULL))
912 return(local);
913 else {
914 *buf = xmlStrdup(ns->prefix);
915 *buf = xmlStrcat(*buf, BAD_CAST ":");
916 *buf = xmlStrcat(*buf, local);
917 }
918 return ((const xmlChar *) *buf);
919}
920
921/**
922 * xmlSchemaFormatItemForReport:
923 * @buf: the string buffer
924 * @itemDes: the designation of the item
925 * @itemName: the name of the item
926 * @item: the item as an object
927 * @itemNode: the node of the item
928 * @local: the local name
929 * @parsing: if the function is used during the parse
930 *
931 * Returns a representation of the given item used
932 * for error reports.
933 *
934 * The following order is used to build the resulting
935 * designation if the arguments are not NULL:
936 * 1a. If itemDes not NULL -> itemDes
937 * 1b. If (itemDes not NULL) and (itemName not NULL)
938 * -> itemDes + itemName
939 * 2. If the preceding was NULL and (item not NULL) -> item
940 * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
941 *
942 * If the itemNode is an attribute node, the name of the attribute
943 * will be appended to the result.
944 *
945 * Returns the formatted string and sets @buf to the resulting value.
946 */
947static xmlChar*
948xmlSchemaFormatItemForReport(xmlChar **buf,
949 const xmlChar *itemDes,
950 xmlSchemaTypePtr item,
951 xmlNodePtr itemNode,
952 int parsing)
953{
954 xmlChar *str = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +0000955 int named = 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +0000956
957 if (*buf != NULL) {
958 xmlFree(*buf);
959 *buf = NULL;
960 }
961
William M. Brack2f2a6632004-08-20 23:09:47 +0000962 if (itemDes != NULL) {
963 *buf = xmlStrdup(itemDes);
964 } else if (item != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000965 switch (item->type) {
966 case XML_SCHEMA_TYPE_BASIC:
Daniel Veillardc0826a72004-08-10 14:17:33 +0000967 if (item->builtInType == XML_SCHEMAS_ANYTYPE)
968 *buf = xmlStrdup(BAD_CAST "'anyType'");
969 else if (item->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)
970 *buf = xmlStrdup(BAD_CAST "'anySimpleType'");
971 else {
972 /* *buf = xmlStrdup(BAD_CAST "bi "); */
973 /* *buf = xmlStrcat(*buf, xmlSchemaElemDesST); */
974 *buf = xmlStrdup(BAD_CAST "'");
975 *buf = xmlStrcat(*buf, item->name);
976 *buf = xmlStrcat(*buf, BAD_CAST "'");
977 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000978 break;
979 case XML_SCHEMA_TYPE_SIMPLE:
Daniel Veillardc0826a72004-08-10 14:17:33 +0000980 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
981 *buf = xmlStrdup(xmlSchemaElemDesST);
982 *buf = xmlStrcat(*buf, BAD_CAST " '");
983 *buf = xmlStrcat(*buf, item->name);
984 *buf = xmlStrcat(*buf, BAD_CAST "'");
985 } else {
986 *buf = xmlStrdup(xmlSchemaElemDesST);
Daniel Veillardc0826a72004-08-10 14:17:33 +0000987 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000988 break;
989 case XML_SCHEMA_TYPE_COMPLEX:
Daniel Veillardc0826a72004-08-10 14:17:33 +0000990 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
991 *buf = xmlStrdup(xmlSchemaElemDesCT);
992 *buf = xmlStrcat(*buf, BAD_CAST " '");
993 *buf = xmlStrcat(*buf, item->name);
994 *buf = xmlStrcat(*buf, BAD_CAST "'");
995 } else {
996 *buf = xmlStrdup(xmlSchemaElemDesCT);
Daniel Veillardc0826a72004-08-10 14:17:33 +0000997 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000998 break;
999 case XML_SCHEMA_TYPE_ATTRIBUTE: {
1000 xmlSchemaAttributePtr attr;
1001
1002 attr = (xmlSchemaAttributePtr) item;
1003 if ((attr->flags & XML_SCHEMAS_TYPE_GLOBAL) ||
1004 (attr->ref == NULL)) {
1005 *buf = xmlStrdup(xmlSchemaElemDesAttrDecl);
1006 *buf = xmlStrcat(*buf, BAD_CAST " '");
1007 *buf = xmlStrcat(*buf, attr->name);
1008 *buf = xmlStrcat(*buf, BAD_CAST "'");
1009 } else {
1010 *buf = xmlStrdup(xmlSchemaElemDesAttrRef);
1011 *buf = xmlStrcat(*buf, BAD_CAST " '");
1012 *buf = xmlStrcat(*buf, attr->refPrefix);
1013 *buf = xmlStrcat(*buf, BAD_CAST ":");
1014 *buf = xmlStrcat(*buf, attr->ref);
1015 *buf = xmlStrcat(*buf, BAD_CAST "'");
1016 }
1017 }
1018 break;
1019 case XML_SCHEMA_TYPE_ELEMENT: {
1020 xmlSchemaElementPtr elem;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001021
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001022 elem = (xmlSchemaElementPtr) item;
1023 if ((elem->flags & XML_SCHEMAS_TYPE_GLOBAL) ||
1024 (elem->ref == NULL)) {
1025 *buf = xmlStrdup(xmlSchemaElemDesElemDecl);
1026 *buf = xmlStrcat(*buf, BAD_CAST " '");
1027 *buf = xmlStrcat(*buf, elem->name);
1028 *buf = xmlStrcat(*buf, BAD_CAST "'");
1029 } else {
1030 *buf = xmlStrdup(xmlSchemaElemDesElemRef);
1031 *buf = xmlStrcat(*buf, BAD_CAST " '");
1032 *buf = xmlStrcat(*buf, elem->refPrefix);
1033 *buf = xmlStrcat(*buf, BAD_CAST ":");
1034 *buf = xmlStrcat(*buf, elem->ref);
1035 *buf = xmlStrcat(*buf, BAD_CAST "'");
1036 }
1037 }
1038 break;
1039 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1040 case XML_SCHEMA_TYPE_IDC_KEY:
1041 case XML_SCHEMA_TYPE_IDC_KEYREF:
1042 if (item->type == XML_SCHEMA_TYPE_IDC_UNIQUE)
1043 *buf = xmlStrdup(BAD_CAST "unique '");
1044 else if (item->type == XML_SCHEMA_TYPE_IDC_KEY)
1045 *buf = xmlStrdup(BAD_CAST "key '");
1046 else
1047 *buf = xmlStrdup(BAD_CAST "keyRef '");
1048 *buf = xmlStrcat(*buf, ((xmlSchemaIDCPtr) item)->name);
1049 *buf = xmlStrcat(*buf, BAD_CAST "'");
1050 break;
1051 default:
William M. Brack2f2a6632004-08-20 23:09:47 +00001052 named = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001053 }
William M. Brack2f2a6632004-08-20 23:09:47 +00001054 } else
1055 named = 0;
1056
1057 if ((named == 0) && (itemNode != NULL)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00001058 xmlNodePtr elem;
1059
1060 if (itemNode->type == XML_ATTRIBUTE_NODE)
1061 elem = itemNode->parent;
1062 else
1063 elem = itemNode;
1064 *buf = xmlStrdup(BAD_CAST "Element '");
1065 if (parsing)
1066 *buf = xmlStrcat(*buf, elem->name);
1067 else
1068 *buf = xmlStrcat(*buf,
1069 xmlSchemaFormatNsPrefixLocal(&str, elem->ns, elem->name));
1070 *buf = xmlStrcat(*buf, BAD_CAST "'");
1071 }
1072 if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
1073 *buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
1074 *buf = xmlStrcat(*buf, xmlSchemaFormatNsPrefixLocal(&str,
1075 itemNode->ns, itemNode->name));
1076 *buf = xmlStrcat(*buf, BAD_CAST "'");
1077 }
1078 FREE_AND_NULL(str);
1079
1080 return (*buf);
1081}
1082
1083/**
1084 * xmlSchemaPFormatItemDes:
1085 * @buf: the string buffer
1086 * @item: the item as a schema object
1087 * @itemNode: the item as a node
1088 *
1089 * If the pointer to @buf is not NULL and @but holds no value,
1090 * the value is set to a item designation using
1091 * xmlSchemaFormatItemForReport. This one avoids adding
1092 * an attribute designation postfix.
1093 *
1094 * Returns a string of all enumeration elements.
1095 */
1096static void
1097xmlSchemaPRequestItemDes(xmlChar **buf,
1098 xmlSchemaTypePtr item,
1099 xmlNodePtr itemNode)
1100{
1101 if ((buf == 0) || (*buf != NULL))
1102 return;
1103 if (itemNode->type == XML_ATTRIBUTE_NODE)
1104 itemNode = itemNode->parent;
1105 xmlSchemaFormatItemForReport(buf, NULL, item, itemNode, 1);
1106}
1107
1108/**
1109 * xmlSchemaFormatFacetEnumSet:
1110 * @buf: the string buffer
1111 * @type: the type holding the enumeration facets
1112 *
1113 * Builds a string consisting of all enumeration elements.
1114 *
1115 * Returns a string of all enumeration elements.
1116 */
1117static const xmlChar *
1118xmlSchemaFormatFacetEnumSet(xmlChar **buf, xmlSchemaTypePtr type)
1119{
1120 xmlSchemaFacetLinkPtr link;
1121
1122 if (*buf != NULL)
1123 xmlFree(*buf);
1124 *buf = NULL;
1125 for (link = type->facetSet; link != NULL; link = link->next) {
1126 if (link->facet->type == XML_SCHEMA_FACET_ENUMERATION) {
1127 if (*buf == NULL) {
1128 *buf = xmlStrdup(BAD_CAST "'");
1129 *buf = xmlStrcat(*buf, link->facet->value);
1130 *buf = xmlStrcat(*buf, BAD_CAST "'");
1131 } else {
1132 *buf = xmlStrcat(*buf, BAD_CAST ", '");
1133 *buf = xmlStrcat(*buf, link->facet->value);
1134 *buf = xmlStrcat(*buf, BAD_CAST "'");
1135 }
1136 }
1137 }
1138 return ((const xmlChar *) *buf);
1139}
1140
1141/**
1142 * xmlSchemaVFacetErr:
1143 * @ctxt: the schema validation context
1144 * @error: the error code
1145 * @node: the node to be validated
1146 * @value: the value of the node
1147 * @type: the type holding the facet
1148 * @facet: the facet
1149 * @message: the error message of NULL
1150 * @str1: extra data
1151 * @str2: extra data
1152 * @str3: extra data
1153 *
1154 * Reports a facet validation error.
1155 * TODO: Should this report the value of an element as well?
1156 */
1157static void
1158xmlSchemaVFacetErr(xmlSchemaValidCtxtPtr ctxt,
1159 xmlParserErrors error,
1160 xmlNodePtr node,
1161 const xmlChar *value,
1162 unsigned long length,
1163 xmlSchemaTypePtr type,
1164 xmlSchemaFacetPtr facet,
1165 const char *message,
1166 const xmlChar *str1,
1167 const xmlChar *str2,
1168 const xmlChar *str3)
1169{
1170 xmlChar *str = NULL, *msg = NULL;
1171 xmlSchemaTypeType facetType;
1172
1173 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
1174 msg = xmlStrcat(msg, BAD_CAST " [");
1175 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1176 msg = xmlStrcat(msg, BAD_CAST ", facet '");
1177 if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
1178 facetType = XML_SCHEMA_FACET_ENUMERATION;
1179 /*
1180 * If enumerations are validated, one must not expect the
1181 * facet to be given.
1182 */
1183 } else
1184 facetType = facet->type;
1185 msg = xmlStrcat(msg, BAD_CAST xmlSchemaFacetTypeToString(facetType));
1186 msg = xmlStrcat(msg, BAD_CAST "']: ");
1187 if (message == NULL) {
1188 /*
1189 * Use a default message.
1190 */
1191 if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
1192 (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
1193 (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
1194
1195 char len[25], actLen[25];
1196
1197 /* FIXME, TODO: What is the max expected string length of the
1198 * this value?
1199 */
1200 if (node->type == XML_ATTRIBUTE_NODE)
1201 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
1202 else
1203 msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
1204
1205 snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
1206 snprintf(actLen, 24, "%lu", length);
1207
1208 if (facetType == XML_SCHEMA_FACET_LENGTH)
1209 msg = xmlStrcat(msg,
1210 BAD_CAST "this differs from the allowed length of '%s'.\n");
1211 else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
1212 msg = xmlStrcat(msg,
1213 BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
1214 else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
1215 msg = xmlStrcat(msg,
1216 BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
1217
1218 if (node->type == XML_ATTRIBUTE_NODE)
1219 xmlSchemaVErrExt(ctxt, node, error,
1220 (const char *) msg,
1221 value, (const xmlChar *) actLen, (const xmlChar *) len,
1222 NULL, NULL);
1223 else
1224 xmlSchemaVErr(ctxt, node, error,
1225 (const char *) msg,
1226 (const xmlChar *) actLen, (const xmlChar *) len);
1227
1228 } else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
1229 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
1230 "of the set {%s}.\n");
1231 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
1232 xmlSchemaFormatFacetEnumSet(&str, type));
1233 } else if (facetType == XML_SCHEMA_FACET_PATTERN) {
1234 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
1235 "by the pattern '%s'.\n");
1236 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
1237 facet->value);
1238 } else if (node->type == XML_ATTRIBUTE_NODE) {
1239 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
1240 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value, NULL);
1241 } else {
1242 msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
1243 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
1244 }
1245 } else {
1246 msg = xmlStrcat(msg, (const xmlChar *) message);
1247 msg = xmlStrcat(msg, BAD_CAST ".\n");
1248 xmlSchemaVErr3(ctxt, node, error, (const char *) msg, str1, str2, str3);
1249 }
1250 FREE_AND_NULL(str)
1251 xmlFree(msg);
1252}
1253
1254/**
1255 * xmlSchemaVSimpleTypeErr:
1256 * @ctxt: the schema validation context
1257 * @error: the error code
1258 * @type: the type used for validation
1259 * @node: the node containing the validated value
1260 * @value: the validated value
1261 *
1262 * Reports a simple type validation error.
1263 * TODO: Should this report the value of an element as well?
1264 */
1265static void
1266xmlSchemaVSimpleTypeErr(xmlSchemaValidCtxtPtr ctxt,
1267 xmlParserErrors error,
1268 xmlNodePtr node,
1269 const xmlChar *value,
1270 xmlSchemaTypePtr type)
1271{
1272 xmlChar *str = NULL, *msg = NULL;
1273
1274 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
1275 msg = xmlStrcat(msg, BAD_CAST " [");
1276 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1277 if (node->type == XML_ATTRIBUTE_NODE) {
1278 msg = xmlStrcat(msg, BAD_CAST "]: The value '%s' is not valid.\n");
1279 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value, NULL);
1280 } else {
1281 msg = xmlStrcat(msg, BAD_CAST "]: The character content is not valid.\n");
1282 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
1283 }
1284 FREE_AND_NULL(str)
1285 xmlFree(msg);
1286}
1287
1288/**
William M. Brack2f2a6632004-08-20 23:09:47 +00001289 * xmlSchemaVComplexTypeErr:
1290 * @ctxt: the schema validation context
1291 * @error: the error code
1292 * @node: the node containing the validated value
1293 * @type: the complex type used for validation
1294 * @message: the error message
1295 *
1296 * Reports a complex type validation error.
1297 */
1298static void
1299xmlSchemaVComplexTypeErr(xmlSchemaValidCtxtPtr ctxt,
1300 xmlParserErrors error,
1301 xmlNodePtr node,
1302 xmlSchemaTypePtr type,
1303 const char *message)
1304{
1305 xmlChar *str = NULL, *msg = NULL;
1306
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00001307 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00001308 /* Specify the complex type only if it is global. */
1309 if ((type != NULL) && (type->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00001310 msg = xmlStrcat(msg, BAD_CAST " [");
1311 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1312 msg = xmlStrcat(msg, BAD_CAST "]");
1313 }
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001314 msg = xmlStrcat(msg, BAD_CAST ": %s.\n");
1315 xmlSchemaVErr(ctxt, node, error, (const char *) msg,
William M. Brack2f2a6632004-08-20 23:09:47 +00001316 (const xmlChar *) message, NULL);
1317 FREE_AND_NULL(str)
1318 xmlFree(msg);
1319}
1320
1321/**
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001322 * xmlSchemaVComplexTypeElemErr:
1323 * @ctxt: the schema validation context
1324 * @error: the error code
1325 * @node: the node containing the validated value
1326 * @type: the complex type used for validation
1327 * @message: the error message
1328 *
1329 * Reports a complex type validation error.
1330 */
1331static void
1332xmlSchemaVComplexTypeElemErr(xmlSchemaValidCtxtPtr ctxt,
1333 xmlParserErrors error,
1334 xmlNodePtr node,
1335 xmlSchemaTypePtr type,
1336 const char *message,
1337 int nbval,
1338 int nbneg,
1339 xmlChar **values)
1340{
1341 xmlChar *str = NULL, *msg = NULL;
1342 xmlChar *localName, *nsName;
1343 const xmlChar *cur, *end;
1344 int i;
1345
1346 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
1347 /* Specify the complex type only if it is global. */
1348 if ((type != NULL) && (type->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
1349 msg = xmlStrcat(msg, BAD_CAST " [");
1350 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1351 msg = xmlStrcat(msg, BAD_CAST "]");
1352 FREE_AND_NULL(str)
1353 }
1354 msg = xmlStrcat(msg, BAD_CAST ": ");
1355 msg = xmlStrcat(msg, (const xmlChar *) message);
1356 /*
1357 * Note that is does not make sense to report that we have a
1358 * wildcard here, since the wildcard might be unfolded into
1359 * multiple transitions.
1360 */
1361 if (nbval + nbneg > 0) {
1362 if (nbval + nbneg > 1) {
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00001363 str = xmlStrdup(BAD_CAST ". Expected is one of ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001364 } else
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00001365 str = xmlStrdup(BAD_CAST ". Expected is ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001366 nsName = NULL;
1367
1368 for (i = 0; i < nbval + nbneg; i++) {
1369 cur = values[i];
1370 /*
1371 * Get the local name.
1372 */
1373 localName = NULL;
1374
1375 end = cur;
1376 if (*end == '*') {
1377 localName = xmlStrdup(BAD_CAST "*");
1378 *end++;
1379 } else {
1380 while ((*end != 0) && (*end != '|'))
1381 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001382 localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001383 }
1384 if (*end != 0) {
1385 *end++;
1386 /*
1387 * Skip "*|*" if they come with negated expressions, since
1388 * they represent the same negated wildcard.
1389 */
1390 if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
1391 /*
1392 * Get the namespace name.
1393 */
1394 cur = end;
1395 if (*end == '*') {
1396 nsName = xmlStrdup(BAD_CAST "{*}");
1397 } else {
1398 while (*end != 0)
1399 end++;
1400
1401 if (i >= nbval)
1402 nsName = xmlStrdup(BAD_CAST "{##other:");
1403 else
1404 nsName = xmlStrdup(BAD_CAST "{");
1405
1406 nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
1407 nsName = xmlStrcat(nsName, BAD_CAST "}");
1408 }
1409 str = xmlStrcat(str, BAD_CAST nsName);
1410 FREE_AND_NULL(nsName)
1411 } else {
1412 FREE_AND_NULL(localName);
1413 continue;
1414 }
1415 }
1416 str = xmlStrcat(str, BAD_CAST localName);
1417 FREE_AND_NULL(localName);
1418
1419 if (i < nbval + nbneg -1)
1420 str = xmlStrcat(str, BAD_CAST ", ");
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00001421 }
1422 str = xmlStrcat(str, BAD_CAST " )");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001423 msg = xmlStrcat(msg, BAD_CAST str);
1424 FREE_AND_NULL(str)
1425 }
1426 msg = xmlStrcat(msg, BAD_CAST ".\n");
1427 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
1428 xmlFree(msg);
1429}
1430
1431/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00001432 * xmlSchemaPMissingAttrErr:
1433 * @ctxt: the schema validation context
1434 * @ownerDes: the designation of the owner
1435 * @ownerName: the name of the owner
1436 * @ownerItem: the owner as a schema object
1437 * @ownerElem: the owner as an element node
1438 * @node: the parent element node of the missing attribute node
1439 * @type: the corresponding type of the attribute node
1440 *
1441 * Reports an illegal attribute.
1442 */
1443static void
1444xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
1445 xmlParserErrors error,
1446 xmlChar **ownerDes,
1447 xmlSchemaTypePtr ownerItem,
1448 xmlNodePtr ownerElem,
1449 const char *name,
1450 const char *message)
1451{
1452 xmlChar *des = NULL;
1453
1454 if (ownerDes == NULL)
1455 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
1456 else if (*ownerDes == NULL) {
1457 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
1458 des = *ownerDes;
1459 } else
1460 des = *ownerDes;
1461 if (message != NULL)
1462 xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
1463 else
1464 xmlSchemaPErr(ctxt, ownerElem, error,
1465 "%s: The attribute '%s' is required but missing.\n",
1466 BAD_CAST des, BAD_CAST name);
1467 if (ownerDes == NULL)
1468 FREE_AND_NULL(des);
1469}
1470
William M. Brack2f2a6632004-08-20 23:09:47 +00001471/**
1472 * xmlSchemaCompTypeToString:
1473 * @type: the type of the schema item
1474 *
1475 * Returns the component name of a schema item.
1476 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001477static const char *
1478xmlSchemaCompTypeToString(xmlSchemaTypeType type)
1479{
1480 switch (type) {
1481 case XML_SCHEMA_TYPE_SIMPLE:
1482 return("simple type definition");
1483 case XML_SCHEMA_TYPE_COMPLEX:
1484 return("complex type definition");
1485 case XML_SCHEMA_TYPE_ELEMENT:
1486 return("element declaration");
1487 case XML_SCHEMA_TYPE_ATTRIBUTE:
1488 return("attribute declaration");
1489 case XML_SCHEMA_TYPE_GROUP:
1490 return("model group definition");
1491 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1492 return("attribute group definition");
1493 case XML_SCHEMA_TYPE_NOTATION:
1494 return("notation declaration");
1495 default:
1496 return("Not a schema component");
1497 }
1498}
1499/**
1500 * xmlSchemaPResCompAttrErr:
1501 * @ctxt: the schema validation context
1502 * @error: the error code
1503 * @ownerDes: the designation of the owner
1504 * @ownerItem: the owner as a schema object
1505 * @ownerElem: the owner as an element node
1506 * @name: the name of the attribute holding the QName
1507 * @refName: the referenced local name
1508 * @refURI: the referenced namespace URI
1509 * @message: optional message
1510 *
1511 * Used to report QName attribute values that failed to resolve
1512 * to schema components.
1513 */
1514static void
1515xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
1516 xmlParserErrors error,
1517 xmlChar **ownerDes,
1518 xmlSchemaTypePtr ownerItem,
1519 xmlNodePtr ownerElem,
1520 const char *name,
1521 const xmlChar *refName,
1522 const xmlChar *refURI,
1523 xmlSchemaTypeType refType,
1524 const char *refTypeStr)
1525{
1526 xmlChar *des = NULL, *strA = NULL;
1527
1528 if (ownerDes == NULL)
1529 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
1530 else if (*ownerDes == NULL) {
1531 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
1532 des = *ownerDes;
1533 } else
1534 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001535 if (refTypeStr == NULL)
1536 refTypeStr = xmlSchemaCompTypeToString(refType);
1537 xmlSchemaPErrExt(ctxt, ownerElem, error,
1538 NULL, NULL, NULL,
1539 "%s, attribute '%s': The QName value %s does not resolve to a(n) "
1540 "%s.\n", BAD_CAST des, BAD_CAST name,
1541 xmlSchemaFormatNsUriLocal(&strA, refURI, refName),
1542 BAD_CAST refTypeStr, NULL);
1543 if (ownerDes == NULL)
1544 FREE_AND_NULL(des)
1545 FREE_AND_NULL(strA)
1546}
1547
William M. Brack2f2a6632004-08-20 23:09:47 +00001548/**
1549 * xmlSchemaPCustomAttrErr:
1550 * @ctxt: the schema parser context
1551 * @error: the error code
1552 * @ownerDes: the designation of the owner
1553 * @ownerItem: the owner as a schema object
1554 * @attr: the illegal attribute node
1555 *
1556 * Reports an illegal attribute during the parse.
1557 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001558static void
1559xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00001560 xmlParserErrors error,
1561 xmlChar **ownerDes,
1562 xmlSchemaTypePtr ownerItem,
1563 xmlAttrPtr attr,
1564 const char *msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001565{
1566 xmlChar *des = NULL;
1567
1568 if (ownerDes == NULL)
1569 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
1570 else if (*ownerDes == NULL) {
1571 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
1572 des = *ownerDes;
1573 } else
1574 des = *ownerDes;
1575 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
1576 "%s, attribute '%s': %s.\n",
1577 BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
1578 if (ownerDes == NULL)
1579 FREE_AND_NULL(des);
1580}
1581
1582/**
1583 * xmlSchemaPIllegalAttrErr:
William M. Brack2f2a6632004-08-20 23:09:47 +00001584 * @ctxt: the schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00001585 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00001586 * @ownerDes: the designation of the attribute's owner
1587 * @ownerItem: the attribute's owner item
Daniel Veillardc0826a72004-08-10 14:17:33 +00001588 * @attr: the illegal attribute node
1589 *
William M. Brack2f2a6632004-08-20 23:09:47 +00001590 * Reports an illegal attribute during the parse.
Daniel Veillardc0826a72004-08-10 14:17:33 +00001591 */
1592static void
1593xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
1594 xmlParserErrors error,
1595 xmlChar **ownerDes,
1596 xmlSchemaTypePtr ownerItem,
1597 xmlAttrPtr attr)
1598{
1599 xmlChar *des = NULL, *strA = NULL;
1600
1601 if (ownerDes == NULL)
1602 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
1603 else if (*ownerDes == NULL) {
1604 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
1605 des = *ownerDes;
1606 } else
1607 des = *ownerDes;
1608 xmlSchemaPErr(ctxt, (xmlNodePtr) attr, error,
1609 "%s: The attribute '%s' is not allowed.\n", BAD_CAST des,
1610 xmlSchemaFormatNsPrefixLocal(&strA, attr->ns, attr->name));
1611 if (ownerDes == NULL)
1612 FREE_AND_NULL(des);
1613 FREE_AND_NULL(strA);
1614}
1615
William M. Brack2f2a6632004-08-20 23:09:47 +00001616/**
1617 * xmlSchemaPAquireDes:
1618 * @des: the first designation
1619 * @itemDes: the second designation
1620 * @item: the schema item
1621 * @itemElem: the node of the schema item
1622 *
1623 * Creates a designation for an item.
1624 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001625static void
1626xmlSchemaPAquireDes(xmlChar **des,
1627 xmlChar **itemDes,
1628 xmlSchemaTypePtr item,
1629 xmlNodePtr itemElem)
1630{
1631 if (itemDes == NULL)
1632 xmlSchemaFormatItemForReport(des, NULL, item, itemElem, 1);
1633 else if (*itemDes == NULL) {
1634 xmlSchemaFormatItemForReport(itemDes, NULL, item, itemElem, 1);
1635 *des = *itemDes;
1636 } else
1637 *des = *itemDes;
1638}
1639
William M. Brack2f2a6632004-08-20 23:09:47 +00001640/**
1641 * xmlSchemaPCustomErr:
1642 * @ctxt: the schema parser context
1643 * @error: the error code
1644 * @itemDes: the designation of the schema item
1645 * @item: the schema item
1646 * @itemElem: the node of the schema item
1647 * @message: the error message
1648 * @str1: an optional param for the error message
1649 * @str2: an optional param for the error message
1650 * @str3: an optional param for the error message
1651 *
1652 * Reports an error during parsing.
1653 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001654static void
1655xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
1656 xmlParserErrors error,
1657 xmlChar **itemDes,
1658 xmlSchemaTypePtr item,
1659 xmlNodePtr itemElem,
1660 const char *message,
1661 const xmlChar *str1,
1662 const xmlChar *str2,
1663 const xmlChar *str3)
1664{
1665 xmlChar *des = NULL, *msg = NULL;
1666
1667 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
1668 msg = xmlStrdup(BAD_CAST "%s: ");
1669 msg = xmlStrcat(msg, (const xmlChar *) message);
1670 msg = xmlStrcat(msg, BAD_CAST ".\n");
1671 if ((itemElem == NULL) && (item != NULL))
1672 itemElem = item->node;
1673 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
1674 (const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
1675 if (itemDes == NULL)
1676 FREE_AND_NULL(des);
1677 FREE_AND_NULL(msg);
1678}
1679
William M. Brack2f2a6632004-08-20 23:09:47 +00001680/**
1681 * xmlSchemaPCustomErr:
1682 * @ctxt: the schema parser context
1683 * @error: the error code
1684 * @itemDes: the designation of the schema item
1685 * @item: the schema item
1686 * @itemElem: the node of the schema item
1687 * @message: the error message
1688 * @str1: the optional param for the error message
1689 *
1690 * Reports an error during parsing.
1691 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001692static void
1693xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
1694 xmlParserErrors error,
1695 xmlChar **itemDes,
1696 xmlSchemaTypePtr item,
1697 xmlNodePtr itemElem,
1698 const char *message,
1699 const xmlChar *str1)
1700{
1701 xmlSchemaPCustomErrExt(ctxt, error, itemDes, item, itemElem, message,
1702 str1, NULL, NULL);
1703}
1704
William M. Brack2f2a6632004-08-20 23:09:47 +00001705/**
1706 * xmlSchemaPAttrUseErr:
1707 * @ctxt: the schema parser context
1708 * @error: the error code
1709 * @itemDes: the designation of the schema type
1710 * @item: the schema type
1711 * @itemElem: the node of the schema type
1712 * @attr: the invalid schema attribute
1713 * @message: the error message
1714 * @str1: the optional param for the error message
1715 *
1716 * Reports an attribute use error during parsing.
1717 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001718static void
1719xmlSchemaPAttrUseErr(xmlSchemaParserCtxtPtr ctxt,
1720 xmlParserErrors error,
1721 xmlChar **itemDes,
1722 xmlSchemaTypePtr item,
1723 xmlNodePtr itemElem,
1724 const xmlSchemaAttributePtr attr,
1725 const char *message,
1726 const xmlChar *str1)
1727{
1728 xmlChar *des = NULL, *strA = NULL, *msg = NULL;
1729
1730 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
1731 xmlSchemaFormatNsUriLocal(&strA, xmlSchemaGetAttrTargetNsURI(attr),
1732 xmlSchemaGetAttrName(attr));
1733 msg = xmlStrdup(BAD_CAST "%s, attr. use %s: ");
1734 msg = xmlStrcat(msg, (const xmlChar *) message);
1735 msg = xmlStrcat(msg, BAD_CAST ".\n");
1736 if ((itemElem == NULL) && (item != NULL))
1737 itemElem = item->node;
1738 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
1739 (const char *) msg, BAD_CAST des, BAD_CAST strA, str1, NULL, NULL);
1740 if (itemDes == NULL)
1741 FREE_AND_NULL(des);
1742 FREE_AND_NULL(strA);
1743 xmlFree(msg);
1744}
1745
William M. Brack2f2a6632004-08-20 23:09:47 +00001746/**
1747 * xmlSchemaPIllegalFacetAtomicErr:
1748 * @ctxt: the schema parser context
1749 * @error: the error code
1750 * @itemDes: the designation of the type
1751 * @item: the schema type
1752 * @baseItem: the base type of type
1753 * @facet: the illegal facet
1754 *
1755 * Reports an illegal facet for atomic simple types.
1756 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001757static void
1758xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
1759 xmlParserErrors error,
1760 xmlChar **itemDes,
1761 xmlSchemaTypePtr item,
1762 xmlSchemaTypePtr baseItem,
1763 xmlSchemaFacetPtr facet)
1764{
1765 xmlChar *des = NULL, *strT = NULL;
1766
1767 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
1768 xmlSchemaPErrExt(ctxt, item->node, error, NULL, NULL, NULL,
1769 "%s: The facet '%s' is not allowed on types derived from the "
1770 "type %s.\n",
1771 BAD_CAST des, BAD_CAST xmlSchemaFacetTypeToString(facet->type),
1772 xmlSchemaFormatItemForReport(&strT, NULL, baseItem, NULL, 1),
1773 NULL, NULL);
1774 if (itemDes == NULL)
1775 FREE_AND_NULL(des);
1776 FREE_AND_NULL(strT);
1777}
1778
William M. Brack2f2a6632004-08-20 23:09:47 +00001779/**
1780 * xmlSchemaPIllegalFacetListUnionErr:
1781 * @ctxt: the schema parser context
1782 * @error: the error code
1783 * @itemDes: the designation of the schema item involved
1784 * @item: the schema item involved
1785 * @facet: the illegal facet
1786 *
1787 * Reports an illegal facet for <list> and <union>.
1788 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001789static void
1790xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
1791 xmlParserErrors error,
1792 xmlChar **itemDes,
1793 xmlSchemaTypePtr item,
1794 xmlSchemaFacetPtr facet)
1795{
1796 xmlChar *des = NULL, *strT = NULL;
1797
1798 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
1799 xmlSchemaPErr(ctxt, item->node, error,
1800 "%s: The facet '%s' is not allowed.\n",
1801 BAD_CAST des, BAD_CAST xmlSchemaFacetTypeToString(facet->type));
1802 if (itemDes == NULL)
1803 FREE_AND_NULL(des);
1804 FREE_AND_NULL(strT);
1805}
1806
1807/**
1808 * xmlSchemaPMutualExclAttrErr:
1809 * @ctxt: the schema validation context
1810 * @error: the error code
1811 * @elemDes: the designation of the parent element node
1812 * @attr: the bad attribute node
1813 * @type: the corresponding type of the attribute node
1814 *
1815 * Reports an illegal attribute.
1816 */
1817static void
1818xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
1819 xmlParserErrors error,
1820 xmlChar **ownerDes,
1821 xmlSchemaTypePtr ownerItem,
1822 xmlAttrPtr attr,
1823 const char *name1,
1824 const char *name2)
1825{
1826 xmlChar *des = NULL;
1827
1828 if (ownerDes == NULL)
1829 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
1830 else if (*ownerDes == NULL) {
1831 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
1832 des = *ownerDes;
1833 } else
1834 des = *ownerDes;
1835 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
1836 "%s: The attributes '%s' and '%s' are mutually exclusive.\n",
1837 BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
1838 if (ownerDes == NULL)
1839 FREE_AND_NULL(des)
1840}
1841
1842/**
1843 * xmlSchemaPSimpleTypeErr:
1844 * @ctxt: the schema validation context
1845 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00001846 * @type: the type specifier
Daniel Veillardc0826a72004-08-10 14:17:33 +00001847 * @ownerDes: the designation of the owner
1848 * @ownerItem: the schema object if existent
1849 * @node: the validated node
1850 * @value: the validated value
1851 *
1852 * Reports a simple type validation error.
1853 * TODO: Should this report the value of an element as well?
1854 */
1855static void
1856xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
1857 xmlParserErrors error,
1858 xmlChar **ownerDes,
1859 xmlSchemaTypePtr ownerItem,
1860 xmlNodePtr node,
William M. Brack2f2a6632004-08-20 23:09:47 +00001861 xmlSchemaTypePtr type,
Daniel Veillardc0826a72004-08-10 14:17:33 +00001862 const char *typeDes,
1863 const xmlChar *value,
1864 const char *message,
1865 const xmlChar *str1,
1866 const xmlChar *str2)
1867{
William M. Brack2f2a6632004-08-20 23:09:47 +00001868 xmlChar *des = NULL, *strA = NULL, *strT = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001869
1870 if (ownerDes == NULL)
1871 xmlSchemaPRequestItemDes(&des, ownerItem, node);
1872 else if (*ownerDes == NULL) {
1873 xmlSchemaPRequestItemDes(ownerDes, ownerItem, node);
1874 des = *ownerDes;
1875 } else
1876 des = *ownerDes;
William M. Brack2f2a6632004-08-20 23:09:47 +00001877 if (type != NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001878 typeDes = (const char *) xmlSchemaFormatItemForReport(&strT, NULL, type, NULL, 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001879 if (message == NULL) {
1880 /*
1881 * Use default messages.
1882 */
1883 if (node->type == XML_ATTRIBUTE_NODE) {
1884 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
1885 "%s, attribute '%s' [%s]: The value '%s' is not "
1886 "valid.\n",
1887 BAD_CAST des, xmlSchemaFormatNsPrefixLocal(&strA, node->ns,
1888 node->name), BAD_CAST typeDes, value, NULL);
1889 } else {
1890 xmlSchemaPErr(ctxt, node, error,
1891 "%s [%s]: The character content is not valid.\n",
1892 BAD_CAST des, BAD_CAST typeDes);
1893 }
1894 } else {
1895 xmlChar *msg;
1896
1897 msg = xmlStrdup(BAD_CAST "%s");
1898 if (node->type == XML_ATTRIBUTE_NODE)
1899 msg = xmlStrcat(msg, BAD_CAST ", attribute '%s'");
1900 msg = xmlStrcat(msg, BAD_CAST " [%s]: ");
1901 msg = xmlStrcat(msg, (const xmlChar *) message);
1902 msg = xmlStrcat(msg, BAD_CAST ".\n");
1903 if (node->type == XML_ATTRIBUTE_NODE) {
1904 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
1905 (const char *) msg,
1906 BAD_CAST des, xmlSchemaFormatNsPrefixLocal(&strA,
1907 node->ns, node->name), BAD_CAST typeDes, str1, str2);
1908 } else {
1909 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
1910 (const char *) msg,
1911 BAD_CAST des, BAD_CAST typeDes, str1, str2, NULL);
1912 }
1913 xmlFree(msg);
1914 }
1915 /* Cleanup. */
1916 FREE_AND_NULL(strA)
1917 FREE_AND_NULL(strT)
1918 if (ownerDes == NULL)
1919 FREE_AND_NULL(des)
1920}
1921
William M. Brack2f2a6632004-08-20 23:09:47 +00001922/**
1923 * xmlSchemaPContentErr:
1924 * @ctxt: the schema parser context
1925 * @error: the error code
1926 * @onwerDes: the designation of the holder of the content
1927 * @ownerItem: the owner item of the holder of the content
1928 * @ownerElem: the node of the holder of the content
1929 * @child: the invalid child node
1930 * @message: the optional error message
1931 * @content: the optional string describing the correct content
1932 *
1933 * Reports an error concerning the content of a schema element.
1934 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001935static void
1936xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
1937 xmlParserErrors error,
1938 xmlChar **ownerDes,
1939 xmlSchemaTypePtr ownerItem,
1940 xmlNodePtr ownerElem,
1941 xmlNodePtr child,
1942 const char *message,
1943 const char *content)
1944{
1945 xmlChar *des = NULL;
1946
1947 if (ownerDes == NULL)
1948 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
1949 else if (*ownerDes == NULL) {
1950 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
1951 des = *ownerDes;
1952 } else
1953 des = *ownerDes;
1954 if (message != NULL)
1955 xmlSchemaPErr2(ctxt, ownerElem, child, error,
1956 "%s: %s.\n",
1957 BAD_CAST des, BAD_CAST message);
1958 else {
1959 if (content != NULL) {
1960 xmlSchemaPErr2(ctxt, ownerElem, child, error,
1961 "%s: The content is not valid. Expected is %s.\n",
1962 BAD_CAST des, BAD_CAST content);
1963 } else {
1964 xmlSchemaPErr2(ctxt, ownerElem, child, error,
1965 "%s: The content is not valid.\n",
1966 BAD_CAST des, NULL);
1967 }
1968 }
1969 if (ownerDes == NULL)
1970 FREE_AND_NULL(des)
1971}
1972
1973/**
1974 * xmlSchemaVIllegalAttrErr:
1975 * @ctxt: the schema validation context
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001976 * @error: the error code
Daniel Veillardc0826a72004-08-10 14:17:33 +00001977 * @attr: the illegal attribute node
1978 *
1979 * Reports an illegal attribute.
1980 */
1981static void
1982xmlSchemaVIllegalAttrErr(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001983 xmlParserErrors error,
William M. Brack2f2a6632004-08-20 23:09:47 +00001984 xmlAttrPtr attr)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001985{
1986 xmlChar *strE = NULL, *strA = NULL;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001987
1988 xmlSchemaVErr(ctxt, (xmlNodePtr) attr,
1989 error,
1990 /* XML_SCHEMAS_ERR_ATTRUNKNOWN, */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001991 "%s: The attribute '%s' is not allowed.\n",
1992 xmlSchemaFormatItemForReport(&strE, NULL, NULL, attr->parent, 0),
1993 xmlSchemaFormatNsPrefixLocal(&strA, attr->ns, attr->name));
1994 FREE_AND_NULL(strE)
1995 FREE_AND_NULL(strA)
1996}
1997
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00001998
1999static int
2000xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
2001{
2002 switch (item->type) {
2003 case XML_SCHEMA_TYPE_COMPLEX:
2004 case XML_SCHEMA_TYPE_SIMPLE:
2005 case XML_SCHEMA_TYPE_GROUP:
2006 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
2007 return(1);
2008 break;
2009 case XML_SCHEMA_TYPE_ELEMENT:
2010 if ( ((xmlSchemaElementPtr) item)->flags &
2011 XML_SCHEMAS_ELEM_GLOBAL)
2012 return(1);
2013 break;
2014 case XML_SCHEMA_TYPE_ATTRIBUTE:
2015 if ( ((xmlSchemaAttributePtr) item)->flags &
2016 XML_SCHEMAS_ATTR_GLOBAL)
2017 return(1);
2018 break;
2019 /* Note that attribute groups are always global. */
2020 default:
2021 return(1);
2022 }
2023 return (0);
2024}
2025
William M. Brack2f2a6632004-08-20 23:09:47 +00002026/**
2027 * xmlSchemaVCustomErr:
2028 * @ctxt: the schema validation context
2029 * @error: the error code
2030 * @node: the validated node
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002031 * @type: the schema type of the validated node
William M. Brack2f2a6632004-08-20 23:09:47 +00002032 * @message: the error message
2033 * @str1: the optional param for the message
2034 *
2035 * Reports a validation error.
2036 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002037static void
2038xmlSchemaVCustomErr(xmlSchemaValidCtxtPtr ctxt,
2039 xmlParserErrors error,
2040 xmlNodePtr node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002041 xmlSchemaTypePtr type,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002042 const char *message,
2043 const xmlChar *str1)
2044{
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002045 xmlChar *msg = NULL, *str = NULL;
2046
2047 if (node == NULL) {
2048 xmlSchemaVErr(ctxt, NULL,
2049 XML_SCHEMAV_INTERNAL,
2050 "Internal error: xmlSchemaVCustomErr, no node "
2051 "given.\n", NULL, NULL);
2052 return;
2053 }
2054 /* TODO: Are the HTML and DOCB doc nodes expected here? */
2055 if (node->type != XML_DOCUMENT_NODE) {
2056 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002057 if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002058 msg = xmlStrcat(msg, BAD_CAST " [");
2059 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
2060 msg = xmlStrcat(msg, BAD_CAST "]");
2061 }
2062 msg = xmlStrcat(msg, BAD_CAST ": ");
2063 } else
2064 msg = xmlStrdup((const xmlChar *) "");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002065 msg = xmlStrcat(msg, (const xmlChar *) message);
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002066 msg = xmlStrcat(msg, BAD_CAST ".\n");
2067 xmlSchemaVErr(ctxt, node, error, (const char *) msg, str1, NULL);
2068 FREE_AND_NULL(msg)
2069 FREE_AND_NULL(str)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002070}
2071
William M. Brack2f2a6632004-08-20 23:09:47 +00002072/**
2073 * xmlSchemaWildcardPCToString:
2074 * @pc: the type of processContents
2075 *
2076 * Returns a string representation of the type of
2077 * processContents.
2078 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002079static const char *
2080xmlSchemaWildcardPCToString(int pc)
2081{
2082 switch (pc) {
2083 case XML_SCHEMAS_ANY_SKIP:
2084 return ("skip");
2085 case XML_SCHEMAS_ANY_LAX:
2086 return ("lax");
2087 case XML_SCHEMAS_ANY_STRICT:
2088 return ("strict");
2089 default:
2090 return ("invalid process contents");
2091 }
2092}
2093
William M. Brack2f2a6632004-08-20 23:09:47 +00002094/**
2095 * xmlSchemaVWildcardErr:
2096 * @ctxt: the schema validation context
2097 * @error: the error code
2098 * @node: the validated node
2099 * @wild: the wildcard used
2100 * @message: the error message
2101 *
2102 * Reports an validation-by-wildcard error.
2103 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002104static void
2105xmlSchemaVWildcardErr(xmlSchemaValidCtxtPtr ctxt,
2106 xmlParserErrors error,
2107 xmlNodePtr node,
2108 xmlSchemaWildcardPtr wild,
2109 const char *message)
2110{
2111 xmlChar *des = NULL, *msg = NULL;
2112
2113 xmlSchemaFormatItemForReport(&des, NULL, NULL, node, 0);
2114 msg = xmlStrdup(BAD_CAST "%s, [");
2115 msg = xmlStrcat(msg, BAD_CAST xmlSchemaWildcardPCToString(wild->processContents));
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002116 msg = xmlStrcat(msg, BAD_CAST " wildcard]: ");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002117 msg = xmlStrcat(msg, (const xmlChar *) message);
2118 msg = xmlStrcat(msg, BAD_CAST ".\n");
2119 xmlSchemaVErr(ctxt, node, error, (const char *) msg, BAD_CAST des, NULL);
2120 FREE_AND_NULL(des);
2121 FREE_AND_NULL(msg);
2122}
2123
2124/**
2125 * xmlSchemaVMissingAttrErr:
2126 * @ctxt: the schema validation context
2127 * @node: the parent element node of the missing attribute node
2128 * @type: the corresponding type of the attribute node
2129 *
2130 * Reports an illegal attribute.
2131 */
2132static void
2133xmlSchemaVMissingAttrErr(xmlSchemaValidCtxtPtr ctxt,
2134 xmlNodePtr elem,
2135 xmlSchemaAttributePtr type)
2136{
2137 const xmlChar *name, *uri;
2138 xmlChar *strE = NULL, *strA = NULL;
2139
2140 if (type->ref != NULL) {
2141 name = type->ref;
2142 uri = type->refNs;
2143 } else {
2144 name = type->name;
2145 uri = type->targetNamespace;
2146 }
2147 xmlSchemaVErr(ctxt, elem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002148 XML_SCHEMAV_CVC_COMPLEX_TYPE_4,
2149 /* XML_SCHEMAS_ERR_MISSING, */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002150 "%s: The attribute %s is required but missing.\n",
2151 xmlSchemaFormatItemForReport(&strE, NULL, NULL, elem, 0),
2152 xmlSchemaFormatNsUriLocal(&strA, uri, name));
2153 FREE_AND_NULL(strE)
2154 FREE_AND_NULL(strA)
2155}
2156
Daniel Veillard4255d502002-04-16 15:50:10 +00002157/************************************************************************
2158 * *
2159 * Allocation functions *
2160 * *
2161 ************************************************************************/
2162
2163/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002164 * xmlSchemaNewSchemaForParserCtxt:
William M. Brack08171912003-12-29 02:52:11 +00002165 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00002166 *
2167 * Allocate a new Schema structure.
2168 *
2169 * Returns the newly allocated structure or NULL in case or error
2170 */
2171static xmlSchemaPtr
2172xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
2173{
2174 xmlSchemaPtr ret;
2175
2176 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
2177 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002178 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002179 return (NULL);
2180 }
2181 memset(ret, 0, sizeof(xmlSchema));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002182 ret->dict = ctxt->dict;
Daniel Veillard500a1de2004-03-22 15:22:58 +00002183 xmlDictReference(ret->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00002184
2185 return (ret);
2186}
2187
2188/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002189 * xmlSchemaNewSchema:
2190 * @ctxt: a schema validation context
2191 *
2192 * Allocate a new Schema structure.
2193 *
2194 * Returns the newly allocated structure or NULL in case or error
2195 */
2196static xmlSchemaAssemblePtr
2197xmlSchemaNewAssemble(void)
2198{
2199 xmlSchemaAssemblePtr ret;
2200
2201 ret = (xmlSchemaAssemblePtr) xmlMalloc(sizeof(xmlSchemaAssemble));
2202 if (ret == NULL) {
2203 /* xmlSchemaPErrMemory(ctxt, "allocating assemble info", NULL); */
2204 return (NULL);
2205 }
2206 memset(ret, 0, sizeof(xmlSchemaAssemble));
2207 ret->items = NULL;
2208 return (ret);
2209}
2210
2211/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002212 * xmlSchemaNewFacet:
Daniel Veillard4255d502002-04-16 15:50:10 +00002213 *
2214 * Allocate a new Facet structure.
2215 *
2216 * Returns the newly allocated structure or NULL in case or error
2217 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00002218xmlSchemaFacetPtr
2219xmlSchemaNewFacet(void)
Daniel Veillard4255d502002-04-16 15:50:10 +00002220{
2221 xmlSchemaFacetPtr ret;
2222
2223 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
2224 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002225 return (NULL);
2226 }
2227 memset(ret, 0, sizeof(xmlSchemaFacet));
2228
2229 return (ret);
2230}
2231
2232/**
2233 * xmlSchemaNewAnnot:
William M. Brack08171912003-12-29 02:52:11 +00002234 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00002235 * @node: a node
2236 *
2237 * Allocate a new annotation structure.
2238 *
2239 * Returns the newly allocated structure or NULL in case or error
2240 */
2241static xmlSchemaAnnotPtr
2242xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
2243{
2244 xmlSchemaAnnotPtr ret;
2245
2246 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
2247 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002248 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
Daniel Veillard4255d502002-04-16 15:50:10 +00002249 return (NULL);
2250 }
2251 memset(ret, 0, sizeof(xmlSchemaAnnot));
2252 ret->content = node;
2253 return (ret);
2254}
2255
2256/**
Daniel Veillardfdc91562002-07-01 21:52:03 +00002257 * xmlSchemaFreeAnnot:
2258 * @annot: a schema type structure
2259 *
2260 * Deallocate a annotation structure
2261 */
2262static void
2263xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
2264{
2265 if (annot == NULL)
2266 return;
2267 xmlFree(annot);
2268}
2269
2270/**
Daniel Veillard1d913862003-11-21 00:28:39 +00002271 * xmlSchemaFreeImport:
2272 * @import: a schema import structure
2273 *
2274 * Deallocate an import structure
2275 */
2276static void
2277xmlSchemaFreeImport(xmlSchemaImportPtr import)
2278{
2279 if (import == NULL)
2280 return;
2281
2282 xmlSchemaFree(import->schema);
William M. Brack2f2a6632004-08-20 23:09:47 +00002283 xmlFreeDoc(import->doc);
Daniel Veillard1d913862003-11-21 00:28:39 +00002284 xmlFree(import);
2285}
2286
2287/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002288 * xmlSchemaFreeInclude:
2289 * @include: a schema include structure
2290 *
2291 * Deallocate an include structure
2292 */
2293static void
2294xmlSchemaFreeInclude(xmlSchemaIncludePtr include)
2295{
2296 if (include == NULL)
2297 return;
2298
2299 xmlFreeDoc(include->doc);
2300 xmlFree(include);
2301}
2302
2303/**
2304 * xmlSchemaFreeIncludeList:
2305 * @includes: a schema include list
2306 *
2307 * Deallocate an include structure
2308 */
2309static void
2310xmlSchemaFreeIncludeList(xmlSchemaIncludePtr includes)
2311{
2312 xmlSchemaIncludePtr next;
2313
2314 while (includes != NULL) {
2315 next = includes->next;
2316 xmlSchemaFreeInclude(includes);
2317 includes = next;
2318 }
2319}
2320
2321/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002322 * xmlSchemaFreeNotation:
2323 * @schema: a schema notation structure
2324 *
2325 * Deallocate a Schema Notation structure.
2326 */
2327static void
2328xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
2329{
2330 if (nota == NULL)
2331 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002332 xmlFree(nota);
2333}
2334
2335/**
2336 * xmlSchemaFreeAttribute:
2337 * @schema: a schema attribute structure
2338 *
2339 * Deallocate a Schema Attribute structure.
2340 */
2341static void
2342xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
2343{
2344 if (attr == NULL)
2345 return;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002346 if (attr->annot != NULL)
2347 xmlSchemaFreeAnnot(attr->annot);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002348 if (attr->defVal != NULL)
2349 xmlSchemaFreeValue(attr->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00002350 xmlFree(attr);
2351}
2352
2353/**
Daniel Veillard3646d642004-06-02 19:19:14 +00002354 * xmlSchemaFreeWildcardNsSet:
2355 * set: a schema wildcard namespace
2356 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00002357 * Deallocates a list of wildcard constraint structures.
Daniel Veillard3646d642004-06-02 19:19:14 +00002358 */
2359static void
2360xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
2361{
2362 xmlSchemaWildcardNsPtr next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002363
Daniel Veillard3646d642004-06-02 19:19:14 +00002364 while (set != NULL) {
2365 next = set->next;
2366 xmlFree(set);
2367 set = next;
2368 }
2369}
2370
2371/**
2372 * xmlSchemaFreeWildcard:
Daniel Veillard01fa6152004-06-29 17:04:39 +00002373 * @wildcard: a wildcard structure
Daniel Veillard3646d642004-06-02 19:19:14 +00002374 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00002375 * Deallocates a wildcard structure.
Daniel Veillard3646d642004-06-02 19:19:14 +00002376 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00002377void
Daniel Veillard3646d642004-06-02 19:19:14 +00002378xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
2379{
2380 if (wildcard == NULL)
2381 return;
2382 if (wildcard->annot != NULL)
2383 xmlSchemaFreeAnnot(wildcard->annot);
2384 if (wildcard->nsSet != NULL)
2385 xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
2386 if (wildcard->negNsSet != NULL)
2387 xmlFree(wildcard->negNsSet);
2388 xmlFree(wildcard);
2389}
2390
2391/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002392 * xmlSchemaFreeAttributeGroup:
2393 * @schema: a schema attribute group structure
2394 *
2395 * Deallocate a Schema Attribute Group structure.
2396 */
2397static void
2398xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attr)
2399{
2400 if (attr == NULL)
2401 return;
Daniel Veillard3646d642004-06-02 19:19:14 +00002402 if (attr->annot != NULL)
2403 xmlSchemaFreeAnnot(attr->annot);
2404 if ((attr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) &&
2405 (attr->attributeWildcard != NULL))
2406 xmlSchemaFreeWildcard(attr->attributeWildcard);
2407
Daniel Veillard4255d502002-04-16 15:50:10 +00002408 xmlFree(attr);
2409}
2410
2411/**
Daniel Veillard3646d642004-06-02 19:19:14 +00002412 * xmlSchemaFreeAttributeUseList:
Daniel Veillard01fa6152004-06-29 17:04:39 +00002413 * @attrUse: an attribute link
Daniel Veillard3646d642004-06-02 19:19:14 +00002414 *
2415 * Deallocate a list of schema attribute uses.
2416 */
2417static void
2418xmlSchemaFreeAttributeUseList(xmlSchemaAttributeLinkPtr attrUse)
2419{
2420 xmlSchemaAttributeLinkPtr next;
2421
2422 while (attrUse != NULL) {
2423 next = attrUse->next;
2424 xmlFree(attrUse);
2425 attrUse = next;
2426 }
2427}
2428
2429/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00002430 * xmlSchemaFreeTypeLinkList:
2431 * @alink: a type link
2432 *
2433 * Deallocate a list of types.
2434 */
2435static void
2436xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
2437{
2438 xmlSchemaTypeLinkPtr next;
2439
2440 while (link != NULL) {
2441 next = link->next;
2442 xmlFree(link);
2443 link = next;
2444 }
2445}
2446
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00002447#ifdef IDC_ENABLED
2448static void
2449xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
2450{
2451 xmlSchemaIDCStateObjPtr next;
2452 while (sto != NULL) {
2453 next = sto->next;
2454 if (sto->history != NULL)
2455 xmlFree(sto->history);
2456 if (sto->xpathCtxt != NULL)
2457 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
2458 xmlFree(sto);
2459 sto = next;
2460 }
2461}
2462
2463/**
2464 * xmlSchemaFreeIDC:
2465 * @idc: a identity-constraint definition
2466 *
2467 * Deallocates an identity-constraint definition.
2468 */
2469static void
2470xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)
2471{
2472 xmlSchemaIDCSelectPtr cur, prev;
2473
2474 if (idcDef == NULL)
2475 return;
2476 if (idcDef->annot != NULL)
2477 xmlSchemaFreeAnnot(idcDef->annot);
2478 if (idcDef->ref != NULL)
2479 xmlFree(idcDef->ref);
2480 /* Selector */
2481 if (idcDef->selector != NULL) {
2482 if (idcDef->selector->xpathComp != NULL)
2483 xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp);
2484 xmlFree(idcDef->selector);
2485 }
2486 /* Fields */
2487 if (idcDef->fields != NULL) {
2488 cur = idcDef->fields;
2489 do {
2490 prev = cur;
2491 cur = cur->next;
2492 if (prev->xpathComp != NULL)
2493 xmlFreePattern((xmlPatternPtr) prev->xpathComp);
2494 xmlFree(prev);
2495 } while (cur != NULL);
2496 }
2497 xmlFree(idcDef);
2498}
2499#endif /* IDC_ENABLED */
2500
Daniel Veillard01fa6152004-06-29 17:04:39 +00002501/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002502 * xmlSchemaFreeElement:
2503 * @schema: a schema element structure
2504 *
2505 * Deallocate a Schema Element structure.
2506 */
2507static void
2508xmlSchemaFreeElement(xmlSchemaElementPtr elem)
2509{
2510 if (elem == NULL)
2511 return;
Daniel Veillard32370232002-10-16 14:08:14 +00002512 if (elem->annot != NULL)
2513 xmlSchemaFreeAnnot(elem->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00002514 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002515 xmlRegFreeRegexp(elem->contModel);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002516 if (elem->defVal != NULL)
2517 xmlSchemaFreeValue(elem->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00002518 xmlFree(elem);
2519}
2520
2521/**
2522 * xmlSchemaFreeFacet:
2523 * @facet: a schema facet structure
2524 *
2525 * Deallocate a Schema Facet structure.
2526 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00002527void
Daniel Veillard4255d502002-04-16 15:50:10 +00002528xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
2529{
2530 if (facet == NULL)
2531 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002532 if (facet->val != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002533 xmlSchemaFreeValue(facet->val);
Daniel Veillard4255d502002-04-16 15:50:10 +00002534 if (facet->regexp != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002535 xmlRegFreeRegexp(facet->regexp);
Daniel Veillardfdc91562002-07-01 21:52:03 +00002536 if (facet->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002537 xmlSchemaFreeAnnot(facet->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00002538 xmlFree(facet);
2539}
2540
2541/**
2542 * xmlSchemaFreeType:
2543 * @type: a schema type structure
2544 *
2545 * Deallocate a Schema Type structure.
2546 */
2547void
2548xmlSchemaFreeType(xmlSchemaTypePtr type)
2549{
2550 if (type == NULL)
2551 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002552 if (type->annot != NULL)
Daniel Veillard32370232002-10-16 14:08:14 +00002553 xmlSchemaFreeAnnot(type->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00002554 if (type->facets != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002555 xmlSchemaFacetPtr facet, next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002556
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002557 facet = type->facets;
2558 while (facet != NULL) {
2559 next = facet->next;
2560 xmlSchemaFreeFacet(facet);
2561 facet = next;
2562 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002563 }
Daniel Veillard3646d642004-06-02 19:19:14 +00002564 if (type->type != XML_SCHEMA_TYPE_BASIC) {
2565 if (type->attributeUses != NULL)
2566 xmlSchemaFreeAttributeUseList(type->attributeUses);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002567 if ((type->attributeWildcard != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +00002568 ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002569 (type->flags & XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD))) {
2570 /*
2571 * NOTE: The only case where an attribute wildcard
2572 * is not owned, is if a complex type inherits it
2573 * from a base type.
2574 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002575 xmlSchemaFreeWildcard(type->attributeWildcard);
2576 }
2577 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00002578 if (type->memberTypes != NULL)
2579 xmlSchemaFreeTypeLinkList(type->memberTypes);
2580 if (type->facetSet != NULL) {
2581 xmlSchemaFacetLinkPtr next, link;
2582
2583 link = type->facetSet;
2584 do {
2585 next = link->next;
2586 xmlFree(link);
2587 link = next;
2588 } while (link != NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002589 }
2590 if (type->contModel != NULL)
2591 xmlRegFreeRegexp(type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00002592 xmlFree(type);
2593}
2594
2595/**
Daniel Veillardb0f397e2003-12-23 23:30:53 +00002596 * xmlSchemaFreeTypeList:
2597 * @type: a schema type structure
2598 *
2599 * Deallocate a Schema Type structure.
2600 */
2601static void
2602xmlSchemaFreeTypeList(xmlSchemaTypePtr type)
2603{
2604 xmlSchemaTypePtr next;
2605
2606 while (type != NULL) {
2607 next = type->redef;
2608 xmlSchemaFreeType(type);
2609 type = next;
2610 }
2611}
2612
2613/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002614 * xmlSchemaFree:
2615 * @schema: a schema structure
2616 *
2617 * Deallocate a Schema structure.
2618 */
2619void
2620xmlSchemaFree(xmlSchemaPtr schema)
2621{
2622 if (schema == NULL)
2623 return;
2624
Daniel Veillard4255d502002-04-16 15:50:10 +00002625 if (schema->notaDecl != NULL)
2626 xmlHashFree(schema->notaDecl,
2627 (xmlHashDeallocator) xmlSchemaFreeNotation);
2628 if (schema->attrDecl != NULL)
2629 xmlHashFree(schema->attrDecl,
2630 (xmlHashDeallocator) xmlSchemaFreeAttribute);
2631 if (schema->attrgrpDecl != NULL)
2632 xmlHashFree(schema->attrgrpDecl,
2633 (xmlHashDeallocator) xmlSchemaFreeAttributeGroup);
2634 if (schema->elemDecl != NULL)
2635 xmlHashFree(schema->elemDecl,
2636 (xmlHashDeallocator) xmlSchemaFreeElement);
2637 if (schema->typeDecl != NULL)
2638 xmlHashFree(schema->typeDecl,
Daniel Veillardb0f397e2003-12-23 23:30:53 +00002639 (xmlHashDeallocator) xmlSchemaFreeTypeList);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00002640 if (schema->groupDecl != NULL)
2641 xmlHashFree(schema->groupDecl,
2642 (xmlHashDeallocator) xmlSchemaFreeType);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00002643#ifdef IDC_ENABLED
2644 if (schema->idcDef != NULL)
2645 xmlHashFree(schema->idcDef,
2646 (xmlHashDeallocator) xmlSchemaFreeIDC);
2647#endif
Daniel Veillard1d913862003-11-21 00:28:39 +00002648 if (schema->schemasImports != NULL)
2649 xmlHashFree(schema->schemasImports,
2650 (xmlHashDeallocator) xmlSchemaFreeImport);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002651 if (schema->includes != NULL) {
2652 xmlSchemaFreeIncludeList((xmlSchemaIncludePtr) schema->includes);
2653 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002654 if (schema->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002655 xmlSchemaFreeAnnot(schema->annot);
Daniel Veillarddda22c12004-01-24 08:31:30 +00002656 if (schema->doc != NULL && !schema->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002657 xmlFreeDoc(schema->doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002658 xmlDictFree(schema->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00002659 xmlFree(schema);
2660}
2661
2662/************************************************************************
2663 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00002664 * Debug functions *
2665 * *
2666 ************************************************************************/
2667
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002668#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002669
Daniel Veillard4255d502002-04-16 15:50:10 +00002670/**
2671 * xmlSchemaElementDump:
2672 * @elem: an element
2673 * @output: the file output
2674 *
2675 * Dump the element
2676 */
2677static void
2678xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002679 const xmlChar * name ATTRIBUTE_UNUSED,
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002680 const xmlChar * namespace ATTRIBUTE_UNUSED,
2681 const xmlChar * context ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00002682{
2683 if (elem == NULL)
2684 return;
2685
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002686 if (elem->flags & XML_SCHEMAS_ELEM_REF) {
2687 fprintf(output, "Particle: %s", name);
2688 fprintf(output, ", term element: %s", elem->ref);
2689 if (elem->refNs != NULL)
2690 fprintf(output, " ns %s", elem->refNs);
2691 } else {
2692 fprintf(output, "Element");
2693 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
2694 fprintf(output, " (global)");
2695 fprintf(output, ": %s ", elem->name);
2696 if (namespace != NULL)
2697 fprintf(output, "ns %s", namespace);
2698 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002699 fprintf(output, "\n");
2700 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002701 fprintf(output, " min %d ", elem->minOccurs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002702 if (elem->maxOccurs >= UNBOUNDED)
2703 fprintf(output, "max: unbounded\n");
2704 else if (elem->maxOccurs != 1)
2705 fprintf(output, "max: %d\n", elem->maxOccurs);
2706 else
2707 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002708 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002709 /*
2710 * Misc other properties.
2711 */
2712 if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
2713 (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
2714 (elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
2715 (elem->flags & XML_SCHEMAS_ELEM_DEFAULT) ||
2716 (elem->id != NULL)) {
2717 fprintf(output, " props: ");
2718 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
2719 fprintf(output, "[fixed] ");
2720 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
2721 fprintf(output, "[default] ");
2722 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
2723 fprintf(output, "[abstract] ");
2724 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
2725 fprintf(output, "[nillable] ");
2726 if (elem->id != NULL)
2727 fprintf(output, "[id: '%s'] ", elem->id);
2728 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002729 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002730 /*
2731 * Default/fixed value.
2732 */
Daniel Veillard4255d502002-04-16 15:50:10 +00002733 if (elem->value != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002734 fprintf(output, " value: '%s'\n", elem->value);
2735 /*
2736 * Type.
2737 */
2738 if (elem->namedType != NULL) {
2739 fprintf(output, " type: %s ", elem->namedType);
2740 if (elem->namedTypeNs != NULL)
2741 fprintf(output, "ns %s\n", elem->namedTypeNs);
2742 else
2743 fprintf(output, "\n");
2744 }
2745 /*
2746 * Substitution group.
2747 */
2748 if (elem->substGroup != NULL) {
2749 fprintf(output, " substitutionGroup: %s ", elem->substGroup);
2750 if (elem->substGroupNs != NULL)
2751 fprintf(output, "ns %s\n", elem->substGroupNs);
2752 else
2753 fprintf(output, "\n");
2754 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002755}
2756
2757/**
2758 * xmlSchemaAnnotDump:
2759 * @output: the file output
2760 * @annot: a annotation
2761 *
2762 * Dump the annotation
2763 */
2764static void
2765xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
2766{
2767 xmlChar *content;
2768
2769 if (annot == NULL)
2770 return;
2771
2772 content = xmlNodeGetContent(annot->content);
2773 if (content != NULL) {
2774 fprintf(output, " Annot: %s\n", content);
2775 xmlFree(content);
2776 } else
2777 fprintf(output, " Annot: empty\n");
2778}
2779
2780/**
2781 * xmlSchemaTypeDump:
2782 * @output: the file output
2783 * @type: a type structure
2784 *
2785 * Dump a SchemaType structure
2786 */
2787static void
2788xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
2789{
2790 if (type == NULL) {
2791 fprintf(output, "Type: NULL\n");
2792 return;
2793 }
2794 fprintf(output, "Type: ");
2795 if (type->name != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002796 fprintf(output, "%s ", type->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00002797 else
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002798 fprintf(output, "no name ");
2799 if (type->targetNamespace != NULL)
2800 fprintf(output, "ns %s ", type->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00002801 switch (type->type) {
2802 case XML_SCHEMA_TYPE_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002803 fprintf(output, "[basic] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002804 break;
2805 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002806 fprintf(output, "[simple] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002807 break;
2808 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002809 fprintf(output, "[complex] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002810 break;
2811 case XML_SCHEMA_TYPE_SEQUENCE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002812 fprintf(output, "[sequence] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002813 break;
2814 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002815 fprintf(output, "[choice] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002816 break;
2817 case XML_SCHEMA_TYPE_ALL:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002818 fprintf(output, "[all] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002819 break;
2820 case XML_SCHEMA_TYPE_UR:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002821 fprintf(output, "[ur] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002822 break;
2823 case XML_SCHEMA_TYPE_RESTRICTION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002824 fprintf(output, "[restriction] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002825 break;
2826 case XML_SCHEMA_TYPE_EXTENSION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002827 fprintf(output, "[extension] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002828 break;
2829 default:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002830 fprintf(output, "[unknown type %d] ", type->type);
Daniel Veillard4255d502002-04-16 15:50:10 +00002831 break;
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002832 }
2833 fprintf(output, "content: ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002834 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002835 case XML_SCHEMA_CONTENT_UNKNOWN:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002836 fprintf(output, "[unknown] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002837 break;
2838 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002839 fprintf(output, "[empty] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002840 break;
2841 case XML_SCHEMA_CONTENT_ELEMENTS:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002842 fprintf(output, "[element] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002843 break;
2844 case XML_SCHEMA_CONTENT_MIXED:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002845 fprintf(output, "[mixed] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002846 break;
2847 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00002848 /* not used. */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002849 break;
2850 case XML_SCHEMA_CONTENT_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002851 fprintf(output, "[basic] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002852 break;
2853 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002854 fprintf(output, "[simple] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002855 break;
2856 case XML_SCHEMA_CONTENT_ANY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002857 fprintf(output, "[any] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002858 break;
Daniel Veillard4255d502002-04-16 15:50:10 +00002859 }
2860 fprintf(output, "\n");
2861 if ((type->minOccurs != 1) || (type->maxOccurs != 1)) {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002862 fprintf(output, " min: %d ", type->minOccurs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002863 if (type->maxOccurs >= UNBOUNDED)
2864 fprintf(output, "max: unbounded\n");
2865 else if (type->maxOccurs != 1)
2866 fprintf(output, "max: %d\n", type->maxOccurs);
2867 else
2868 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002869 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002870 if (type->base != NULL) {
2871 fprintf(output, " base type: %s", type->base);
2872 if (type->baseNs != NULL)
2873 fprintf(output, " ns %s\n", type->baseNs);
2874 else
2875 fprintf(output, "\n");
2876 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002877 if (type->annot != NULL)
2878 xmlSchemaAnnotDump(output, type->annot);
2879 if (type->subtypes != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002880 xmlSchemaTypePtr sub = type->subtypes;
Daniel Veillard4255d502002-04-16 15:50:10 +00002881
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002882 fprintf(output, " subtypes: ");
2883 while (sub != NULL) {
2884 fprintf(output, "%s ", sub->name);
2885 sub = sub->next;
2886 }
2887 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002888 }
2889
2890}
2891
2892/**
2893 * xmlSchemaDump:
2894 * @output: the file output
2895 * @schema: a schema structure
2896 *
2897 * Dump a Schema structure.
2898 */
2899void
2900xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
2901{
Daniel Veillardce682bc2004-11-05 17:22:25 +00002902 if (output == NULL)
2903 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002904 if (schema == NULL) {
2905 fprintf(output, "Schemas: NULL\n");
2906 return;
2907 }
2908 fprintf(output, "Schemas: ");
2909 if (schema->name != NULL)
2910 fprintf(output, "%s, ", schema->name);
2911 else
2912 fprintf(output, "no name, ");
2913 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00002914 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00002915 else
2916 fprintf(output, "no target namespace");
2917 fprintf(output, "\n");
2918 if (schema->annot != NULL)
2919 xmlSchemaAnnotDump(output, schema->annot);
2920
2921 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
2922 output);
2923 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002924 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00002925}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00002926
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00002927#ifdef IDC_ENABLED
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00002928/**
2929 * xmlSchemaDebugDumpIDCTable:
2930 * @vctxt: the WXS validation context
2931 *
2932 * Displays the current IDC table for debug purposes.
2933 */
2934static void
2935xmlSchemaDebugDumpIDCTable(FILE * output,
2936 const xmlChar *namespaceName,
2937 const xmlChar *localName,
2938 xmlSchemaPSVIIDCBindingPtr bind)
2939{
2940 xmlChar *str = NULL, *value;
2941 xmlSchemaPSVIIDCNodePtr tab;
2942 xmlSchemaPSVIIDCKeyPtr key;
2943 int i, j, res;
2944
2945 fprintf(output, "IDC: TABLES on %s\n",
2946 xmlSchemaFormatNsUriLocal(&str, namespaceName, localName));
2947 FREE_AND_NULL(str)
2948
2949 if (bind == NULL)
2950 return;
2951 do {
2952 fprintf(output, "IDC: BINDING %s\n",
2953 xmlSchemaFormatNsUriLocal(&str, bind->definition->targetNamespace,
2954 bind->definition->name));
2955 FREE_AND_NULL(str)
2956 for (i = 0; i < bind->nbNodes; i++) {
2957 tab = bind->nodeTable[i];
2958 fprintf(output, " ( ");
2959 for (j = 0; j < bind->definition->nbFields; j++) {
2960 key = tab->keys[j];
2961 if ((key != NULL) && (key->compValue != NULL)) {
2962#ifdef IDC_VALUE_SUPPORT
2963 res = xmlSchemaGetCanonValue(key->compValue, &value);
2964#else
2965 value = xmlStrdup(BAD_CAST "dummy-value");
2966 res = 0;
2967#endif
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00002968 if (res >= 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00002969 fprintf(output, "\"%s\" ", value);
2970 else
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00002971 fprintf(output, "CANON-VALUE-FAILED ");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00002972 if (res == 0)
2973 FREE_AND_NULL(value)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00002974 } else if (key != NULL)
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00002975 fprintf(output, "(no val), ");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00002976 else
2977 fprintf(output, "(key missing), ");
2978 }
2979 fprintf(output, ")\n");
2980 }
2981 bind = bind->next;
2982 } while (bind != NULL);
2983}
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00002984#endif /* IDC_ENABLED */
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002985#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +00002986
2987/************************************************************************
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002988 * *
2989 * Utilities *
2990 * *
2991 ************************************************************************/
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002992
Daniel Veillardc0826a72004-08-10 14:17:33 +00002993/**
2994 * xmlSchemaGetPropNode:
2995 * @node: the element node
2996 * @name: the name of the attribute
2997 *
2998 * Seeks an attribute with a name of @name in
2999 * no namespace.
3000 *
3001 * Returns the attribute or NULL if not present.
3002 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003003static xmlAttrPtr
Daniel Veillardc0826a72004-08-10 14:17:33 +00003004xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
Daniel Veillard01fa6152004-06-29 17:04:39 +00003005{
3006 xmlAttrPtr prop;
3007
Daniel Veillardc0826a72004-08-10 14:17:33 +00003008 if ((node == NULL) || (name == NULL))
3009 return(NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003010 prop = node->properties;
3011 while (prop != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00003012 if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
3013 return(prop);
3014 prop = prop->next;
3015 }
3016 return (NULL);
3017}
3018
3019/**
3020 * xmlSchemaGetPropNodeNs:
3021 * @node: the element node
3022 * @uri: the uri
3023 * @name: the name of the attribute
3024 *
3025 * Seeks an attribute with a local name of @name and
3026 * a namespace URI of @uri.
3027 *
3028 * Returns the attribute or NULL if not present.
3029 */
3030static xmlAttrPtr
3031xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
3032{
3033 xmlAttrPtr prop;
3034
3035 if ((node == NULL) || (name == NULL))
3036 return(NULL);
3037 prop = node->properties;
3038 while (prop != NULL) {
3039 if ((prop->ns != NULL) &&
3040 xmlStrEqual(prop->name, BAD_CAST name) &&
3041 xmlStrEqual(prop->ns->href, BAD_CAST uri))
Daniel Veillard01fa6152004-06-29 17:04:39 +00003042 return(prop);
3043 prop = prop->next;
3044 }
3045 return (NULL);
3046}
3047
3048static const xmlChar *
3049xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3050{
3051 xmlChar *val;
3052 const xmlChar *ret;
3053
3054 val = xmlNodeGetContent(node);
3055 if (val == NULL)
3056 return(NULL);
3057 ret = xmlDictLookup(ctxt->dict, val, -1);
3058 xmlFree(val);
3059 return(ret);
3060}
3061
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003062/**
3063 * xmlSchemaGetProp:
3064 * @ctxt: the parser context
3065 * @node: the node
3066 * @name: the property name
3067 *
3068 * Read a attribute value and internalize the string
3069 *
3070 * Returns the string or NULL if not present.
3071 */
3072static const xmlChar *
3073xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
3074 const char *name)
3075{
3076 xmlChar *val;
3077 const xmlChar *ret;
3078
3079 val = xmlGetProp(node, BAD_CAST name);
3080 if (val == NULL)
3081 return(NULL);
3082 ret = xmlDictLookup(ctxt->dict, val, -1);
3083 xmlFree(val);
3084 return(ret);
3085}
3086
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003087/************************************************************************
Daniel Veillard4255d502002-04-16 15:50:10 +00003088 * *
3089 * Parsing functions *
3090 * *
3091 ************************************************************************/
3092
3093/**
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003094 * xmlSchemaGetElem:
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003095 * @schema: the schema context
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003096 * @name: the element name
3097 * @ns: the element namespace
3098 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003099 * Lookup a global element declaration in the schema.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003100 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003101 * Returns the element declaration or NULL if not found.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003102 */
3103static xmlSchemaElementPtr
3104xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003105 const xmlChar * namespace)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003106{
3107 xmlSchemaElementPtr ret;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003108
3109 if ((name == NULL) || (schema == NULL))
3110 return (NULL);
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003111
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003112 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003113 if ((ret != NULL) &&
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003114 (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003115 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00003116 } else
3117 ret = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00003118 /*
3119 * This one was removed, since top level element declarations have
3120 * the target namespace specified in targetNamespace of the <schema>
3121 * information element, even if elementFormDefault is "unqualified".
3122 */
3123
3124 /* else if ((schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003125 if (xmlStrEqual(namespace, schema->targetNamespace))
3126 ret = xmlHashLookup2(schema->elemDecl, name, NULL);
3127 else
3128 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003129 if ((ret != NULL) &&
3130 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003131 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003132 }
William M. Bracke7091952004-05-11 15:09:58 +00003133 */
Daniel Veillard3646d642004-06-02 19:19:14 +00003134
William M. Brack2f2a6632004-08-20 23:09:47 +00003135 /*
3136 * Removed since imported components will be hold by the main schema only.
3137 *
Daniel Veillard3646d642004-06-02 19:19:14 +00003138 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003139 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003140 else
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003141 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003142 if (import != NULL) {
Daniel Veillardf2a12832003-11-24 13:04:35 +00003143 ret = xmlSchemaGetElem(import->schema, name, namespace, level + 1);
Daniel Veillard3646d642004-06-02 19:19:14 +00003144 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
3145 return (ret);
3146 } else
3147 ret = NULL;
3148 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003149 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003150#ifdef DEBUG
3151 if (ret == NULL) {
3152 if (namespace == NULL)
3153 fprintf(stderr, "Unable to lookup type %s", name);
3154 else
3155 fprintf(stderr, "Unable to lookup type %s:%s", name,
3156 namespace);
3157 }
3158#endif
3159 return (ret);
3160}
3161
3162/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003163 * xmlSchemaGetType:
3164 * @schema: the schemas context
3165 * @name: the type name
3166 * @ns: the type namespace
3167 *
3168 * Lookup a type in the schemas or the predefined types
3169 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003170 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +00003171 */
3172static xmlSchemaTypePtr
3173xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003174 const xmlChar * namespace)
3175{
Daniel Veillard4255d502002-04-16 15:50:10 +00003176 xmlSchemaTypePtr ret;
3177
3178 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003179 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003180 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003181 ret = xmlHashLookup2(schema->typeDecl, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003182 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003183 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003184 }
3185 ret = xmlSchemaGetPredefinedType(name, namespace);
Daniel Veillard1d913862003-11-21 00:28:39 +00003186 if (ret != NULL)
3187 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00003188 /*
3189 * Removed, since the imported components will be grafted on the
3190 * main schema only.
Daniel Veillard3646d642004-06-02 19:19:14 +00003191 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003192 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003193 else
Daniel Veillard1d913862003-11-21 00:28:39 +00003194 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003195 if (import != NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00003196 ret = xmlSchemaGetType(import->schema, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003197 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
3198 return (ret);
3199 } else
3200 ret = NULL;
3201 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003202 */
Daniel Veillard4255d502002-04-16 15:50:10 +00003203#ifdef DEBUG
3204 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003205 if (namespace == NULL)
3206 fprintf(stderr, "Unable to lookup type %s", name);
3207 else
3208 fprintf(stderr, "Unable to lookup type %s:%s", name,
3209 namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003210 }
3211#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003212 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003213}
3214
Daniel Veillard3646d642004-06-02 19:19:14 +00003215/**
3216 * xmlSchemaGetAttribute:
3217 * @schema: the context of the schema
3218 * @name: the name of the attribute
3219 * @ns: the target namespace of the attribute
3220 *
3221 * Lookup a an attribute in the schema or imported schemas
3222 *
3223 * Returns the attribute declaration or NULL if not found.
3224 */
3225static xmlSchemaAttributePtr
3226xmlSchemaGetAttribute(xmlSchemaPtr schema, const xmlChar * name,
3227 const xmlChar * namespace)
3228{
3229 xmlSchemaAttributePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00003230
3231 if ((name == NULL) || (schema == NULL))
3232 return (NULL);
3233
3234
3235 ret = xmlHashLookup2(schema->attrDecl, name, namespace);
3236 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL))
3237 return (ret);
3238 else
3239 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00003240 /*
3241 * Removed, since imported components will be hold by the main schema only.
3242 *
Daniel Veillard3646d642004-06-02 19:19:14 +00003243 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003244 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003245 else
3246 import = xmlHashLookup(schema->schemasImports, namespace);
3247 if (import != NULL) {
3248 ret = xmlSchemaGetAttribute(import->schema, name, namespace);
3249 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL)) {
3250 return (ret);
3251 } else
3252 ret = NULL;
3253 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003254 */
Daniel Veillard3646d642004-06-02 19:19:14 +00003255#ifdef DEBUG
3256 if (ret == NULL) {
3257 if (namespace == NULL)
3258 fprintf(stderr, "Unable to lookup attribute %s", name);
3259 else
3260 fprintf(stderr, "Unable to lookup attribute %s:%s", name,
3261 namespace);
3262 }
3263#endif
3264 return (ret);
3265}
3266
3267/**
3268 * xmlSchemaGetAttributeGroup:
3269 * @schema: the context of the schema
3270 * @name: the name of the attribute group
3271 * @ns: the target namespace of the attribute group
3272 *
3273 * Lookup a an attribute group in the schema or imported schemas
3274 *
3275 * Returns the attribute group definition or NULL if not found.
3276 */
3277static xmlSchemaAttributeGroupPtr
3278xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
3279 const xmlChar * namespace)
3280{
3281 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00003282
3283 if ((name == NULL) || (schema == NULL))
3284 return (NULL);
3285
3286
3287 ret = xmlHashLookup2(schema->attrgrpDecl, name, namespace);
3288 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
3289 return (ret);
3290 else
3291 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00003292 /*
3293 * Removed since imported components will be hold by the main schema only.
3294 *
Daniel Veillard3646d642004-06-02 19:19:14 +00003295 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003296 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003297 else
3298 import = xmlHashLookup(schema->schemasImports, namespace);
3299 if (import != NULL) {
3300 ret = xmlSchemaGetAttributeGroup(import->schema, name, namespace);
3301 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
3302 return (ret);
3303 else
3304 ret = NULL;
3305 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003306 */
Daniel Veillard3646d642004-06-02 19:19:14 +00003307#ifdef DEBUG
3308 if (ret == NULL) {
3309 if (namespace == NULL)
3310 fprintf(stderr, "Unable to lookup attribute group %s", name);
3311 else
3312 fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
3313 namespace);
3314 }
3315#endif
3316 return (ret);
3317}
3318
3319/**
3320 * xmlSchemaGetGroup:
3321 * @schema: the context of the schema
3322 * @name: the name of the group
3323 * @ns: the target namespace of the group
3324 *
3325 * Lookup a group in the schema or imported schemas
3326 *
3327 * Returns the group definition or NULL if not found.
3328 */
3329static xmlSchemaTypePtr
3330xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
3331 const xmlChar * namespace)
3332{
3333 xmlSchemaTypePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00003334
3335 if ((name == NULL) || (schema == NULL))
3336 return (NULL);
3337
3338
3339 ret = xmlHashLookup2(schema->groupDecl, name, namespace);
3340 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
3341 return (ret);
3342 else
3343 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00003344 /*
3345 * Removed since imported components will be hold by the main schema only.
3346 *
Daniel Veillard3646d642004-06-02 19:19:14 +00003347 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003348 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003349 else
3350 import = xmlHashLookup(schema->schemasImports, namespace);
3351 if (import != NULL) {
3352 ret = xmlSchemaGetGroup(import->schema, name, namespace);
3353 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
3354 return (ret);
3355 else
3356 ret = NULL;
3357 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003358 */
Daniel Veillard3646d642004-06-02 19:19:14 +00003359#ifdef DEBUG
3360 if (ret == NULL) {
3361 if (namespace == NULL)
3362 fprintf(stderr, "Unable to lookup group %s", name);
3363 else
3364 fprintf(stderr, "Unable to lookup group %s:%s", name,
3365 namespace);
3366 }
3367#endif
3368 return (ret);
3369}
3370
Daniel Veillard4255d502002-04-16 15:50:10 +00003371/************************************************************************
3372 * *
3373 * Parsing functions *
3374 * *
3375 ************************************************************************/
3376
3377#define IS_BLANK_NODE(n) \
3378 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content)))
3379
3380/**
3381 * xmlSchemaIsBlank:
3382 * @str: a string
3383 *
3384 * Check if a string is ignorable
3385 *
3386 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
3387 */
3388static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003389xmlSchemaIsBlank(xmlChar * str)
3390{
Daniel Veillard4255d502002-04-16 15:50:10 +00003391 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003392 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003393 while (*str != 0) {
William M. Brack76e95df2003-10-18 16:20:14 +00003394 if (!(IS_BLANK_CH(*str)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003395 return (0);
3396 str++;
Daniel Veillard4255d502002-04-16 15:50:10 +00003397 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003398 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003399}
3400
3401/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003402 * xmlSchemaAddAssembledItem:
3403 * @ctxt: a schema parser context
3404 * @schema: the schema being built
3405 * @item: the item
3406 *
3407 * Add a item to the schema's list of current items.
3408 * This is used if the schema was already constructed and
3409 * new schemata need to be added to it.
3410 * *WARNING* this interface is highly subject to change.
3411 *
3412 * Returns 0 if suceeds and -1 if an internal error occurs.
3413 */
3414static int
3415xmlSchemaAddAssembledItem(xmlSchemaParserCtxtPtr ctxt,
3416 xmlSchemaTypePtr item)
3417{
3418 static int growSize = 100;
3419 xmlSchemaAssemblePtr ass;
3420
3421 ass = ctxt->assemble;
3422 if (ass->sizeItems < 0) {
3423 /* If disabled. */
3424 return (0);
3425 }
3426 if (ass->sizeItems <= 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003427 ass->items = (void **) xmlMalloc(growSize * sizeof(xmlSchemaTypePtr));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003428 if (ass->items == NULL) {
3429 xmlSchemaPErrMemory(ctxt,
3430 "allocating new item buffer", NULL);
3431 return (-1);
3432 }
3433 ass->sizeItems = growSize;
3434 } else if (ass->sizeItems <= ass->nbItems) {
3435 ass->sizeItems *= 2;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003436 ass->items = (void **) xmlRealloc(ass->items,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003437 ass->sizeItems * sizeof(xmlSchemaTypePtr));
3438 if (ass->items == NULL) {
3439 xmlSchemaPErrMemory(ctxt,
3440 "growing item buffer", NULL);
3441 ass->sizeItems = 0;
3442 return (-1);
3443 }
3444 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003445 /* ass->items[ass->nbItems++] = (void *) item; */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003446 ((xmlSchemaTypePtr *) ass->items)[ass->nbItems++] = (void *) item;
3447 return (0);
3448}
3449
3450/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003451 * xmlSchemaAddNotation:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003452 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003453 * @schema: the schema being built
3454 * @name: the item name
3455 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00003456 * Add an XML schema annotation declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00003457 * *WARNING* this interface is highly subject to change
3458 *
3459 * Returns the new struture or NULL in case of error
3460 */
3461static xmlSchemaNotationPtr
3462xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003463 const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00003464{
3465 xmlSchemaNotationPtr ret = NULL;
3466 int val;
3467
3468 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3469 return (NULL);
3470
3471 if (schema->notaDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003472 schema->notaDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003473 if (schema->notaDecl == NULL)
3474 return (NULL);
3475
3476 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
3477 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003478 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003479 return (NULL);
3480 }
3481 memset(ret, 0, sizeof(xmlSchemaNotation));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003482 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003483 val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
3484 ret);
3485 if (val != 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00003486 /*
3487 * TODO: This should never happen, since a unique name will be computed.
3488 * If it fails, then an other internal error must have occured.
3489 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003490 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
3491 XML_SCHEMAP_REDEFINED_NOTATION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003492 "Annotation declaration '%s' is already declared.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003493 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003494 xmlFree(ret);
3495 return (NULL);
3496 }
3497 return (ret);
3498}
3499
3500
3501/**
3502 * xmlSchemaAddAttribute:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003503 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003504 * @schema: the schema being built
3505 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003506 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00003507 *
3508 * Add an XML schema Attrribute declaration
3509 * *WARNING* this interface is highly subject to change
3510 *
3511 * Returns the new struture or NULL in case of error
3512 */
3513static xmlSchemaAttributePtr
3514xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003515 const xmlChar * name, const xmlChar * namespace,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003516 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00003517{
3518 xmlSchemaAttributePtr ret = NULL;
3519 int val;
3520
3521 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3522 return (NULL);
3523
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003524#ifdef DEBUG
3525 fprintf(stderr, "Adding attribute %s\n", name);
3526 if (namespace != NULL)
3527 fprintf(stderr, " target namespace %s\n", namespace);
3528#endif
3529
Daniel Veillard4255d502002-04-16 15:50:10 +00003530 if (schema->attrDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003531 schema->attrDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003532 if (schema->attrDecl == NULL)
3533 return (NULL);
3534
3535 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
3536 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003537 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003538 return (NULL);
3539 }
3540 memset(ret, 0, sizeof(xmlSchemaAttribute));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003541 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00003542 ret->targetNamespace = namespace;
Daniel Veillard4255d502002-04-16 15:50:10 +00003543 val = xmlHashAddEntry3(schema->attrDecl, name,
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00003544 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003545 if (val != 0) {
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003546 if (topLevel) {
3547 xmlSchemaPCustomErr(ctxt,
3548 XML_SCHEMAP_REDEFINED_ATTR,
3549 NULL, NULL, node,
3550 "A global attribute declaration with the name '%s' does "
3551 "already exist", name);
3552 xmlFree(ret);
3553 return (NULL);
3554 } else {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003555 char buf[30];
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003556 /*
3557 * Using the ctxt->container for xmlHashAddEntry3 is ambigious
3558 * in the scenario:
3559 * 1. multiple top-level complex types have different target
3560 * namespaces but have the SAME NAME; this can happen if
3561 * schemata are imported
3562 * 2. those complex types contain attributes with an equal name
3563 * 3. those attributes are in no namespace
3564 * We will compute a new context string.
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003565 */
3566 snprintf(buf, 29, "#aCont%d", ctxt->counter++ + 1);
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003567 val = xmlHashAddEntry3(schema->attrDecl, name,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003568 namespace, BAD_CAST buf, ret);
3569
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003570 if (val != 0) {
3571 xmlSchemaPCustomErr(ctxt,
3572 XML_SCHEMAP_INTERNAL,
3573 NULL, NULL, node,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003574 "Internal error: xmlSchemaAddAttribute, "
3575 "a dublicate attribute declaration with the name '%s' "
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003576 "could not be added to the hash.", name);
3577 xmlFree(ret);
3578 return (NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003579 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003580 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003581 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003582 if (ctxt->assemble != NULL)
3583 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003584 return (ret);
3585}
3586
3587/**
3588 * xmlSchemaAddAttributeGroup:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003589 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003590 * @schema: the schema being built
3591 * @name: the item name
3592 *
3593 * Add an XML schema Attrribute Group declaration
3594 *
3595 * Returns the new struture or NULL in case of error
3596 */
3597static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003598xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00003599 xmlSchemaPtr schema, const xmlChar * name,
3600 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003601{
3602 xmlSchemaAttributeGroupPtr ret = NULL;
3603 int val;
3604
3605 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3606 return (NULL);
3607
3608 if (schema->attrgrpDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003609 schema->attrgrpDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003610 if (schema->attrgrpDecl == NULL)
3611 return (NULL);
3612
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003613 ret =
3614 (xmlSchemaAttributeGroupPtr)
3615 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00003616 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003617 xmlSchemaPErrMemory(ctxt, "allocating attribute group", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003618 return (NULL);
3619 }
3620 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003621 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003622 val = xmlHashAddEntry3(schema->attrgrpDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003623 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003624 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003625 xmlSchemaPCustomErr(ctxt,
3626 XML_SCHEMAP_REDEFINED_ATTRGROUP,
3627 NULL, NULL, node,
3628 "A global attribute group definition with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003629 xmlFree(ret);
3630 return (NULL);
3631 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003632 if (ctxt->assemble != NULL)
3633 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003634 return (ret);
3635}
3636
3637/**
3638 * xmlSchemaAddElement:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003639 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003640 * @schema: the schema being built
3641 * @name: the type name
3642 * @namespace: the type namespace
3643 *
3644 * Add an XML schema Element declaration
3645 * *WARNING* this interface is highly subject to change
3646 *
3647 * Returns the new struture or NULL in case of error
3648 */
3649static xmlSchemaElementPtr
3650xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003651 const xmlChar * name, const xmlChar * namespace,
3652 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00003653{
3654 xmlSchemaElementPtr ret = NULL;
3655 int val;
3656
3657 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3658 return (NULL);
3659
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003660#ifdef DEBUG
3661 fprintf(stderr, "Adding element %s\n", name);
3662 if (namespace != NULL)
3663 fprintf(stderr, " target namespace %s\n", namespace);
3664#endif
3665
Daniel Veillard4255d502002-04-16 15:50:10 +00003666 if (schema->elemDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003667 schema->elemDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003668 if (schema->elemDecl == NULL)
3669 return (NULL);
3670
3671 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
3672 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003673 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003674 return (NULL);
3675 }
3676 memset(ret, 0, sizeof(xmlSchemaElement));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003677 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003678 val = xmlHashAddEntry3(schema->elemDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003679 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003680 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003681 if (topLevel) {
3682 xmlSchemaPCustomErr(ctxt,
3683 XML_SCHEMAP_REDEFINED_ELEMENT,
3684 NULL, NULL, node,
3685 "A global element declaration with the name '%s' does "
3686 "already exist", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003687 xmlFree(ret);
3688 return (NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00003689 } else {
3690 char buf[30];
3691
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003692 snprintf(buf, 29, "#eCont%d", ctxt->counter++ + 1);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003693 val = xmlHashAddEntry3(schema->elemDecl, name,
3694 namespace, (xmlChar *) buf, ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00003695 if (val != 0) {
3696 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003697 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00003698 NULL, NULL, node,
3699 "Internal error: xmlSchemaAddElement, "
3700 "a dublicate element declaration with the name '%s' "
3701 "could not be added to the hash.", name);
3702 xmlFree(ret);
3703 return (NULL);
3704 }
3705 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00003706
Daniel Veillard4255d502002-04-16 15:50:10 +00003707 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003708 if (ctxt->assemble != NULL)
3709 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003710 return (ret);
3711}
3712
3713/**
3714 * xmlSchemaAddType:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003715 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003716 * @schema: the schema being built
3717 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003718 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00003719 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00003720 * Add an XML schema item
Daniel Veillard4255d502002-04-16 15:50:10 +00003721 * *WARNING* this interface is highly subject to change
3722 *
3723 * Returns the new struture or NULL in case of error
3724 */
3725static xmlSchemaTypePtr
3726xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003727 const xmlChar * name, const xmlChar * namespace,
3728 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003729{
3730 xmlSchemaTypePtr ret = NULL;
3731 int val;
3732
3733 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3734 return (NULL);
3735
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003736#ifdef DEBUG
3737 fprintf(stderr, "Adding type %s\n", name);
3738 if (namespace != NULL)
3739 fprintf(stderr, " target namespace %s\n", namespace);
3740#endif
3741
Daniel Veillard4255d502002-04-16 15:50:10 +00003742 if (schema->typeDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003743 schema->typeDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003744 if (schema->typeDecl == NULL)
3745 return (NULL);
3746
3747 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
3748 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003749 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003750 return (NULL);
3751 }
3752 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003753 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003754 ret->redef = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003755 val = xmlHashAddEntry2(schema->typeDecl, name, namespace, ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00003756 if (val != 0) {
3757 if (ctxt->includes == 0) {
3758 xmlSchemaPCustomErr(ctxt,
3759 XML_SCHEMAP_REDEFINED_TYPE,
3760 NULL, NULL, node,
3761 "A global type definition with the name '%s' does already exist", name);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003762 xmlFree(ret);
3763 return (NULL);
3764 } else {
3765 xmlSchemaTypePtr prev;
3766
3767 prev = xmlHashLookup2(schema->typeDecl, name, namespace);
3768 if (prev == NULL) {
3769 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003770 XML_ERR_INTERNAL_ERROR,
3771 "Internal error: xmlSchemaAddType, on type "
3772 "'%s'.\n",
3773 name, NULL);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003774 xmlFree(ret);
3775 return (NULL);
3776 }
3777 ret->redef = prev->redef;
3778 prev->redef = ret;
3779 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003780 }
3781 ret->minOccurs = 1;
3782 ret->maxOccurs = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +00003783 ret->attributeUses = NULL;
3784 ret->attributeWildcard = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003785 if (ctxt->assemble != NULL)
3786 xmlSchemaAddAssembledItem(ctxt,ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003787 return (ret);
3788}
3789
3790/**
3791 * xmlSchemaAddGroup:
3792 * @ctxt: a schema validation context
3793 * @schema: the schema being built
3794 * @name: the group name
3795 *
3796 * Add an XML schema Group definition
3797 *
3798 * Returns the new struture or NULL in case of error
3799 */
3800static xmlSchemaTypePtr
3801xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00003802 const xmlChar *name, const xmlChar *namespaceName,
3803 xmlNodePtr node)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003804{
3805 xmlSchemaTypePtr ret = NULL;
3806 int val;
3807
3808 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3809 return (NULL);
3810
3811 if (schema->groupDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003812 schema->groupDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003813 if (schema->groupDecl == NULL)
3814 return (NULL);
3815
3816 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
3817 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003818 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003819 return (NULL);
3820 }
3821 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003822 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003823 val =
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00003824 xmlHashAddEntry2(schema->groupDecl, name, namespaceName,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003825 ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003826 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003827 xmlSchemaPCustomErr(ctxt,
3828 XML_SCHEMAP_REDEFINED_GROUP,
3829 NULL, NULL, node,
3830 "A global model group definition with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003831 xmlFree(ret);
3832 return (NULL);
3833 }
3834 ret->minOccurs = 1;
3835 ret->maxOccurs = 1;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003836 if (ctxt->assemble != NULL)
3837 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003838 return (ret);
3839}
3840
Daniel Veillard3646d642004-06-02 19:19:14 +00003841/**
3842 * xmlSchemaNewWildcardNs:
3843 * @ctxt: a schema validation context
3844 *
3845 * Creates a new wildcard namespace constraint.
3846 *
3847 * Returns the new struture or NULL in case of error
3848 */
3849static xmlSchemaWildcardNsPtr
3850xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
3851{
3852 xmlSchemaWildcardNsPtr ret;
3853
3854 ret = (xmlSchemaWildcardNsPtr)
3855 xmlMalloc(sizeof(xmlSchemaWildcardNs));
3856 if (ret == NULL) {
3857 xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
3858 return (NULL);
3859 }
3860 ret->value = NULL;
3861 ret->next = NULL;
3862 return (ret);
3863}
3864
3865/**
3866 * xmlSchemaAddWildcard:
3867 * @ctxt: a schema validation context
Daniel Veillardc0826a72004-08-10 14:17:33 +00003868 * Adds a wildcard. It corresponds to a
3869 * xsd:anyAttribute and is used as storage for namespace
3870 * constraints on a xsd:any.
Daniel Veillard3646d642004-06-02 19:19:14 +00003871 *
3872 * Returns the new struture or NULL in case of error
3873 */
3874static xmlSchemaWildcardPtr
3875xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt)
3876{
3877 xmlSchemaWildcardPtr ret = NULL;
3878
3879 if (ctxt == NULL)
3880 return (NULL);
3881
3882 ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
3883 if (ret == NULL) {
3884 xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
3885 return (NULL);
3886 }
3887 memset(ret, 0, sizeof(xmlSchemaWildcard));
3888 ret->minOccurs = 1;
3889 ret->maxOccurs = 1;
3890
3891 return (ret);
3892}
3893
Daniel Veillard4255d502002-04-16 15:50:10 +00003894/************************************************************************
3895 * *
3896 * Utilities for parsing *
3897 * *
3898 ************************************************************************/
3899
3900/**
3901 * xmlGetQNameProp:
3902 * @ctxt: a schema validation context
3903 * @node: a subtree containing XML Schema informations
3904 * @name: the attribute name
3905 * @namespace: the result namespace if any
3906 *
3907 * Extract a QName Attribute value
3908 *
3909 * Returns the NCName or NULL if not found, and also update @namespace
3910 * with the namespace URI
3911 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003912static const xmlChar *
Daniel Veillard4255d502002-04-16 15:50:10 +00003913xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003914 const char *name, const xmlChar ** namespace)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003915{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003916 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00003917 xmlNsPtr ns;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003918 const xmlChar *ret, *prefix;
3919 int len;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00003920 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00003921
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003922 *namespace = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00003923 attr = xmlSchemaGetPropNode(node, name);
3924 if (attr == NULL)
3925 return (NULL);
3926 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003927
Daniel Veillard4255d502002-04-16 15:50:10 +00003928 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003929 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003930
Daniel Veillardba0153a2004-04-01 10:42:31 +00003931 if (!strchr((char *) val, ':')) {
Daniel Veillardebcdebd2004-03-05 00:15:50 +00003932 ns = xmlSearchNs(node->doc, node, 0);
3933 if (ns) {
3934 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
3935 return (val);
3936 }
3937 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003938 ret = xmlSplitQName3(val, &len);
3939 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003940 return (val);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003941 }
3942 ret = xmlDictLookup(ctxt->dict, ret, -1);
3943 prefix = xmlDictLookup(ctxt->dict, val, len);
Daniel Veillard4255d502002-04-16 15:50:10 +00003944
3945 ns = xmlSearchNs(node->doc, node, prefix);
3946 if (ns == NULL) {
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00003947 xmlSchemaPSimpleTypeErr(ctxt, XML_SCHEMAP_PREFIX_UNDEFINED,
3948 NULL, NULL, (xmlNodePtr) attr,
3949 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, val,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003950 "The QName value '%s' has no corresponding namespace "
3951 "declaration in scope", val, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003952 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003953 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003954 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003955 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003956}
3957
3958/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00003959 * xmlSchemaPValAttrNodeQNameValue:
3960 * @ctxt: a schema parser context
3961 * @schema: the schema context
3962 * @ownerDes: the designation of the parent element
3963 * @ownerItem: the parent as a schema object
3964 * @value: the QName value
3965 * @local: the resulting local part if found, the attribute value otherwise
3966 * @uri: the resulting namespace URI if found
3967 *
3968 * Extracts the local name and the URI of a QName value and validates it.
3969 * This one is intended to be used on attribute values that
3970 * should resolve to schema components.
3971 *
3972 * Returns 0, in case the QName is valid, a positive error code
3973 * if not valid and -1 if an internal error occurs.
3974 */
3975static int
3976xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
3977 xmlSchemaPtr schema,
3978 xmlChar **ownerDes,
3979 xmlSchemaTypePtr ownerItem,
3980 xmlAttrPtr attr,
3981 const xmlChar *value,
3982 const xmlChar **uri,
3983 const xmlChar **prefix,
3984 const xmlChar **local)
3985{
3986 const xmlChar *pref;
3987 xmlNsPtr ns;
3988 int len, ret;
3989
3990 *uri = NULL;
3991 *local = NULL;
3992 if (prefix != 0)
3993 *prefix = NULL;
3994 ret = xmlValidateQName(value, 1);
3995 if (ret > 0) {
3996 xmlSchemaPSimpleTypeErr(ctxt,
3997 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3998 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00003999 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
4000 "QName", value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004001 NULL, NULL, NULL);
4002 *local = value;
4003 return (ctxt->err);
4004 } else if (ret < 0)
4005 return (-1);
4006
4007 if (!strchr((char *) value, ':')) {
4008 ns = xmlSearchNs(attr->doc, attr->parent, 0);
4009 if (ns)
4010 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
4011 else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
4012 /*
4013 * This one takes care of included schemas with no
4014 * target namespace.
4015 */
4016 *uri = schema->targetNamespace;
4017 }
4018 *local = value;
4019 return (0);
4020 }
4021 /*
4022 * At this point xmlSplitQName3 has to return a local name.
4023 */
4024 *local = xmlSplitQName3(value, &len);
4025 *local = xmlDictLookup(ctxt->dict, *local, -1);
4026 pref = xmlDictLookup(ctxt->dict, value, len);
4027 if (prefix != 0)
4028 *prefix = pref;
4029 ns = xmlSearchNs(attr->doc, attr->parent, pref);
4030 if (ns == NULL) {
4031 xmlSchemaPSimpleTypeErr(ctxt,
4032 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4033 ownerDes, ownerItem, (xmlNodePtr) attr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004034 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), "QName", value,
4035 "The QName value '%s' has no corresponding namespace "
4036 "declaration in scope", value, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004037 return (ctxt->err);
4038 } else {
4039 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
4040 }
4041 return (0);
4042}
4043
4044/**
4045 * xmlSchemaPValAttrNodeQName:
4046 * @ctxt: a schema parser context
4047 * @schema: the schema context
4048 * @ownerDes: the designation of the owner element
4049 * @ownerItem: the owner as a schema object
4050 * @attr: the attribute node
4051 * @local: the resulting local part if found, the attribute value otherwise
4052 * @uri: the resulting namespace URI if found
4053 *
4054 * Extracts and validates the QName of an attribute value.
4055 * This one is intended to be used on attribute values that
4056 * should resolve to schema components.
4057 *
4058 * Returns 0, in case the QName is valid, a positive error code
4059 * if not valid and -1 if an internal error occurs.
4060 */
4061static int
4062xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
4063 xmlSchemaPtr schema,
4064 xmlChar **ownerDes,
4065 xmlSchemaTypePtr ownerItem,
4066 xmlAttrPtr attr,
4067 const xmlChar **uri,
4068 const xmlChar **prefix,
4069 const xmlChar **local)
4070{
4071 const xmlChar *value;
4072
4073 value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4074 return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
4075 ownerDes, ownerItem, attr, value, uri, prefix, local));
4076}
4077
4078/**
4079 * xmlSchemaPValAttrQName:
4080 * @ctxt: a schema parser context
4081 * @schema: the schema context
4082 * @ownerDes: the designation of the parent element
4083 * @ownerItem: the owner as a schema object
4084 * @ownerElem: the parent node of the attribute
4085 * @name: the name of the attribute
4086 * @local: the resulting local part if found, the attribute value otherwise
4087 * @uri: the resulting namespace URI if found
4088 *
4089 * Extracts and validates the QName of an attribute value.
4090 *
4091 * Returns 0, in case the QName is valid, a positive error code
4092 * if not valid and -1 if an internal error occurs.
4093 */
4094static int
4095xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
4096 xmlSchemaPtr schema,
4097 xmlChar **ownerDes,
4098 xmlSchemaTypePtr ownerItem,
4099 xmlNodePtr ownerElem,
4100 const char *name,
4101 const xmlChar **uri,
4102 const xmlChar **prefix,
4103 const xmlChar **local)
4104{
4105 xmlAttrPtr attr;
4106
4107 attr = xmlSchemaGetPropNode(ownerElem, name);
4108 if (attr == NULL) {
4109 *local = NULL;
4110 *uri = NULL;
4111 return (0);
4112 }
4113 return (xmlSchemaPValAttrNodeQName(ctxt, schema,
4114 ownerDes, ownerItem, attr, uri, prefix, local));
4115}
4116
4117/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004118 * xmlGetMaxOccurs:
4119 * @ctxt: a schema validation context
4120 * @node: a subtree containing XML Schema informations
4121 *
4122 * Get the maxOccurs property
4123 *
4124 * Returns the default if not found, or the value
4125 */
4126static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004127xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
4128 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004129{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004130 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00004131 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004132 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00004133
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004134 attr = xmlSchemaGetPropNode(node, "maxOccurs");
4135 if (attr == NULL)
4136 return (def);
4137 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00004138
4139 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004140 if (max != UNBOUNDED) {
4141 xmlSchemaPSimpleTypeErr(ctxt,
4142 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4143 /* XML_SCHEMAP_INVALID_MINOCCURS, */
4144 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
4145 val, NULL, NULL, NULL);
4146 return (def);
4147 } else
4148 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00004149 }
4150
4151 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00004152 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004153 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004154 if (*cur == 0) {
4155 xmlSchemaPSimpleTypeErr(ctxt,
4156 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4157 /* XML_SCHEMAP_INVALID_MINOCCURS, */
4158 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
4159 val, NULL, NULL, NULL);
4160 return (def);
4161 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004162 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004163 ret = ret * 10 + (*cur - '0');
4164 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00004165 }
William M. Brack76e95df2003-10-18 16:20:14 +00004166 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004167 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004168 /*
4169 * TODO: Restrict the maximal value to Integer.
4170 */
4171 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
4172 xmlSchemaPSimpleTypeErr(ctxt,
4173 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4174 /* XML_SCHEMAP_INVALID_MINOCCURS, */
4175 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
4176 val, NULL, NULL, NULL);
4177 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00004178 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004179 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004180}
4181
4182/**
4183 * xmlGetMinOccurs:
4184 * @ctxt: a schema validation context
4185 * @node: a subtree containing XML Schema informations
4186 *
4187 * Get the minOccurs property
4188 *
4189 * Returns the default if not found, or the value
4190 */
4191static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004192xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
4193 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004194{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004195 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00004196 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004197 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00004198
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004199 attr = xmlSchemaGetPropNode(node, "minOccurs");
4200 if (attr == NULL)
4201 return (def);
4202 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00004203 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00004204 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004205 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004206 if (*cur == 0) {
4207 xmlSchemaPSimpleTypeErr(ctxt,
4208 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4209 /* XML_SCHEMAP_INVALID_MINOCCURS, */
4210 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
4211 val, NULL, NULL, NULL);
4212 return (def);
4213 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004214 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004215 ret = ret * 10 + (*cur - '0');
4216 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00004217 }
William M. Brack76e95df2003-10-18 16:20:14 +00004218 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004219 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004220 /*
4221 * TODO: Restrict the maximal value to Integer.
4222 */
4223 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
4224 xmlSchemaPSimpleTypeErr(ctxt,
4225 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4226 /* XML_SCHEMAP_INVALID_MINOCCURS, */
4227 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
4228 val, NULL, NULL, NULL);
4229 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00004230 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004231 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004232}
4233
4234/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004235 * xmlSchemaPGetBoolNodeValue:
4236 * @ctxt: a schema validation context
4237 * @ownerDes: owner designation
4238 * @ownerItem: the owner as a schema item
4239 * @node: the node holding the value
4240 *
4241 * Converts a boolean string value into 1 or 0.
4242 *
4243 * Returns 0 or 1.
4244 */
4245static int
4246xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
4247 xmlChar **ownerDes,
4248 xmlSchemaTypePtr ownerItem,
4249 xmlNodePtr node)
4250{
4251 xmlChar *value = NULL;
4252 int res = 0;
4253
4254 value = xmlNodeGetContent(node);
4255 /*
4256 * 3.2.2.1 Lexical representation
4257 * An instance of a datatype that is defined as ·boolean·
4258 * can have the following legal literals {true, false, 1, 0}.
4259 */
4260 if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
4261 res = 1;
4262 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
4263 res = 0;
4264 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
4265 res = 1;
4266 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
4267 res = 0;
4268 else {
4269 xmlSchemaPSimpleTypeErr(ctxt,
4270 XML_SCHEMAP_INVALID_BOOLEAN,
4271 ownerDes, ownerItem, node,
4272 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
4273 "(1 | 0 | true | false)", BAD_CAST value,
4274 NULL, NULL, NULL);
4275 }
4276 if (value != NULL)
4277 xmlFree(value);
4278 return (res);
4279}
4280
4281/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004282 * xmlGetBooleanProp:
4283 * @ctxt: a schema validation context
4284 * @node: a subtree containing XML Schema informations
4285 * @name: the attribute name
4286 * @def: the default value
4287 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00004288 * Evaluate if a boolean property is set
Daniel Veillard4255d502002-04-16 15:50:10 +00004289 *
4290 * Returns the default if not found, 0 if found to be false,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004291 * 1 if found to be true
Daniel Veillard4255d502002-04-16 15:50:10 +00004292 */
4293static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00004294xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
4295 xmlChar **ownerDes,
4296 xmlSchemaTypePtr ownerItem,
4297 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004298 const char *name, int def)
4299{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004300 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00004301
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004302 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004303 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004304 return (def);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004305 /*
4306 * 3.2.2.1 Lexical representation
4307 * An instance of a datatype that is defined as ·boolean·
4308 * can have the following legal literals {true, false, 1, 0}.
4309 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004310 if (xmlStrEqual(val, BAD_CAST "true"))
4311 def = 1;
4312 else if (xmlStrEqual(val, BAD_CAST "false"))
4313 def = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004314 else if (xmlStrEqual(val, BAD_CAST "1"))
4315 def = 1;
4316 else if (xmlStrEqual(val, BAD_CAST "0"))
4317 def = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00004318 else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004319 xmlSchemaPSimpleTypeErr(ctxt,
4320 XML_SCHEMAP_INVALID_BOOLEAN,
William M. Brack2f2a6632004-08-20 23:09:47 +00004321 ownerDes, ownerItem, node,
4322 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
4323 "(1 | 0 | true | false)", val, NULL, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004324 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004325 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00004326}
4327
4328/************************************************************************
4329 * *
4330 * Shema extraction from an Infoset *
4331 * *
4332 ************************************************************************/
4333static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
4334 ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00004335 xmlNodePtr node,
4336 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004337static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
4338 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00004339 xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00004340 xmlNodePtr node,
4341 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004342static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
4343 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00004344 xmlSchemaPtr schema,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00004345 xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00004346static xmlSchemaTypePtr xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt,
4347 xmlSchemaPtr schema,
4348 xmlNodePtr node);
4349static xmlSchemaTypePtr xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt,
4350 xmlSchemaPtr schema,
4351 xmlNodePtr node);
4352static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
4353 ctxt,
4354 xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00004355 xmlNodePtr node,
4356 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00004357static xmlSchemaAttributeGroupPtr
4358xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00004359 xmlSchemaPtr schema, xmlNodePtr node,
4360 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00004361static xmlSchemaTypePtr xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt,
4362 xmlSchemaPtr schema,
4363 xmlNodePtr node);
4364static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
4365 xmlSchemaPtr schema,
4366 xmlNodePtr node);
Daniel Veillard3646d642004-06-02 19:19:14 +00004367static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004368xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
4369 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00004370
4371/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004372 * xmlSchemaPValAttrNodeValue:
Daniel Veillard01fa6152004-06-29 17:04:39 +00004373 *
4374 * @ctxt: a schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00004375 * @ownerDes: the designation of the parent element
4376 * @ownerItem: the schema object owner if existent
4377 * @attr: the schema attribute node being validated
4378 * @value: the value
4379 * @type: the built-in type to be validated against
Daniel Veillard01fa6152004-06-29 17:04:39 +00004380 *
4381 * Validates a value against the given built-in type.
4382 * This one is intended to be used internally for validation
4383 * of schema attribute values during parsing of the schema.
4384 *
4385 * Returns 0 if the value is valid, a positive error code
4386 * number otherwise and -1 in case of an internal or API error.
4387 */
4388static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00004389xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr ctxt,
4390 xmlChar **ownerDes,
4391 xmlSchemaTypePtr ownerItem,
4392 xmlAttrPtr attr,
4393 const xmlChar *value,
4394 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +00004395{
Daniel Veillard01fa6152004-06-29 17:04:39 +00004396
Daniel Veillardc0826a72004-08-10 14:17:33 +00004397 int ret = 0;
4398
4399 /*
4400 * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
4401 * one is really meant to be used internally, so better not.
4402 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00004403 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00004404 return (-1);
4405 if (type->type != XML_SCHEMA_TYPE_BASIC) {
4406 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004407 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004408 "Internal error: xmlSchemaPValAttrNodeValue, the given "
Daniel Veillardc0826a72004-08-10 14:17:33 +00004409 "type '%s' is not a built-in type.\n",
4410 type->name, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00004411 return (-1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004412 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00004413 switch (type->builtInType) {
4414 case XML_SCHEMAS_NCNAME:
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004415 case XML_SCHEMAS_QNAME:
4416 case XML_SCHEMAS_ANYURI:
4417 case XML_SCHEMAS_TOKEN:
4418 case XML_SCHEMAS_LANGUAGE:
4419 ret = xmlSchemaValPredefTypeNode(type, value, NULL, (xmlNodePtr) attr);
4420 break;
4421
4422 /*
4423 case XML_SCHEMAS_NCNAME:
Daniel Veillard01fa6152004-06-29 17:04:39 +00004424 ret = xmlValidateNCName(value, 1);
4425 break;
4426 case XML_SCHEMAS_QNAME:
Daniel Veillardc0826a72004-08-10 14:17:33 +00004427 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004428 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004429 "Internal error: xmlSchemaPvalueAttrNode, use "
4430 "the function xmlSchemaExtractSchemaQNamePropvalueidated "
4431 "for extracting QName valueues instead.\n",
4432 NULL, NULL);
4433 return (-1);
4434 case XML_SCHEMAS_ANYURI:
4435 if (value != NULL) {
4436 xmlURIPtr uri = xmlParseURI((const char *) value);
4437 if (uri == NULL)
4438 ret = 1;
4439 else
4440 xmlFreeURI(uri);
Daniel Veillard01fa6152004-06-29 17:04:39 +00004441 }
4442 break;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004443 case XML_SCHEMAS_TOKEN: {
4444 const xmlChar *cur = value;
4445
4446 if (IS_BLANK_CH(*cur)) {
4447 ret = 1;
4448 } else while (*cur != 0) {
4449 if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) {
4450 ret = 1;
4451 break;
4452 } else if (*cur == ' ') {
4453 cur++;
4454 if ((*cur == 0) || (*cur == ' ')) {
4455 ret = 1;
4456 break;
4457 }
4458 } else {
4459 cur++;
4460 }
4461 }
4462 }
4463 break;
4464 case XML_SCHEMAS_LANGUAGE:
4465 if (xmlCheckLanguageID(value) != 1)
4466 ret = 1;
4467 break;
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004468 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00004469 default: {
4470 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004471 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004472 "Internal error: xmlSchemaPValAttrNodeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +00004473 "valueidation using the type '%s' is not implemented "
4474 "yet.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +00004475 type->name, NULL);
4476 return (-1);
4477 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004478 }
4479 /*
4480 * TODO: Should we use the S4S error codes instead?
4481 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004482 if (ret < 0) {
4483 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
4484 XML_SCHEMAP_INTERNAL,
4485 "Internal error: xmlSchemaPValAttrNodeValue, "
4486 "failed to validate a schema attribute value.\n",
4487 NULL, NULL);
4488 return (-1);
4489 } else if (ret > 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004490 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
4491 xmlSchemaPSimpleTypeErr(ctxt,
4492 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2,
4493 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004494 type, NULL, value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004495 NULL, NULL, NULL);
4496 return(XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2);
4497 } else {
4498 xmlSchemaPSimpleTypeErr(ctxt,
4499 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
4500 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004501 type, NULL, value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004502 NULL, NULL, NULL);
4503 return(XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
4504 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00004505 }
4506 return (ret);
4507}
4508
4509/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00004510 * xmlSchemaPValAttrNode:
4511 *
4512 * @ctxt: a schema parser context
4513 * @ownerDes: the designation of the parent element
4514 * @ownerItem: the schema object owner if existent
4515 * @attr: the schema attribute node being validated
4516 * @type: the built-in type to be validated against
4517 * @value: the resulting value if any
4518 *
4519 * Extracts and validates a value against the given built-in type.
4520 * This one is intended to be used internally for validation
4521 * of schema attribute values during parsing of the schema.
4522 *
4523 * Returns 0 if the value is valid, a positive error code
4524 * number otherwise and -1 in case of an internal or API error.
4525 */
4526static int
4527xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
4528 xmlChar **ownerDes,
4529 xmlSchemaTypePtr ownerItem,
4530 xmlAttrPtr attr,
4531 xmlSchemaTypePtr type,
4532 const xmlChar **value)
4533{
4534 const xmlChar *val;
4535
4536 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
4537 return (-1);
4538
4539 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4540 if (value != NULL)
4541 *value = val;
4542
4543 return (xmlSchemaPValAttrNodeValue(ctxt, ownerDes, ownerItem, attr,
4544 val, type));
4545}
4546
4547/**
4548 * xmlSchemaPValAttr:
4549 *
4550 * @ctxt: a schema parser context
4551 * @node: the element node of the attribute
4552 * @ownerDes: the designation of the parent element
4553 * @ownerItem: the schema object owner if existent
4554 * @ownerElem: the owner element node
4555 * @name: the name of the schema attribute node
4556 * @type: the built-in type to be validated against
4557 * @value: the resulting value if any
4558 *
4559 * Extracts and validates a value against the given built-in type.
4560 * This one is intended to be used internally for validation
4561 * of schema attribute values during parsing of the schema.
4562 *
4563 * Returns 0 if the value is valid, a positive error code
4564 * number otherwise and -1 in case of an internal or API error.
4565 */
4566static int
4567xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
4568 xmlChar **ownerDes,
4569 xmlSchemaTypePtr ownerItem,
4570 xmlNodePtr ownerElem,
4571 const char *name,
4572 xmlSchemaTypePtr type,
4573 const xmlChar **value)
4574{
4575 xmlAttrPtr attr;
4576
4577 if ((ctxt == NULL) || (type == NULL)) {
4578 if (value != NULL)
4579 *value = NULL;
4580 return (-1);
4581 }
4582 if (type->type != XML_SCHEMA_TYPE_BASIC) {
4583 if (value != NULL)
4584 *value = NULL;
4585 xmlSchemaPErr(ctxt, ownerElem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004586 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004587 "Internal error: xmlSchemaPValAttr, the given "
4588 "type '%s' is not a built-in type.\n",
4589 type->name, NULL);
4590 return (-1);
4591 }
4592 attr = xmlSchemaGetPropNode(ownerElem, name);
4593 if (attr == NULL) {
4594 if (value != NULL)
4595 *value = NULL;
4596 return (0);
4597 }
4598 return (xmlSchemaPValAttrNode(ctxt, ownerDes, ownerItem, attr,
4599 type, value));
4600}
4601/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004602 * xmlSchemaParseAttrDecls:
4603 * @ctxt: a schema validation context
4604 * @schema: the schema being built
4605 * @node: a subtree containing XML Schema informations
4606 * @type: the hosting type
4607 *
4608 * parse a XML schema attrDecls declaration corresponding to
4609 * <!ENTITY % attrDecls
4610 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
4611 */
4612static xmlNodePtr
4613xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4614 xmlNodePtr child, xmlSchemaTypePtr type)
4615{
4616 xmlSchemaAttributePtr lastattr, attr;
4617
4618 lastattr = NULL;
4619 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004620 (IS_SCHEMA(child, "attributeGroup"))) {
4621 attr = NULL;
4622 if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00004623 attr = xmlSchemaParseAttribute(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004624 } else if (IS_SCHEMA(child, "attributeGroup")) {
4625 attr = (xmlSchemaAttributePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00004626 xmlSchemaParseAttributeGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004627 }
4628 if (attr != NULL) {
4629 if (lastattr == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00004630 if (type->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
4631 ((xmlSchemaAttributeGroupPtr) type)->attributes = attr;
4632 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004633 type->attributes = attr;
4634 lastattr = attr;
4635 } else {
4636 lastattr->next = attr;
4637 lastattr = attr;
4638 }
4639 }
4640 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004641 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004642 return (child);
Daniel Veillard4255d502002-04-16 15:50:10 +00004643}
4644
4645/**
4646 * xmlSchemaParseAnnotation:
4647 * @ctxt: a schema validation context
4648 * @schema: the schema being built
4649 * @node: a subtree containing XML Schema informations
4650 *
4651 * parse a XML schema Attrribute declaration
4652 * *WARNING* this interface is highly subject to change
4653 *
William M. Bracke7091952004-05-11 15:09:58 +00004654 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00004655 * 1 in case of success.
4656 */
4657static xmlSchemaAnnotPtr
4658xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4659 xmlNodePtr node)
4660{
4661 xmlSchemaAnnotPtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004662 xmlNodePtr child = NULL;
4663 xmlAttrPtr attr;
4664 int barked = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00004665
Daniel Veillardc0826a72004-08-10 14:17:33 +00004666 /*
4667 * INFO: S4S completed.
4668 */
4669 /*
4670 * id = ID
4671 * {any attributes with non-schema namespace . . .}>
4672 * Content: (appinfo | documentation)*
4673 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004674 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4675 return (NULL);
4676 ret = xmlSchemaNewAnnot(ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004677 attr = node->properties;
4678 while (attr != NULL) {
4679 if (((attr->ns == NULL) &&
4680 (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
4681 ((attr->ns != NULL) &&
4682 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
4683
4684 xmlSchemaPIllegalAttrErr(ctxt,
4685 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4686 NULL, NULL, attr);
4687 }
4688 attr = attr->next;
4689 }
4690 /* TODO: Check id. */
4691
4692 /*
4693 * And now for the children...
4694 */
4695 child = node->children;
4696 while (child != NULL) {
4697 if (IS_SCHEMA(child, "appinfo")) {
4698 /* TODO: make available the content of "appinfo". */
4699 /*
4700 * source = anyURI
4701 * {any attributes with non-schema namespace . . .}>
4702 * Content: ({any})*
4703 */
4704 attr = child->properties;
4705 while (attr != NULL) {
4706 if (((attr->ns == NULL) &&
4707 (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
4708 ((attr->ns != NULL) &&
4709 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004710
Daniel Veillardc0826a72004-08-10 14:17:33 +00004711 xmlSchemaPIllegalAttrErr(ctxt,
4712 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4713 NULL, NULL, attr);
4714 }
4715 attr = attr->next;
4716 }
4717 xmlSchemaPValAttr(ctxt, NULL, NULL, child, "source",
4718 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
4719 child = child->next;
4720 } else if (IS_SCHEMA(child, "documentation")) {
4721 /* TODO: make available the content of "documentation". */
4722 /*
4723 * source = anyURI
4724 * {any attributes with non-schema namespace . . .}>
4725 * Content: ({any})*
4726 */
4727 attr = child->properties;
4728 while (attr != NULL) {
4729 if (attr->ns == NULL) {
4730 if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
4731 xmlSchemaPIllegalAttrErr(ctxt,
4732 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4733 NULL, NULL, attr);
4734 }
4735 } else {
4736 if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
4737 (xmlStrEqual(attr->name, BAD_CAST "lang") &&
4738 (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
4739
4740 xmlSchemaPIllegalAttrErr(ctxt,
4741 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4742 NULL, NULL, attr);
4743 }
4744 }
4745 attr = attr->next;
4746 }
4747 /*
4748 * Attribute "xml:lang".
4749 */
4750 attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
4751 if (attr != NULL)
4752 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
4753 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
4754 child = child->next;
4755 } else {
4756 if (!barked)
4757 xmlSchemaPContentErr(ctxt,
4758 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
4759 NULL, NULL, node, child, NULL, "(appinfo | documentation)*");
4760 barked = 1;
4761 child = child->next;
4762 }
4763 }
4764
Daniel Veillard4255d502002-04-16 15:50:10 +00004765 return (ret);
4766}
4767
4768/**
4769 * xmlSchemaParseFacet:
4770 * @ctxt: a schema validation context
4771 * @schema: the schema being built
4772 * @node: a subtree containing XML Schema informations
4773 *
4774 * parse a XML schema Facet declaration
4775 * *WARNING* this interface is highly subject to change
4776 *
4777 * Returns the new type structure or NULL in case of error
4778 */
4779static xmlSchemaFacetPtr
4780xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004781 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004782{
4783 xmlSchemaFacetPtr facet;
4784 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004785 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00004786
4787 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4788 return (NULL);
4789
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004790 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004791 if (facet == NULL) {
4792 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
4793 return (NULL);
4794 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004795 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004796 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00004797 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004798 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
4799 "Facet %s has no value\n", node->name, NULL);
4800 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00004801 return (NULL);
4802 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004803 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004804 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004805 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004806 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004807 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004808 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004809 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004810 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004811 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004812 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004813 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004814 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004815 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004816 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004817 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004818 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004819 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004820 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004821 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004822 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004823 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004824 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
4825 } else if (IS_SCHEMA(node, "minLength")) {
4826 facet->type = XML_SCHEMA_FACET_MINLENGTH;
4827 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004828 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
4829 "Unknown facet type %s\n", node->name, NULL);
4830 xmlSchemaFreeFacet(facet);
4831 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004832 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004833 facet->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00004834 facet->value = value;
Daniel Veillard01fa6152004-06-29 17:04:39 +00004835 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
4836 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
4837 const xmlChar *fixed;
4838
4839 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
4840 if (fixed != NULL) {
4841 if (xmlStrEqual(fixed, BAD_CAST "true"))
4842 facet->fixed = 1;
4843 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004844 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004845 child = node->children;
4846
4847 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004848 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4849 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004850 }
4851 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004852 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
4853 "Facet %s has unexpected child content\n",
4854 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004855 }
4856 return (facet);
4857}
4858
4859/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00004860 * xmlSchemaParseWildcardNs:
4861 * @ctxt: a schema parser context
4862 * @wildc: the wildcard, already created
4863 * @node: a subtree containing XML Schema informations
4864 *
4865 * Parses the attribute "processContents" and "namespace"
4866 * of a xsd:anyAttribute and xsd:any.
4867 * *WARNING* this interface is highly subject to change
4868 *
4869 * Returns 0 if everything goes fine, a positive error code
4870 * if something is not valid and -1 if an internal error occurs.
4871 */
4872static int
4873xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
4874 xmlSchemaPtr schema,
4875 xmlSchemaWildcardPtr wildc,
4876 xmlNodePtr node)
4877{
4878 const xmlChar *pc, *ns, *dictnsItem;
4879 int ret = 0;
4880 xmlChar *nsItem;
4881 xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
4882 xmlAttrPtr attr;
4883
4884 pc = xmlSchemaGetProp(ctxt, node, "processContents");
4885 if ((pc == NULL)
4886 || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
4887 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
4888 } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
4889 wildc->processContents = XML_SCHEMAS_ANY_SKIP;
4890 } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
4891 wildc->processContents = XML_SCHEMAS_ANY_LAX;
4892 } else {
4893 xmlSchemaPSimpleTypeErr(ctxt,
4894 XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD,
4895 NULL, NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00004896 NULL, "(strict | skip | lax)", pc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004897 NULL, NULL, NULL);
4898 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
4899 ret = XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD;
4900 }
4901 /*
4902 * Build the namespace constraints.
4903 */
4904 attr = xmlSchemaGetPropNode(node, "namespace");
4905 ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4906 if ((ns == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
4907 wildc->any = 1;
4908 else if (xmlStrEqual(ns, BAD_CAST "##other")) {
4909 wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
4910 if (wildc->negNsSet == NULL) {
4911 return (-1);
4912 }
4913 wildc->negNsSet->value = schema->targetNamespace;
4914 } else {
4915 const xmlChar *end, *cur;
4916
4917 cur = ns;
4918 do {
4919 while (IS_BLANK_CH(*cur))
4920 cur++;
4921 end = cur;
4922 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
4923 end++;
4924 if (end == cur)
4925 break;
4926 nsItem = xmlStrndup(cur, end - cur);
4927 if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
4928 (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
4929 xmlSchemaPSimpleTypeErr(ctxt,
4930 XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
4931 NULL, NULL, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004932 NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004933 "((##any | ##other) | List of (anyURI | "
4934 "(##targetNamespace | ##local)))",
4935 nsItem, NULL, NULL, NULL);
4936 ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
4937 } else {
4938 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
4939 dictnsItem = schema->targetNamespace;
4940 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
4941 dictnsItem = NULL;
4942 } else {
4943 /*
4944 * Validate the item (anyURI).
4945 */
4946 xmlSchemaPValAttrNodeValue(ctxt, NULL, NULL, attr,
4947 nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
4948 dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
4949 }
4950 /*
4951 * Avoid dublicate namespaces.
4952 */
4953 tmp = wildc->nsSet;
4954 while (tmp != NULL) {
4955 if (dictnsItem == tmp->value)
4956 break;
4957 tmp = tmp->next;
4958 }
4959 if (tmp == NULL) {
4960 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
4961 if (tmp == NULL) {
4962 xmlFree(nsItem);
4963 return (-1);
4964 }
4965 tmp->value = dictnsItem;
4966 tmp->next = NULL;
4967 if (wildc->nsSet == NULL)
4968 wildc->nsSet = tmp;
4969 else
4970 lastNs->next = tmp;
4971 lastNs = tmp;
4972 }
4973
4974 }
4975 xmlFree(nsItem);
4976 cur = end;
4977 } while (*cur != 0);
4978 }
4979 return (ret);
4980}
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004981
4982static int
4983xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
4984 xmlSchemaTypePtr item,
4985 xmlNodePtr node,
4986 int minOccurs,
4987 int maxOccurs) {
4988
4989 if (maxOccurs != UNBOUNDED) {
4990 /*
4991 * TODO: Maby we should better not create the particle,
4992 * if min/max is invalid, since it could confuse the build of the
4993 * content model.
4994 */
4995 /*
4996 * 3.9.6 Schema Component Constraint: Particle Correct
4997 *
4998 */
4999 if (maxOccurs < 1) {
5000 /*
5001 * 2.2 {max occurs} must be greater than or equal to 1.
5002 */
5003 xmlSchemaPCustomAttrErr(ctxt,
5004 XML_SCHEMAP_P_PROPS_CORRECT_2_2,
5005 NULL, item, xmlSchemaGetPropNode(node, "maxOccurs"),
5006 "The value must be greater than or equal to 1");
5007 return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
5008 } else if (minOccurs > maxOccurs) {
5009 /*
5010 * 2.1 {min occurs} must not be greater than {max occurs}.
5011 */
5012 xmlSchemaPCustomAttrErr(ctxt,
5013 XML_SCHEMAP_P_PROPS_CORRECT_2_1,
5014 NULL, item, xmlSchemaGetPropNode(node, "minOccurs"),
5015 "The value must not be greater than the value of 'maxOccurs'");
5016 return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
5017 }
5018 }
5019 return (0);
5020}
5021
Daniel Veillardc0826a72004-08-10 14:17:33 +00005022/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005023 * xmlSchemaParseAny:
5024 * @ctxt: a schema validation context
5025 * @schema: the schema being built
5026 * @node: a subtree containing XML Schema informations
5027 *
5028 * parse a XML schema Any declaration
5029 * *WARNING* this interface is highly subject to change
5030 *
5031 * Returns the new type structure or NULL in case of error
5032 */
5033static xmlSchemaTypePtr
5034xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5035 xmlNodePtr node)
5036{
5037 xmlSchemaTypePtr type;
5038 xmlNodePtr child = NULL;
5039 xmlChar name[30];
Daniel Veillardc0826a72004-08-10 14:17:33 +00005040 xmlSchemaWildcardPtr wildc;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005041 int minOccurs, maxOccurs;
Daniel Veillard4255d502002-04-16 15:50:10 +00005042
5043 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5044 return (NULL);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005045 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
5046 "(nonNegativeInteger | unbounded)");
5047 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
5048 "nonNegativeInteger");
5049 if ((minOccurs == 0) && (maxOccurs == 0))
5050 return (NULL);
5051
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005052 snprintf((char *) name, 30, "#any%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00005053 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005054 if (type == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005055 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005056 type->node = node;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005057 type->type = XML_SCHEMA_TYPE_ANY;
5058
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005059 /*
5060 * TODO: Use a particle component here.
5061 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00005062 wildc = xmlSchemaAddWildcard(ctxt);
5063 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005064 * Check min/max sanity.
5065 */
5066 type->maxOccurs = maxOccurs;
5067 type->minOccurs = minOccurs;
5068 xmlSchemaPCheckParticleCorrect_2(ctxt, type,
5069 node, type->minOccurs, type->maxOccurs);
5070 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005071 * This is not nice, since it is won't be used as a attribute wildcard,
5072 * but better than adding a field to the structure.
5073 */
5074 type->attributeWildcard = wildc;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005075 xmlSchemaParseWildcardNs(ctxt, schema, wildc, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005076 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00005077 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005078 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5079 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005080 }
5081 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005082 xmlSchemaPErr2(ctxt, node, child,
5083 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
5084 "Sequence %s has unexpected content\n", type->name,
5085 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005086 }
5087
5088 return (type);
5089}
5090
5091/**
5092 * xmlSchemaParseNotation:
5093 * @ctxt: a schema validation context
5094 * @schema: the schema being built
5095 * @node: a subtree containing XML Schema informations
5096 *
5097 * parse a XML schema Notation declaration
5098 *
5099 * Returns the new structure or NULL in case of error
5100 */
5101static xmlSchemaNotationPtr
5102xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005103 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005104{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005105 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00005106 xmlSchemaNotationPtr ret;
5107 xmlNodePtr child = NULL;
5108
5109 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5110 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005111 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00005112 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005113 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
5114 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005115 return (NULL);
5116 }
5117 ret = xmlSchemaAddNotation(ctxt, schema, name);
5118 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005119 return (NULL);
5120 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005121 ret->targetNamespace = schema->targetNamespace;
Daniel Veillard4255d502002-04-16 15:50:10 +00005122 child = node->children;
5123 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005124 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5125 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005126 }
5127 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005128 xmlSchemaPErr2(ctxt, node, child,
5129 XML_SCHEMAP_UNKNOWN_NOTATION_CHILD,
5130 "notation %s has unexpected content\n", name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005131 }
5132
5133 return (ret);
5134}
5135
5136/**
5137 * xmlSchemaParseAnyAttribute:
5138 * @ctxt: a schema validation context
5139 * @schema: the schema being built
5140 * @node: a subtree containing XML Schema informations
5141 *
5142 * parse a XML schema AnyAttrribute declaration
5143 * *WARNING* this interface is highly subject to change
5144 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005145 * Returns a wildcard or NULL.
Daniel Veillard4255d502002-04-16 15:50:10 +00005146 */
Daniel Veillard3646d642004-06-02 19:19:14 +00005147static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005148xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
5149 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005150{
Daniel Veillard3646d642004-06-02 19:19:14 +00005151 xmlSchemaWildcardPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00005152 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005153 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005154
5155 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5156 return (NULL);
5157
Daniel Veillard3646d642004-06-02 19:19:14 +00005158 ret = xmlSchemaAddWildcard(ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00005159 if (ret == NULL) {
5160 return (NULL);
5161 }
William M. Bracke7091952004-05-11 15:09:58 +00005162 ret->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005163 /*
5164 * Check for illegal attributes.
5165 */
5166 attr = node->properties;
5167 while (attr != NULL) {
5168 if (attr->ns == NULL) {
5169 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5170 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
5171 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
5172 xmlSchemaPIllegalAttrErr(ctxt,
5173 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5174 NULL, NULL, attr);
5175 }
5176 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5177 xmlSchemaPIllegalAttrErr(ctxt,
5178 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5179 NULL, NULL, attr);
5180 }
5181 attr = attr->next;
5182 }
5183 /* ret->id = xmlSchemaGetProp(ctxt, node, "id"); */
5184 /*
5185 * Parse the namespace list.
5186 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00005187 if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0) {
5188 xmlSchemaFreeWildcard(ret);
5189 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005190 }
5191 /*
5192 * And now for the children...
5193 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005194 child = node->children;
5195 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005196 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5197 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005198 }
5199 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005200 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005201 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5202 NULL, NULL, node, child,
5203 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005204 }
5205
5206 return (ret);
5207}
5208
5209
5210/**
5211 * xmlSchemaParseAttribute:
5212 * @ctxt: a schema validation context
5213 * @schema: the schema being built
5214 * @node: a subtree containing XML Schema informations
5215 *
5216 * parse a XML schema Attrribute declaration
5217 * *WARNING* this interface is highly subject to change
5218 *
William M. Bracke7091952004-05-11 15:09:58 +00005219 * Returns the attribute declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00005220 */
5221static xmlSchemaAttributePtr
5222xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00005223 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005224{
Daniel Veillardc0826a72004-08-10 14:17:33 +00005225 const xmlChar *name, *attrValue;
5226 xmlChar *repName = NULL; /* The reported designation. */
Daniel Veillard4255d502002-04-16 15:50:10 +00005227 xmlSchemaAttributePtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005228 xmlNodePtr child = NULL;
5229 xmlAttrPtr attr, nameAttr;
5230 int isRef = 0;
William M. Bracke7091952004-05-11 15:09:58 +00005231
5232 /*
5233 * Note that the w3c spec assumes the schema to be validated with schema
5234 * for schemas beforehand.
5235 *
5236 * 3.2.3 Constraints on XML Representations of Attribute Declarations
William M. Bracke7091952004-05-11 15:09:58 +00005237 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005238
5239 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5240 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005241 attr = xmlSchemaGetPropNode(node, "ref");
5242 nameAttr = xmlSchemaGetPropNode(node, "name");
5243
5244 if ((attr == NULL) && (nameAttr == NULL)) {
5245 /*
5246 * 3.2.3 : 3.1
5247 * One of ref or name must be present, but not both
5248 */
5249 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
5250 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, node, NULL,
5251 "One of the attributes 'ref' or 'name' must be present");
5252 return (NULL);
5253 }
5254 if ((topLevel) || (attr == NULL)) {
5255 if (nameAttr == NULL) {
5256 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
5257 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, node,
5258 "name", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005259 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005260 }
5261 } else
5262 isRef = 1;
5263
5264 if (isRef) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005265 char buf[50];
Daniel Veillardc0826a72004-08-10 14:17:33 +00005266 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix = NULL;
5267
5268 /*
5269 * Parse as attribute reference.
5270 */
5271 if (xmlSchemaPValAttrNodeQName(ctxt, schema,
5272 (xmlChar **) &xmlSchemaElemDesAttrRef, NULL, attr, &refNs,
5273 &refPrefix, &ref) != 0) {
5274 return (NULL);
5275 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005276 snprintf(buf, 49, "#aRef%d", ctxt->counter++ + 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005277 name = (const xmlChar *) buf;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005278 ret = xmlSchemaAddAttribute(ctxt, schema, name, NULL, node, 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005279 if (ret == NULL) {
5280 if (repName != NULL)
5281 xmlFree(repName);
5282 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005283 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005284 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
5285 ret->node = node;
5286 ret->refNs = refNs;
5287 ret->refPrefix = refPrefix;
5288 ret->ref = ref;
5289 /*
5290 xmlSchemaFormatTypeRep(&repName, (xmlSchemaTypePtr) ret, NULL, NULL);
5291 */
5292 if (nameAttr != NULL)
5293 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
5294 &repName, (xmlSchemaTypePtr) ret, nameAttr,
5295 "ref", "name");
5296 /*
5297 * Check for illegal attributes.
5298 */
5299 attr = node->properties;
5300 while (attr != NULL) {
5301 if (attr->ns == NULL) {
5302 if (xmlStrEqual(attr->name, BAD_CAST "type") ||
5303 xmlStrEqual(attr->name, BAD_CAST "form")) {
5304 /*
5305 * 3.2.3 : 3.2
5306 * If ref is present, then all of <simpleType>,
5307 * form and type must be absent.
5308 */
5309 xmlSchemaPIllegalAttrErr(ctxt,
5310 XML_SCHEMAP_SRC_ATTRIBUTE_3_2, &repName,
5311 (xmlSchemaTypePtr) ret, attr);
5312 } else if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
5313 (!xmlStrEqual(attr->name, BAD_CAST "use")) &&
5314 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5315 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
5316 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
5317 (!xmlStrEqual(attr->name, BAD_CAST "default"))) {
5318 xmlSchemaPIllegalAttrErr(ctxt,
5319 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5320 &repName, (xmlSchemaTypePtr) ret, attr);
5321 }
5322 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5323 xmlSchemaPIllegalAttrErr(ctxt,
5324 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5325 &repName, (xmlSchemaTypePtr) ret, attr);
5326 }
5327 attr = attr->next;
5328 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005329 } else {
William M. Bracke7091952004-05-11 15:09:58 +00005330 const xmlChar *ns = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005331
5332 /*
5333 * Parse as attribute declaration.
5334 */
5335 if (xmlSchemaPValAttrNode(ctxt,
5336 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, nameAttr,
5337 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
5338 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005339 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005340 /*
5341 xmlSchemaFormatTypeRep(&repName, NULL, xmlSchemaElemDesAttrDecl, name);
5342 */
5343 /*
5344 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
5345 */
5346 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
5347 xmlSchemaPSimpleTypeErr(ctxt,
5348 XML_SCHEMAP_NO_XMLNS,
5349 &repName, NULL, (xmlNodePtr) nameAttr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005350 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), "NCName", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005351 "The value must not match 'xmlns'",
5352 NULL, NULL);
5353 if (repName != NULL)
5354 xmlFree(repName);
5355 return (NULL);
5356 }
5357 /*
5358 * Evaluate the target namespace
5359 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005360 if (topLevel) {
5361 ns = schema->targetNamespace;
5362 } else {
5363 attr = xmlSchemaGetPropNode(node, "form");
5364 if (attr != NULL) {
5365 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5366 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
5367 ns = schema->targetNamespace;
5368 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
5369 xmlSchemaPSimpleTypeErr(ctxt,
5370 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5371 &repName, NULL, (xmlNodePtr) attr,
5372 NULL, "(qualified | unqualified)",
5373 attrValue, NULL, NULL, NULL);
5374 }
5375 } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
5376 ns = schema->targetNamespace;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005377 }
5378 ret = xmlSchemaAddAttribute(ctxt, schema, name, ns, node, topLevel);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005379 if (ret == NULL) {
5380 if (repName != NULL)
5381 xmlFree(repName);
Daniel Veillard3646d642004-06-02 19:19:14 +00005382 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005383 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005384 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005385 ret->node = node;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005386 if (topLevel)
5387 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
5388 /*
5389 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
5390 */
5391 if (xmlStrEqual(ret->targetNamespace, xmlSchemaInstanceNs)) {
5392 xmlSchemaPCustomErr(ctxt,
5393 XML_SCHEMAP_NO_XSI,
5394 &repName, (xmlSchemaTypePtr) ret, node,
5395 "The target namespace must not match '%s'",
5396 xmlSchemaInstanceNs);
5397 }
5398 /*
5399 * Check for illegal attributes.
5400 */
5401 attr = node->properties;
5402 while (attr != NULL) {
5403 if (attr->ns == NULL) {
5404 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5405 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
5406 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
5407 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
5408 (!xmlStrEqual(attr->name, BAD_CAST "type"))) {
5409 if ((topLevel) ||
5410 ((!xmlStrEqual(attr->name, BAD_CAST "form")) &&
5411 (!xmlStrEqual(attr->name, BAD_CAST "use")))) {
5412 xmlSchemaPIllegalAttrErr(ctxt,
5413 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5414 &repName, (xmlSchemaTypePtr) ret, attr);
5415 }
5416 }
5417 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5418 xmlSchemaPIllegalAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5419 &repName, (xmlSchemaTypePtr) ret, attr);
5420 }
5421 attr = attr->next;
5422 }
5423 xmlSchemaPValAttrQName(ctxt, schema, &repName, (xmlSchemaTypePtr) ret,
5424 node, "type", &ret->typeNs, NULL, &ret->typeName);
William M. Bracke7091952004-05-11 15:09:58 +00005425 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005426 /* TODO: Check ID. */
5427 ret->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Bracke7091952004-05-11 15:09:58 +00005428 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005429 * Attribute "fixed".
William M. Bracke7091952004-05-11 15:09:58 +00005430 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00005431 ret->defValue = xmlSchemaGetProp(ctxt, node, "fixed");
5432 if (ret->defValue != NULL)
5433 ret->flags |= XML_SCHEMAS_ATTR_FIXED;
5434 /*
5435 * Attribute "default".
5436 */
5437 attr = xmlSchemaGetPropNode(node, "default");
5438 if (attr != NULL) {
5439 /*
5440 * 3.2.3 : 1
5441 * default and fixed must not both be present.
5442 */
5443 if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
5444 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
5445 &repName, (xmlSchemaTypePtr) ret, attr, "default", "fixed");
5446 } else
5447 ret->defValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5448 }
5449 if (topLevel == 0) {
5450 /*
5451 * Attribute "use".
5452 */
5453 attr = xmlSchemaGetPropNode(node, "use");
5454 if (attr != NULL) {
5455 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5456 if (xmlStrEqual(attrValue, BAD_CAST "optional"))
5457 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
5458 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
5459 ret->occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
5460 else if (xmlStrEqual(attrValue, BAD_CAST "required"))
5461 ret->occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
5462 else
5463 xmlSchemaPSimpleTypeErr(ctxt,
5464 XML_SCHEMAP_INVALID_ATTR_USE,
5465 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005466 NULL, "(optional | prohibited | required)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00005467 attrValue, NULL, NULL, NULL);
5468 } else
5469 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
5470 /*
5471 * 3.2.3 : 2
5472 * If default and use are both present, use must have
5473 * the actual value optional.
5474 */
5475 if ((ret->occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
5476 (ret->defValue != NULL) &&
5477 ((ret->flags & XML_SCHEMAS_ATTR_FIXED) == 0)) {
5478 xmlSchemaPSimpleTypeErr(ctxt,
5479 XML_SCHEMAP_SRC_ATTRIBUTE_2,
5480 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005481 NULL, "(optional | prohibited | required)", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005482 "The value must be 'optional' if the attribute "
5483 "'default' is present as well", NULL, NULL);
5484 }
5485 }
5486 /*
5487 * And now for the children...
5488 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005489 child = node->children;
5490 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005491 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5492 child = child->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005493 }
5494 if (isRef) {
5495 if (child != NULL) {
5496 if (IS_SCHEMA(child, "simpleType"))
5497 /*
5498 * 3.2.3 : 3.2
5499 * If ref is present, then all of <simpleType>,
5500 * form and type must be absent.
5501 */
5502 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
5503 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
5504 "(annotation?)");
5505 else
5506 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5507 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
5508 "(annotation?)");
5509 }
5510 } else {
5511 if (IS_SCHEMA(child, "simpleType")) {
5512 if (ret->typeName != NULL) {
5513 /*
5514 * 3.2.3 : 4
5515 * type and <simpleType> must not both be present.
5516 */
5517 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
5518 &repName, (xmlSchemaTypePtr) ret, node, child,
5519 "The attribute 'type' and the <simpleType> child "
5520 "are mutually exclusive", NULL);
5521 } else
5522 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
5523 child = child->next;
5524 }
5525 if (child != NULL)
5526 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5527 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
5528 "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005529 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005530 /*
5531 * Cleanup.
5532 */
5533 if (repName != NULL)
5534 xmlFree(repName);
Daniel Veillard4255d502002-04-16 15:50:10 +00005535 return (ret);
5536}
5537
5538/**
5539 * xmlSchemaParseAttributeGroup:
5540 * @ctxt: a schema validation context
5541 * @schema: the schema being built
5542 * @node: a subtree containing XML Schema informations
5543 *
5544 * parse a XML schema Attribute Group declaration
5545 * *WARNING* this interface is highly subject to change
5546 *
5547 * Returns the attribute group or NULL in case of error.
5548 */
5549static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005550xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00005551 xmlSchemaPtr schema, xmlNodePtr node,
5552 int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005553{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005554 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00005555 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00005556 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005557 const xmlChar *oldcontainer;
5558 xmlAttrPtr attr, nameAttr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005559
5560 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5561 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005562
5563 nameAttr = xmlSchemaGetPropNode(node, "name");
5564 attr = xmlSchemaGetPropNode(node, "ref");
5565 if ((topLevel) || (attr == NULL)) {
5566 /*
5567 * Parse as an attribute group definition.
5568 * Note that those are allowed at top level only.
5569 */
5570 if (nameAttr == NULL) {
5571 xmlSchemaPMissingAttrErr(ctxt,
5572 XML_SCHEMAP_S4S_ATTR_MISSING,
5573 NULL, NULL, node, "name", NULL);
5574 return (NULL);
5575 }
5576 name = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) nameAttr);
5577 /*
5578 * The name is crucial, exit if invalid.
5579 */
5580 if (xmlSchemaPValAttrNode(ctxt,
5581 NULL, NULL, nameAttr,
5582 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
5583 return (NULL);
5584 }
5585 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
5586 if (ret == NULL)
5587 return (NULL);
5588 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
5589 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
5590 ret->node = node;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005591 ret->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005592 } else {
5593 char buf[50];
5594 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix;
5595
5596 /*
5597 * Parse as an attribute group definition reference.
5598 */
5599 if (attr == NULL) {
5600 xmlSchemaPMissingAttrErr(ctxt,
5601 XML_SCHEMAP_S4S_ATTR_MISSING,
5602 NULL, NULL, node, "ref", NULL);
5603 }
5604 xmlSchemaPValAttrNodeQName(ctxt, schema,
5605 NULL, NULL, attr, &refNs, &refPrefix, &ref);
5606
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005607 snprintf(buf, 49, "#agRef%d", ctxt->counter++ + 1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005608 name = (const xmlChar *) buf;
5609 if (name == NULL) {
5610 xmlSchemaPErrMemory(ctxt, "creating internal name for an "
5611 "attribute group definition reference", node);
5612 return (NULL);
5613 }
5614 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
5615 if (ret == NULL)
5616 return (NULL);
5617 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
5618 ret->ref = ref;
5619 ret->refNs = refNs;
5620 /* TODO: Is @refPrefix currently used? */
5621 ret->refPrefix = refPrefix;
5622 ret->node = node;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005623 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005624 /*
5625 * Check for illegal attributes.
5626 */
5627 attr = node->properties;
5628 while (attr != NULL) {
5629 if (attr->ns == NULL) {
5630 if ((((topLevel == 0) && (!xmlStrEqual(attr->name, BAD_CAST "ref"))) ||
5631 (topLevel && (!xmlStrEqual(attr->name, BAD_CAST "name")))) &&
5632 (!xmlStrEqual(attr->name, BAD_CAST "id")))
5633 {
5634 xmlSchemaPIllegalAttrErr(ctxt,
5635 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5636 NULL, NULL, attr);
5637 }
5638 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5639 xmlSchemaPIllegalAttrErr(ctxt,
5640 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5641 NULL, NULL, attr);
5642 }
5643 attr = attr->next;
5644 }
5645 /* TODO: Validate "id" ? */
5646 /*
5647 * And now for the children...
5648 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005649 oldcontainer = ctxt->container;
Daniel Veillard4255d502002-04-16 15:50:10 +00005650 ctxt->container = name;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005651 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00005652 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005653 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5654 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005655 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005656 if (topLevel) {
5657 child = xmlSchemaParseAttrDecls(ctxt, schema, child, (xmlSchemaTypePtr) ret);
5658 if (IS_SCHEMA(child, "anyAttribute")) {
5659 ret->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
5660 child = child->next;
5661 }
5662 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005663 if (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005664 xmlSchemaPContentErr(ctxt,
5665 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5666 NULL, NULL, node, child, NULL,
5667 "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005668 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005669 ctxt->container = oldcontainer;
5670 return (ret);
5671}
5672
5673/**
William M. Brack2f2a6632004-08-20 23:09:47 +00005674 * xmlSchemaPValAttrFormDefault:
5675 * @value: the value
5676 * @flags: the flags to be modified
5677 * @flagQualified: the specific flag for "qualified"
5678 *
5679 * Returns 0 if the value is valid, 1 otherwise.
5680 */
5681static int
5682xmlSchemaPValAttrFormDefault(const xmlChar *value,
5683 int *flags,
5684 int flagQualified)
5685{
5686 if (xmlStrEqual(value, BAD_CAST "qualified")) {
5687 if ((*flags & flagQualified) == 0)
5688 *flags |= flagQualified;
5689 } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
5690 return (1);
5691
5692 return (0);
5693}
5694
5695/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005696 * xmlSchemaPValAttrBlockFinal:
5697 * @value: the value
5698 * @flags: the flags to be modified
5699 * @flagAll: the specific flag for "#all"
5700 * @flagExtension: the specific flag for "extension"
5701 * @flagRestriction: the specific flag for "restriction"
5702 * @flagSubstitution: the specific flag for "substitution"
5703 * @flagList: the specific flag for "list"
5704 * @flagUnion: the specific flag for "union"
5705 *
5706 * Validates the value of the attribute "final" and "block". The value
5707 * is converted into the specified flag values and returned in @flags.
5708 *
5709 * Returns 0 if the value is valid, 1 otherwise.
5710 */
5711
5712static int
5713xmlSchemaPValAttrBlockFinal(const xmlChar *value,
5714 int *flags,
5715 int flagAll,
5716 int flagExtension,
5717 int flagRestriction,
5718 int flagSubstitution,
5719 int flagList,
5720 int flagUnion)
5721{
5722 int ret = 0;
5723
5724 /*
5725 * TODO: This does not check for dublicate entries.
5726 */
William M. Brack2f2a6632004-08-20 23:09:47 +00005727 if (value == NULL)
5728 return (1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005729 if (xmlStrEqual(value, BAD_CAST "#all")) {
5730 if (flagAll != -1)
5731 *flags |= flagAll;
5732 else {
5733 if (flagExtension != -1)
5734 *flags |= flagExtension;
5735 if (flagRestriction != -1)
5736 *flags |= flagRestriction;
5737 if (flagSubstitution != -1)
5738 *flags |= flagSubstitution;
5739 if (flagList != -1)
5740 *flags |= flagList;
5741 if (flagUnion != -1)
5742 *flags |= flagUnion;
5743 }
5744 } else {
5745 const xmlChar *end, *cur = value;
5746 xmlChar *item;
5747
5748 do {
5749 while (IS_BLANK_CH(*cur))
5750 cur++;
5751 end = cur;
5752 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
5753 end++;
5754 if (end == cur)
5755 break;
5756 item = xmlStrndup(cur, end - cur);
5757 if (xmlStrEqual(item, BAD_CAST "extension")) {
5758 if (flagExtension != -1) {
5759 if ((*flags & flagExtension) == 0)
5760 *flags |= flagExtension;
5761 } else
5762 ret = 1;
5763 } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
5764 if (flagRestriction != -1) {
5765 if ((*flags & flagRestriction) == 0)
5766 *flags |= flagRestriction;
5767 } else
5768 ret = 1;
5769 } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
5770 if (flagSubstitution != -1) {
5771 if ((*flags & flagSubstitution) == 0)
5772 *flags |= flagSubstitution;
5773 } else
5774 ret = 1;
5775 } else if (xmlStrEqual(item, BAD_CAST "list")) {
5776 if (flagList != -1) {
5777 if ((*flags & flagList) == 0)
5778 *flags |= flagList;
5779 } else
5780 ret = 1;
5781 } else if (xmlStrEqual(item, BAD_CAST "union")) {
5782 if (flagUnion != -1) {
5783 if ((*flags & flagUnion) == 0)
5784 *flags |= flagUnion;
5785 } else
5786 ret = 1;
5787 } else
5788 ret = 1;
5789 if (item != NULL)
5790 xmlFree(item);
5791 cur = end;
5792 } while ((ret == 0) && (*cur != 0));
5793 }
5794
5795 return (ret);
5796}
5797
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005798#ifdef IDC_ENABLED
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00005799static int
5800xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
5801 xmlSchemaPtr schema,
5802 xmlSchemaIDCPtr idc,
5803 xmlSchemaIDCSelectPtr selector,
5804 xmlNodePtr parNode,
5805 xmlAttrPtr attr,
5806 int isField)
5807{
5808 xmlNodePtr node;
5809
5810 /*
5811 * c-selector-xpath:
5812 * Schema Component Constraint: Selector Value OK
5813 *
5814 * TODO: 1 The {selector} must be a valid XPath expression, as defined
5815 * in [XPath].
5816 */
5817 if (selector == NULL) {
5818 xmlSchemaPErr(ctxt, idc->node,
5819 XML_SCHEMAP_INTERNAL,
5820 "Internal error: xmlSchemaCheckCSelectorXPath, "
5821 "the selector is not specified.\n", NULL, NULL);
5822 return (-1);
5823 }
5824 if (attr == NULL)
5825 node = idc->node;
5826 else
5827 node = (xmlNodePtr) attr;
5828 if (selector->xpath == NULL) {
5829 xmlSchemaPCustomErr(ctxt,
5830 /* TODO: Adjust error code. */
5831 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5832 NULL, NULL, node,
5833 "The XPath expression of the selector is not valid", NULL);
5834 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
5835 } else {
5836 /*
5837 * Compile the XPath expression.
5838 */
5839 /*
5840 * TODO: We need the array of in-scope namespaces for compilation.
5841 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00005842 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
5843 NULL, 0, NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00005844#ifdef IDC_XPATH_SUPPORT
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00005845 if (selector->xpathComp == NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00005846 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00005847 * TODO: Adjust error code? *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00005848 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5849 NULL, NULL, node,
5850 "The XPath expression '%s' could not be "
5851 "compiled", selector->xpath);
5852 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
5853 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00005854#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00005855 }
5856 return (0);
5857}
5858
5859/**
5860 * xmlSchemaAssignAnnotation:
5861 * @item: the schema component
5862 * @annot: the annotation
5863 *
5864 * Adds the annotation to the given schema component.
5865 *
5866 * Returns the given annotaion.
5867 */
5868static xmlSchemaAnnotPtr
5869xmlSchemaAssignAnnotation(xmlSchemaBasicItemPtr item,
5870 xmlSchemaAnnotPtr annot)
5871{
5872 xmlSchemaAnnotPtr cur = item->annot;
5873
5874 if (item->annot == NULL) {
5875 item->annot = annot;
5876 return (annot);
5877 }
5878 cur = item->annot;
5879 if (cur->next != NULL) {
5880 cur = cur->next;
5881 }
5882 cur->next = annot;
5883 return (annot);
5884}
5885
5886/**
5887 * xmlSchemaParseIDCSelectorAndField:
5888 * @ctxt: a schema validation context
5889 * @schema: the schema being built
5890 * @node: a subtree containing XML Schema informations
5891 *
5892 * Parses a XML Schema identity-contraint definition's
5893 * <selector> and <field> elements.
5894 *
5895 * Returns the parsed identity-constraint definition.
5896 */
5897static xmlSchemaIDCSelectPtr
5898xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
5899 xmlSchemaPtr schema,
5900 xmlSchemaIDCPtr idc,
5901 xmlNodePtr node,
5902 int isField)
5903{
5904 xmlSchemaIDCSelectPtr item;
5905 xmlNodePtr child = NULL;
5906 xmlAttrPtr attr;
5907
5908 /*
5909 * Check for illegal attributes.
5910 */
5911 attr = node->properties;
5912 while (attr != NULL) {
5913 if (attr->ns == NULL) {
5914 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5915 (!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
5916 xmlSchemaPIllegalAttrErr(ctxt,
5917 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5918 NULL, NULL, attr);
5919 }
5920 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5921 xmlSchemaPIllegalAttrErr(ctxt,
5922 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5923 NULL, NULL, attr);
5924 }
5925 attr = attr->next;
5926 }
5927 /*
5928 * Create the item.
5929 */
5930 item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
5931 if (item == NULL) {
5932 xmlSchemaPErrMemory(ctxt,
5933 "allocating a 'selector' of an identity-constraint definition",
5934 NULL);
5935 return (NULL);
5936 }
5937 memset(item, 0, sizeof(xmlSchemaIDCSelect));
5938 /*
5939 * Attribute "xpath" (mandatory).
5940 */
5941 attr = xmlSchemaGetPropNode(node, "xpath");
5942 if (attr == NULL) {
5943 xmlSchemaPMissingAttrErr(ctxt,
5944 XML_SCHEMAP_S4S_ATTR_MISSING,
5945 NULL, NULL, node,
5946 "name", NULL);
5947 } else {
5948 item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5949 /*
5950 * URGENT TODO: "field"s have an other syntax than "selector"s.
5951 */
5952
5953 if (xmlSchemaCheckCSelectorXPath(ctxt, schema,
5954 idc, item, node, attr, isField) == -1)
5955 {
5956 xmlSchemaPErr(ctxt,
5957 (xmlNodePtr) attr,
5958 XML_SCHEMAP_INTERNAL,
5959 "Internal error: xmlSchemaParseIDCSelectorAndField, "
5960 "validating the XPath expression of a IDC selector.\n",
5961 NULL, NULL);
5962 }
5963
5964 }
5965 /*
5966 * And now for the children...
5967 */
5968 child = node->children;
5969 if (IS_SCHEMA(child, "annotation")) {
5970 /*
5971 * Add the annotation to the parent IDC.
5972 */
5973 xmlSchemaAssignAnnotation((xmlSchemaBasicItemPtr) idc,
5974 xmlSchemaParseAnnotation(ctxt, schema, child));
5975 child = child->next;
5976 }
5977 if (child != NULL) {
5978 xmlSchemaPContentErr(ctxt,
5979 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5980 NULL, NULL, node, child,
5981 NULL, "(annotation?)");
5982 }
5983
5984 return (item);
5985}
5986
5987/**
5988 * xmlSchemaParseIDC:
5989 * @ctxt: a schema validation context
5990 * @schema: the schema being built
5991 * @node: a subtree containing XML Schema informations
5992 *
5993 * Parses a XML Schema identity-contraint definition.
5994 *
5995 * Returns the parsed identity-constraint definition.
5996 */
5997static xmlSchemaIDCPtr
5998xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
5999 xmlSchemaPtr schema,
6000 xmlNodePtr node,
6001 xmlSchemaTypeType idcCategory,
6002 const xmlChar *targetNamespace)
6003{
6004 xmlSchemaIDCPtr item = NULL;
6005 xmlNodePtr child = NULL;
6006 xmlAttrPtr attr;
6007 const xmlChar *name = NULL;
6008 xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
6009 int resAdd;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00006010
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006011 /*
6012 * Check for illegal attributes.
6013 */
6014 attr = node->properties;
6015 while (attr != NULL) {
6016 if (attr->ns == NULL) {
6017 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6018 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
6019 ((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
6020 (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
6021 xmlSchemaPIllegalAttrErr(ctxt,
6022 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6023 NULL, NULL, attr);
6024 }
6025 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6026 xmlSchemaPIllegalAttrErr(ctxt,
6027 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6028 NULL, NULL, attr);
6029 }
6030 attr = attr->next;
6031 }
6032 /*
6033 * Attribute "name" (mandatory).
6034 */
6035 attr = xmlSchemaGetPropNode(node, "name");
6036 if (attr == NULL) {
6037 xmlSchemaPMissingAttrErr(ctxt,
6038 XML_SCHEMAP_S4S_ATTR_MISSING,
6039 NULL, NULL, node,
6040 "name", NULL);
6041 return (NULL);
6042 } else if (xmlSchemaPValAttrNode(ctxt,
6043 NULL, NULL, attr,
6044 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
6045 return (NULL);
6046 }
6047 /*
6048 * Create the component.
6049 */
6050 if (schema->idcDef == NULL)
6051 schema->idcDef = xmlHashCreateDict(10, ctxt->dict);
6052 if (schema->idcDef == NULL)
6053 return (NULL);
6054
6055 item = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
6056 if (item == NULL) {
6057 xmlSchemaPErrMemory(ctxt,
6058 "allocating an identity-constraint definition", NULL);
6059 return (NULL);
6060 }
6061 /*
6062 * Add the IDC to the list of IDCs on the schema component.
6063 */
6064 resAdd = xmlHashAddEntry2(schema->idcDef, name, targetNamespace, item);
6065 if (resAdd != 0) {
6066 xmlSchemaPCustomErrExt(ctxt,
6067 XML_SCHEMAP_REDEFINED_TYPE,
6068 NULL, NULL, node,
6069 "An identity-constraint definition with the name '%s' "
6070 "and targetNamespace '%s' does already exist",
6071 name, targetNamespace, NULL);
6072 xmlFree(item);
6073 return (NULL);
6074 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006075 memset(item, 0, sizeof(xmlSchemaIDC));
6076 item->name = name;
6077 item->type = idcCategory;
6078 item->node = node;
6079 /*
6080 * The target namespace of the parent element declaration.
6081 */
6082 item->targetNamespace = targetNamespace;
6083 /* TODO: Handle attribute "id". */
6084 if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
6085 /*
6086 * Attribute "refer" (mandatory).
6087 */
6088 attr = xmlSchemaGetPropNode(node, "refer");
6089 if (attr == NULL) {
6090 xmlSchemaPMissingAttrErr(ctxt,
6091 XML_SCHEMAP_S4S_ATTR_MISSING,
6092 NULL, NULL, node,
6093 "refer", NULL);
6094 } else {
6095 /*
6096 * Create a reference item.
6097 */
6098 item->ref = (xmlSchemaItemQNRefPtr) xmlMalloc(
6099 sizeof(xmlSchemaItemQNRef));
6100 if (item->ref == NULL) {
6101 xmlSchemaPErrMemory(ctxt,
6102 "allocating a QName reference item", NULL);
6103 return (NULL);
6104 }
6105 memset(item->ref, 0, sizeof(xmlSchemaItemQNRef));
6106 xmlSchemaPValAttrNodeQName(ctxt, schema,
6107 NULL, NULL, attr,
6108 &(item->ref->targetNamespace), 0,
6109 &(item->ref->name));
6110 }
6111 }
6112 /*
6113 * And now for the children...
6114 */
6115 child = node->children;
6116 if (IS_SCHEMA(child, "annotation")) {
6117 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6118 child = child->next;
6119 }
6120 /*
6121 * Child element <selector>.
6122 */
6123 if (IS_SCHEMA(child, "selector")) {
6124 item->selector = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
6125 item, child, 0);
6126 child = child->next;
6127 /*
6128 * Child elements <field>.
6129 */
6130 if (IS_SCHEMA(child, "field")) {
6131 do {
6132 field = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
6133 item, child, 1);
6134 if (field != NULL) {
6135 field->index = item->nbFields;
6136 item->nbFields++;
6137 if (lastField != NULL)
6138 lastField->next = field;
6139 else
6140 item->fields = field;
6141 lastField = field;
6142 }
6143 child = child->next;
6144 } while (IS_SCHEMA(child, "field"));
6145 } else {
6146 xmlSchemaPContentErr(ctxt,
6147 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6148 NULL, NULL, node, child,
6149 NULL, "(annotation?, (selector, field+))");
6150 }
6151 }
6152 if (child != NULL) {
6153 xmlSchemaPContentErr(ctxt,
6154 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6155 NULL, NULL, node, child,
6156 NULL, "(annotation?, (selector, field+))");
6157 }
6158
6159 return (item);
6160}
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006161#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006162
Daniel Veillardc0826a72004-08-10 14:17:33 +00006163/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006164 * xmlSchemaParseElement:
6165 * @ctxt: a schema validation context
6166 * @schema: the schema being built
6167 * @node: a subtree containing XML Schema informations
6168 *
6169 * parse a XML schema Element declaration
6170 * *WARNING* this interface is highly subject to change
6171 *
William M. Bracke7091952004-05-11 15:09:58 +00006172 * Returns the parsed element declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00006173 */
6174static xmlSchemaElementPtr
6175xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00006176 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006177{
Daniel Veillardc0826a72004-08-10 14:17:33 +00006178 const xmlChar *name = NULL;
6179 const xmlChar *attrValue;
6180 xmlChar *repName = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00006181 xmlSchemaElementPtr ret;
6182 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006183 const xmlChar *oldcontainer;
6184 xmlAttrPtr attr, nameAttr;
6185 int minOccurs, maxOccurs;
6186 int isRef = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006187#ifdef IDC_ENABLED
6188 xmlSchemaIDCPtr curIDC, lastIDC = NULL;
6189#endif
William M. Bracke7091952004-05-11 15:09:58 +00006190
6191 /* 3.3.3 Constraints on XML Representations of Element Declarations */
6192 /* TODO: Complete implementation of 3.3.6 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006193
Daniel Veillard4255d502002-04-16 15:50:10 +00006194 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6195 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006196
Daniel Veillardc0826a72004-08-10 14:17:33 +00006197 oldcontainer = ctxt->container;
6198
6199 nameAttr = xmlSchemaGetPropNode(node, "name");
6200 attr = xmlSchemaGetPropNode(node, "ref");
6201 if ((topLevel) || (attr == NULL)) {
6202 if (nameAttr == NULL) {
6203 xmlSchemaPMissingAttrErr(ctxt,
6204 XML_SCHEMAP_S4S_ATTR_MISSING,
6205 (xmlChar **) &xmlSchemaElemDesElemDecl, NULL, node,
6206 "name", NULL);
6207 return (NULL);
6208 }
6209 name = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) nameAttr);
6210 } else {
6211 isRef = 1;
6212
6213 }
6214 /*
6215 * ... unless minOccurs=maxOccurs=0, in which case the item corresponds
6216 * to no component at all
6217 * TODO: It might be better to validate the element, even if it won't be
6218 * used.
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006219 */
6220 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
6221 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(nonNegativeInteger | unbounded)");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006222 if ((minOccurs == 0) && (maxOccurs == 0))
6223 return (NULL);
6224 /*
6225 * If we get a "ref" attribute on a local <element> we will assume it's
6226 * a reference - even if there's a "name" attribute; this seems to be more
6227 * robust.
6228 */
6229 if (isRef) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006230 char buf[50];
Daniel Veillardc0826a72004-08-10 14:17:33 +00006231 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix;
6232
6233 /*
6234 * Parse as a particle.
6235 */
6236 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006237 (xmlChar **) &xmlSchemaElemDesElemRef,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006238 NULL, attr, &refNs, &refPrefix, &ref);
6239
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006240 snprintf(buf, 49, "#eRef%d", ctxt->counter++ + 1);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006241 ret = xmlSchemaAddElement(ctxt, schema, (const xmlChar *) buf, NULL, node, 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006242 if (ret == NULL) {
6243 if (repName != NULL)
6244 xmlFree(repName);
6245 return (NULL);
6246 }
6247 ret->type = XML_SCHEMA_TYPE_ELEMENT;
6248 ret->node = node;
6249 ret->ref = ref;
6250 ret->refNs = refNs;
6251 ret->refPrefix = refPrefix;
6252 ret->flags |= XML_SCHEMAS_ELEM_REF;
6253 /*
6254 * Check for illegal attributes.
6255 */
6256 /*
6257 * 3.3.3 : 2.1
6258 * One of ref or name must be present, but not both
6259 */
6260 if (nameAttr != NULL) {
6261 xmlSchemaPMutualExclAttrErr(ctxt,
6262 XML_SCHEMAP_SRC_ELEMENT_2_1,
6263 &repName, (xmlSchemaTypePtr) ret, nameAttr,
6264 "ref", "name");
6265 }
6266 /* 3.3.3 : 2.2 */
6267 attr = node->properties;
6268 while (attr != NULL) {
6269 if (attr->ns == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006270 if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
6271 xmlStrEqual(attr->name, BAD_CAST "name") ||
6272 xmlStrEqual(attr->name, BAD_CAST "id") ||
6273 xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
6274 xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
6275 {
6276 attr = attr->next;
6277 continue;
6278 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006279 xmlSchemaPCustomAttrErr(ctxt,
6280 XML_SCHEMAP_SRC_ELEMENT_2_2,
6281 &repName, (xmlSchemaTypePtr) ret, attr,
6282 "Only the attributes 'minOccurs', 'maxOccurs' and "
6283 "'id' are allowed in addition to 'ref'");
6284 break;
6285 }
6286 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6287 xmlSchemaPIllegalAttrErr(ctxt,
6288 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6289 &repName, (xmlSchemaTypePtr) ret, attr);
6290 }
6291 attr = attr->next;
6292 }
6293 } else {
6294 const xmlChar *ns = NULL, *fixed;
6295
6296 /*
6297 * Parse as an element declaration.
6298 */
6299 if (xmlSchemaPValAttrNode(ctxt,
6300 (xmlChar **) &xmlSchemaElemDesElemDecl, NULL, nameAttr,
6301 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
6302 return (NULL);
6303 /*
6304 * Evaluate the target namespace.
6305 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006306 if (topLevel) {
6307 ns = schema->targetNamespace;
6308 } else {
6309 attr = xmlSchemaGetPropNode(node, "form");
6310 if (attr != NULL) {
6311 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6312 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
William M. Bracke7091952004-05-11 15:09:58 +00006313 ns = schema->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006314 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
6315 xmlSchemaPSimpleTypeErr(ctxt,
6316 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6317 &repName, NULL, (xmlNodePtr) attr,
6318 NULL, "(qualified | unqualified)",
6319 attrValue, NULL, NULL, NULL);
6320 }
6321 } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
6322 ns = schema->targetNamespace;
William M. Brack2f2a6632004-08-20 23:09:47 +00006323 }
6324 ret = xmlSchemaAddElement(ctxt, schema, name, ns, node, topLevel);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006325 if (ret == NULL) {
6326 if (repName != NULL)
6327 xmlFree(repName);
6328 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006329 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006330 ret->type = XML_SCHEMA_TYPE_ELEMENT;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006331 ret->node = node;
6332 ret->targetNamespace = ns;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006333 /*
6334 * Check for illegal attributes.
6335 */
William M. Bracke7091952004-05-11 15:09:58 +00006336 attr = node->properties;
6337 while (attr != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006338 if (attr->ns == NULL) {
6339 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
6340 (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
6341 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6342 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
6343 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
6344 (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006345 (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
6346 {
6347 if (topLevel == 0) {
6348 if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006349 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006350 (!xmlStrEqual(attr->name, BAD_CAST "form")))
6351 {
6352 if (xmlStrEqual(attr->name, BAD_CAST "substitutionGroup")) {
6353 /*
6354 * 3.3.6 : 3 If there is a non-·absent· {substitution
6355 * group affiliation}, then {scope} must be global.
6356 * TODO: This one is redundant, since the S4S does
6357 * prohibit this attribute on local declarations already;
6358 * so why an explicit error code? Weird spec.
6359 * TODO: Move this to the proper constraint layer.
6360 * TODO: Or better wait for spec 1.1 to come.
6361 */
6362 xmlSchemaPIllegalAttrErr(ctxt,
6363 XML_SCHEMAP_E_PROPS_CORRECT_3,
6364 &repName, (xmlSchemaTypePtr) ret, attr);
6365 } else {
6366 xmlSchemaPIllegalAttrErr(ctxt,
6367 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6368 &repName, (xmlSchemaTypePtr) ret, attr);
6369 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006370 }
6371 } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
6372 (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
6373 (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
6374
6375 xmlSchemaPIllegalAttrErr(ctxt,
6376 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6377 &repName, (xmlSchemaTypePtr) ret, attr);
6378 }
6379 }
6380 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6381
6382 xmlSchemaPIllegalAttrErr(ctxt,
6383 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6384 &repName, (xmlSchemaTypePtr) ret, attr);
William M. Bracke7091952004-05-11 15:09:58 +00006385 }
6386 attr = attr->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006387 }
William M. Bracke7091952004-05-11 15:09:58 +00006388 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006389 * Extract/validate attributes.
6390 */
6391 if (topLevel) {
6392 /*
6393 * Process top attributes of global element declarations here.
6394 */
6395 ret->flags |= XML_SCHEMAS_ELEM_GLOBAL;
6396 ret->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
6397 xmlSchemaPValAttrQName(ctxt, schema, &repName,
6398 (xmlSchemaTypePtr) ret, node, "substitutionGroup",
6399 &(ret->substGroupNs), NULL, &(ret->substGroup));
6400 if (xmlGetBooleanProp(ctxt, &repName, (xmlSchemaTypePtr) ret,
6401 node, "abstract", 0))
6402 ret->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
6403 /*
6404 * Attribute "final".
6405 */
6406 attr = xmlSchemaGetPropNode(node, "final");
6407 if (attr == NULL) {
6408 ret->flags |= XML_SCHEMAS_ELEM_FINAL_ABSENT;
6409 } else {
6410 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6411 if (xmlSchemaPValAttrBlockFinal(attrValue, &(ret->flags),
6412 -1,
6413 XML_SCHEMAS_ELEM_FINAL_EXTENSION,
6414 XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
6415 xmlSchemaPSimpleTypeErr(ctxt,
6416 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6417 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00006418 NULL, "(#all | List of (extension | restriction))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00006419 attrValue, NULL, NULL, NULL);
6420 }
6421 }
6422 }
6423 /*
6424 * Attribute "block".
6425 */
6426 attr = xmlSchemaGetPropNode(node, "block");
6427 if (attr == NULL) {
6428 ret->flags |= XML_SCHEMAS_ELEM_BLOCK_ABSENT;
6429 } else {
6430 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6431 if (xmlSchemaPValAttrBlockFinal(attrValue, &(ret->flags),
6432 -1,
6433 XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
6434 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
6435 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
6436 xmlSchemaPSimpleTypeErr(ctxt,
6437 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6438 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00006439 NULL, "(#all | List of (extension | "
Daniel Veillardc0826a72004-08-10 14:17:33 +00006440 "restriction | substitution))", attrValue,
6441 NULL, NULL, NULL);
6442 }
6443 }
6444 if (xmlGetBooleanProp(ctxt, &repName, (xmlSchemaTypePtr) ret,
6445 node, "nillable", 0))
6446 ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006447
Daniel Veillardc0826a72004-08-10 14:17:33 +00006448 xmlSchemaPValAttrQName(ctxt, schema,
6449 &repName, (xmlSchemaTypePtr) ret, node,
6450 "type", &(ret->namedTypeNs), NULL, &(ret->namedType));
Daniel Veillard4255d502002-04-16 15:50:10 +00006451
Daniel Veillardc0826a72004-08-10 14:17:33 +00006452 ret->value = xmlSchemaGetProp(ctxt, node, "default");
6453 attr = xmlSchemaGetPropNode(node, "fixed");
6454 if (attr != NULL) {
6455 fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6456 if (ret->value != NULL) {
6457 /*
6458 * 3.3.3 : 1
6459 * default and fixed must not both be present.
6460 */
6461 xmlSchemaPMutualExclAttrErr(ctxt,
6462 XML_SCHEMAP_SRC_ELEMENT_1,
6463 &repName, (xmlSchemaTypePtr) ret, attr,
6464 "default", "fixed");
6465 } else {
6466 ret->flags |= XML_SCHEMAS_ELEM_FIXED;
6467 ret->value = fixed;
6468 }
6469 }
6470 }
6471 /*
6472 * Extract/validate common attributes.
6473 */
6474 /* TODO: Check ID: */
6475 ret->id = xmlSchemaGetProp(ctxt, node, "id");
6476 ret->minOccurs = minOccurs;
6477 ret->maxOccurs = maxOccurs;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006478 if (topLevel != 1)
6479 xmlSchemaPCheckParticleCorrect_2(ctxt, (xmlSchemaTypePtr) ret,
6480 node, minOccurs, maxOccurs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006481 /*
6482 * And now for the children...
6483 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006484 ctxt->container = ret->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006485 child = node->children;
6486 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006487 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6488 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006489 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006490 if (isRef) {
6491 if (child != NULL) {
6492 xmlSchemaPContentErr(ctxt,
6493 XML_SCHEMAP_SRC_ELEMENT_2_2,
6494 &repName, (xmlSchemaTypePtr) ret, node, child,
6495 NULL, "(annotation?)");
William M. Bracke7091952004-05-11 15:09:58 +00006496 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006497 } else {
William M. Bracke7091952004-05-11 15:09:58 +00006498 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006499 /*
6500 * 3.3.3 : 3
6501 * "type" and either <simpleType> or <complexType> are mutually
6502 * exclusive
6503 */
William M. Bracke7091952004-05-11 15:09:58 +00006504 if (ret->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006505 xmlSchemaPContentErr(ctxt,
6506 XML_SCHEMAP_SRC_ELEMENT_3,
6507 &repName, (xmlSchemaTypePtr) ret, node, child,
6508 "The attribute 'type' and the <complexType> child are "
6509 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006510 } else
Daniel Veillard3646d642004-06-02 19:19:14 +00006511 ret->subtypes = xmlSchemaParseComplexType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00006512 child = child->next;
6513 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006514 /*
6515 * 3.3.3 : 3
6516 * "type" and either <simpleType> or <complexType> are
6517 * mutually exclusive
6518 */
William M. Bracke7091952004-05-11 15:09:58 +00006519 if (ret->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006520 xmlSchemaPContentErr(ctxt,
6521 XML_SCHEMAP_SRC_ELEMENT_3,
6522 &repName, (xmlSchemaTypePtr) ret, node, child,
6523 "The attribute 'type' and the <simpleType> child are "
6524 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006525 } else
Daniel Veillard3646d642004-06-02 19:19:14 +00006526 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00006527 child = child->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006528 }
William M. Bracke7091952004-05-11 15:09:58 +00006529 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00006530 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006531#ifdef IDC_ENABLED
6532 if (IS_SCHEMA(child, "unique")) {
6533 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
6534 XML_SCHEMA_TYPE_IDC_UNIQUE, ret->targetNamespace);
6535 } else if (IS_SCHEMA(child, "key")) {
6536 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
6537 XML_SCHEMA_TYPE_IDC_KEY, ret->targetNamespace);
6538 } else if (IS_SCHEMA(child, "keyref")) {
6539 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
6540 XML_SCHEMA_TYPE_IDC_KEYREF, ret->targetNamespace);
6541 }
6542 if (lastIDC != NULL)
6543 lastIDC->next = curIDC;
6544 else
6545 (xmlSchemaIDCPtr) ret->idcs = curIDC;
6546 lastIDC = curIDC;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006547#else
6548 TODO
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006549#endif
6550 child = child->next;
William M. Bracke7091952004-05-11 15:09:58 +00006551 }
6552 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006553 xmlSchemaPContentErr(ctxt,
6554 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6555 &repName, (xmlSchemaTypePtr) ret, node, child,
6556 NULL, "(annotation?, ((simpleType | complexType)?, "
6557 "(unique | key | keyref)*))");
6558 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006559
Daniel Veillardc0826a72004-08-10 14:17:33 +00006560 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006561 ctxt->container = oldcontainer;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006562 /*
6563 * Cleanup.
6564 */
6565 if (repName != NULL)
6566 xmlFree(repName);
6567 /*
6568 * NOTE: Element Declaration Representation OK 4. will be checked at a
6569 * different layer.
6570 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006571 return (ret);
6572}
6573
6574/**
6575 * xmlSchemaParseUnion:
6576 * @ctxt: a schema validation context
6577 * @schema: the schema being built
6578 * @node: a subtree containing XML Schema informations
6579 *
6580 * parse a XML schema Union definition
6581 * *WARNING* this interface is highly subject to change
6582 *
William M. Bracke7091952004-05-11 15:09:58 +00006583 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00006584 * 1 in case of success.
6585 */
6586static xmlSchemaTypePtr
6587xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006588 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006589{
6590 xmlSchemaTypePtr type, subtype, last = NULL;
6591 xmlNodePtr child = NULL;
6592 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00006593 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006594
6595 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6596 return (NULL);
6597
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006598 snprintf((char *) name, 30, "#union%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00006599 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006600 if (type == NULL)
6601 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00006602 type->type = XML_SCHEMA_TYPE_UNION;
Daniel Veillard4255d502002-04-16 15:50:10 +00006603 type->node = node;
William M. Brack2f2a6632004-08-20 23:09:47 +00006604 /*
6605 * Check for illegal attributes.
6606 */
6607 attr = node->properties;
6608 while (attr != NULL) {
6609 if (attr->ns == NULL) {
6610 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6611 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
6612 xmlSchemaPIllegalAttrErr(ctxt,
6613 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6614 NULL, type, attr);
6615 }
6616 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6617 xmlSchemaPIllegalAttrErr(ctxt,
6618 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6619 NULL, type, attr);
6620 }
6621 attr = attr->next;
6622 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006623 type->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00006624 /*
6625 * Attribute "memberTypes". This is a list of QNames.
6626 * TODO: Validate the QNames.
6627 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00006628 type->base = xmlSchemaGetProp(ctxt, node, "memberTypes");
William M. Brack2f2a6632004-08-20 23:09:47 +00006629 /*
6630 * And now for the children...
6631 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006632 child = node->children;
6633 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006634 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6635 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006636 }
William M. Brack2f2a6632004-08-20 23:09:47 +00006637 while (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006638 subtype = (xmlSchemaTypePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00006639 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006640 if (subtype != NULL) {
6641 if (last == NULL) {
6642 type->subtypes = subtype;
6643 last = subtype;
6644 } else {
6645 last->next = subtype;
6646 last = subtype;
6647 }
6648 last->next = NULL;
6649 }
6650 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006651 }
6652 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006653 /* TODO: Think about the error code. */
6654 xmlSchemaPContentErr(ctxt,
6655 XML_SCHEMAP_UNKNOWN_UNION_CHILD,
6656 NULL, type, node, child, NULL, "(annotation?, simpleType*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006657 }
6658 return (type);
6659}
6660
6661/**
6662 * xmlSchemaParseList:
6663 * @ctxt: a schema validation context
6664 * @schema: the schema being built
6665 * @node: a subtree containing XML Schema informations
6666 *
6667 * parse a XML schema List definition
6668 * *WARNING* this interface is highly subject to change
6669 *
William M. Bracke7091952004-05-11 15:09:58 +00006670 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00006671 * 1 in case of success.
6672 */
6673static xmlSchemaTypePtr
6674xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006675 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006676{
6677 xmlSchemaTypePtr type, subtype;
6678 xmlNodePtr child = NULL;
6679 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00006680 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006681
6682 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6683 return (NULL);
6684
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006685 snprintf((char *) name, 30, "#list%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00006686 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006687 if (type == NULL)
6688 return (NULL);
6689 type->node = node;
6690 type->type = XML_SCHEMA_TYPE_LIST;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006691 type->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00006692 /*
6693 * Check for illegal attributes.
6694 */
6695 attr = node->properties;
6696 while (attr != NULL) {
6697 if (attr->ns == NULL) {
6698 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6699 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
6700 xmlSchemaPIllegalAttrErr(ctxt,
6701 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6702 NULL, type, attr);
6703 }
6704 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6705 xmlSchemaPIllegalAttrErr(ctxt,
6706 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6707 NULL, type, attr);
6708 }
6709 attr = attr->next;
6710 }
6711 /*
6712 * Attribute "itemType".
6713 */
6714 xmlSchemaPValAttrQName(ctxt, schema, NULL, NULL,
6715 node, "itemType", &(type->baseNs), NULL, &(type->base));
6716 /*
6717 * And now for the children...
6718 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006719 child = node->children;
6720 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006721 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6722 child = child->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00006723 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006724 subtype = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00006725 if (IS_SCHEMA(child, "simpleType")) {
6726 if (type->base != NULL) {
6727 xmlSchemaPCustomErr(ctxt,
6728 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
6729 NULL, type, node,
6730 "The attribute 'itemType' and the <simpleType> child "
6731 "are mutually exclusive", NULL);
6732 } else {
6733 subtype = (xmlSchemaTypePtr)
6734 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
6735 type->subtypes = subtype;
6736 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00006737 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006738 }
6739 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006740 /* TODO: Think about the error code. */
6741 xmlSchemaPContentErr(ctxt,
6742 XML_SCHEMAP_UNKNOWN_LIST_CHILD,
6743 NULL, type, node, child, NULL, "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006744 }
6745 return (type);
6746}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006747
Daniel Veillard4255d502002-04-16 15:50:10 +00006748/**
6749 * xmlSchemaParseSimpleType:
6750 * @ctxt: a schema validation context
6751 * @schema: the schema being built
6752 * @node: a subtree containing XML Schema informations
6753 *
6754 * parse a XML schema Simple Type definition
6755 * *WARNING* this interface is highly subject to change
6756 *
William M. Bracke7091952004-05-11 15:09:58 +00006757 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardc0826a72004-08-10 14:17:33 +00006758 * 1 in case of success.
Daniel Veillard4255d502002-04-16 15:50:10 +00006759 */
6760static xmlSchemaTypePtr
6761xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00006762 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006763{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006764 xmlSchemaTypePtr type, subtype, oldCtxtType, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00006765 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006766 const xmlChar *attrValue = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006767 xmlChar *des = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006768 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006769
6770 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6771 return (NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006772
Daniel Veillardc0826a72004-08-10 14:17:33 +00006773 if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006774 attr = xmlSchemaGetPropNode(node, "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006775 if (attr == NULL) {
6776 xmlSchemaPMissingAttrErr(ctxt,
6777 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006778 (xmlChar **) &xmlSchemaElemDesST, NULL, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006779 "name", NULL);
6780 return (NULL);
6781 } else if (xmlSchemaPValAttrNode(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006782 (xmlChar **) &xmlSchemaElemDesST, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006783 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00006784 return (NULL);
6785 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006786 }
6787
6788 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006789 char buf[40];
Daniel Veillardc0826a72004-08-10 14:17:33 +00006790
Daniel Veillard01fa6152004-06-29 17:04:39 +00006791 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006792 * Parse as local simple type definition.
Daniel Veillard01fa6152004-06-29 17:04:39 +00006793 */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006794 snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00006795 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006796 if (type == NULL)
6797 return (NULL);
6798 type->node = node;
6799 type->type = XML_SCHEMA_TYPE_SIMPLE;
6800 /*
6801 * Check for illegal attributes.
6802 */
6803 attr = node->properties;
6804 while (attr != NULL) {
6805 if (attr->ns == NULL) {
6806 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
6807 xmlSchemaPIllegalAttrErr(ctxt,
6808 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006809 &des, type, attr);
Daniel Veillard01fa6152004-06-29 17:04:39 +00006810 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006811 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6812 xmlSchemaPIllegalAttrErr(ctxt,
6813 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006814 &des, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006815 }
6816 attr = attr->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +00006817 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006818 } else {
6819 /*
6820 * Parse as global simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006821 *
6822 * Note that attrValue is the value of the attribute "name" here.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006823 */
William M. Brack2f2a6632004-08-20 23:09:47 +00006824 type = xmlSchemaAddType(ctxt, schema, attrValue, schema->targetNamespace, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006825 if (type == NULL)
6826 return (NULL);
6827 type->node = node;
6828 type->type = XML_SCHEMA_TYPE_SIMPLE;
6829 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
6830 /*
6831 * Check for illegal attributes.
6832 */
6833 attr = node->properties;
6834 while (attr != NULL) {
6835 if (attr->ns == NULL) {
6836 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6837 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006838 (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006839 xmlSchemaPIllegalAttrErr(ctxt,
6840 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006841 &des, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006842 }
6843 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6844 xmlSchemaPIllegalAttrErr(ctxt,
6845 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006846 &des, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006847 }
6848 attr = attr->next;
6849 }
6850 /*
6851 * Attribute "final".
6852 */
6853 attr = xmlSchemaGetPropNode(node, "final");
6854 if (attr == NULL) {
6855 type->flags |= XML_SCHEMAS_TYPE_FINAL_DEFAULT;
6856 } else {
6857 attrValue = xmlSchemaGetProp(ctxt, node, "final");
6858 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
6859 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
6860 XML_SCHEMAS_TYPE_FINAL_LIST,
6861 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
6862
6863 xmlSchemaPSimpleTypeErr(ctxt,
6864 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006865 &des, type, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00006866 NULL, "(#all | List of (list | union | restriction)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00006867 attrValue, NULL, NULL, NULL);
6868 }
6869 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006870 }
6871 type->targetNamespace = schema->targetNamespace;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006872 /* TODO: Check id. */
6873 type->id = xmlSchemaGetProp(ctxt, node, "id");
6874 /*
6875 * And now for the children...
6876 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006877 oldCtxtType = ctxt->ctxtType;
6878 oldParentItem = ctxt->parentItem;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006879 ctxt->ctxtType = type;
6880 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00006881 child = node->children;
6882 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006883 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6884 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006885 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006886 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00006887 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006888 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00006889 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006890 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006891 } else if (IS_SCHEMA(child, "list")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006892 subtype = (xmlSchemaTypePtr)
6893 xmlSchemaParseList(ctxt, schema, child);
6894 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006895 } else if (IS_SCHEMA(child, "union")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006896 subtype = (xmlSchemaTypePtr)
6897 xmlSchemaParseUnion(ctxt, schema, child);
6898 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006899 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006900 type->subtypes = subtype;
6901 if ((child != NULL) || (subtype == NULL)) {
6902 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006903 &des, type, node, child, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006904 "(annotation?, (restriction | list | union))");
Daniel Veillard4255d502002-04-16 15:50:10 +00006905 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006906 ctxt->parentItem = oldParentItem;
6907 ctxt->ctxtType = oldCtxtType;
6908 FREE_AND_NULL(des)
Daniel Veillard01fa6152004-06-29 17:04:39 +00006909
Daniel Veillard4255d502002-04-16 15:50:10 +00006910 return (type);
6911}
6912
6913
6914/**
6915 * xmlSchemaParseGroup:
6916 * @ctxt: a schema validation context
6917 * @schema: the schema being built
6918 * @node: a subtree containing XML Schema informations
6919 *
6920 * parse a XML schema Group definition
6921 * *WARNING* this interface is highly subject to change
6922 *
William M. Bracke7091952004-05-11 15:09:58 +00006923 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00006924 * 1 in case of success.
6925 */
6926static xmlSchemaTypePtr
6927xmlSchemaParseGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00006928 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006929{
6930 xmlSchemaTypePtr type, subtype;
6931 xmlNodePtr child = NULL;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006932 const xmlChar *name, *ns = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006933 const xmlChar *ref = NULL, *refNs = NULL;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006934 char buf[50];
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00006935 int minOccurs, maxOccurs;
Daniel Veillard4255d502002-04-16 15:50:10 +00006936
6937 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6938 return (NULL);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00006939 /*
6940 * TODO: Validate the element even if no item is created
6941 * (i.e. min/maxOccurs == 0).
6942 */
6943 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
6944 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(nonNegativeInteger | unbounded)");
6945 if ((minOccurs == 0) && (maxOccurs == 0)) {
6946 return (NULL);
6947 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006948 if (topLevel)
6949 ns = schema->targetNamespace;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006950 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00006951 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006952 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
6953 if (ref == NULL) {
6954 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006955 XML_SCHEMAP_GROUP_NONAME_NOREF,
6956 "Group definition or particle: One of the attributes \"name\" "
6957 "or \"ref\" must be present.\n", NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006958 return (NULL);
6959 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006960 if (refNs == NULL)
6961 refNs = schema->targetNamespace;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006962 snprintf(buf, 49, "#grRef%d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006963 name = (const xmlChar *) buf;
Daniel Veillard4255d502002-04-16 15:50:10 +00006964 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006965 type = xmlSchemaAddGroup(ctxt, schema, name, ns, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006966 if (type == NULL)
6967 return (NULL);
6968 type->node = node;
6969 type->type = XML_SCHEMA_TYPE_GROUP;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006970 if (topLevel)
6971 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006972 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00006973 type->ref = ref;
6974 type->refNs = refNs;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00006975 type->minOccurs = minOccurs;
6976 type->maxOccurs = maxOccurs;
6977 xmlSchemaPCheckParticleCorrect_2(ctxt, type,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006978 node, type->minOccurs, type->maxOccurs);
Daniel Veillard4255d502002-04-16 15:50:10 +00006979
6980 child = node->children;
6981 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006982 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6983 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006984 }
6985 subtype = NULL;
6986 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006987 subtype = (xmlSchemaTypePtr)
6988 xmlSchemaParseAll(ctxt, schema, child);
6989 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006990 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006991 subtype = xmlSchemaParseChoice(ctxt, schema, child);
6992 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006993 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006994 subtype = (xmlSchemaTypePtr)
6995 xmlSchemaParseSequence(ctxt, schema, child);
6996 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006997 }
6998 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006999 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00007000 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007001 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_GROUP_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007002 "Group definition \"%s\" has unexpected content.\n", type->name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007003 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007004 }
7005
7006 return (type);
7007}
7008
7009/**
7010 * xmlSchemaParseAll:
7011 * @ctxt: a schema validation context
7012 * @schema: the schema being built
7013 * @node: a subtree containing XML Schema informations
7014 *
7015 * parse a XML schema All definition
7016 * *WARNING* this interface is highly subject to change
7017 *
William M. Bracke7091952004-05-11 15:09:58 +00007018 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00007019 * 1 in case of success.
7020 */
7021static xmlSchemaTypePtr
7022xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007023 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007024{
7025 xmlSchemaTypePtr type, subtype, last = NULL;
7026 xmlNodePtr child = NULL;
7027 xmlChar name[30];
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00007028 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007029
7030 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7031 return (NULL);
7032
7033
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00007034 snprintf((char *) name, 30, "#all%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007035 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007036 if (type == NULL)
7037 return (NULL);
7038 type->node = node;
Daniel Veillard7646b182002-04-20 06:41:40 +00007039 type->type = XML_SCHEMA_TYPE_ALL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007040 type->id = xmlSchemaGetProp(ctxt, node, "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007041
7042 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
7043 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00007044
7045 oldcontainer = ctxt->container;
7046 ctxt->container = (const xmlChar *) name;
Daniel Veillard4255d502002-04-16 15:50:10 +00007047 child = node->children;
7048 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007049 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7050 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007051 }
7052 while (IS_SCHEMA(child, "element")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007053 subtype = (xmlSchemaTypePtr)
7054 xmlSchemaParseElement(ctxt, schema, child, 0);
7055 if (subtype != NULL) {
William M. Brackb15351e2003-12-27 04:34:42 +00007056 if (subtype->minOccurs > 1)
7057 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MINOCCURS,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007058 "invalid value for minOccurs (must be 0 or 1).\n",
William M. Brackb15351e2003-12-27 04:34:42 +00007059 NULL, NULL);
7060 if (subtype->maxOccurs > 1)
7061 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MAXOCCURS,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007062 "invalid value for maxOccurs (must be 0 or 1).\n",
William M. Brackb15351e2003-12-27 04:34:42 +00007063 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007064 if (last == NULL) {
7065 type->subtypes = subtype;
7066 last = subtype;
7067 } else {
7068 last->next = subtype;
7069 last = subtype;
7070 }
7071 last->next = NULL;
7072 }
7073 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007074 }
7075 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007076 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ALL_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007077 "<all> has unexpected content.\n", type->name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007078 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007079 }
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00007080 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007081 return (type);
7082}
7083
7084/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007085 * xmlSchemaCleanupDoc:
7086 * @ctxt: a schema validation context
7087 * @node: the root of the document.
7088 *
7089 * removes unwanted nodes in a schemas document tree
7090 */
7091static void
7092xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
7093{
7094 xmlNodePtr delete, cur;
7095
7096 if ((ctxt == NULL) || (root == NULL)) return;
7097
7098 /*
7099 * Remove all the blank text nodes
7100 */
7101 delete = NULL;
7102 cur = root;
7103 while (cur != NULL) {
7104 if (delete != NULL) {
7105 xmlUnlinkNode(delete);
7106 xmlFreeNode(delete);
7107 delete = NULL;
7108 }
7109 if (cur->type == XML_TEXT_NODE) {
7110 if (IS_BLANK_NODE(cur)) {
7111 if (xmlNodeGetSpacePreserve(cur) != 1) {
7112 delete = cur;
7113 }
7114 }
7115 } else if ((cur->type != XML_ELEMENT_NODE) &&
7116 (cur->type != XML_CDATA_SECTION_NODE)) {
7117 delete = cur;
7118 goto skip_children;
7119 }
7120
7121 /*
7122 * Skip to next node
7123 */
7124 if (cur->children != NULL) {
7125 if ((cur->children->type != XML_ENTITY_DECL) &&
7126 (cur->children->type != XML_ENTITY_REF_NODE) &&
7127 (cur->children->type != XML_ENTITY_NODE)) {
7128 cur = cur->children;
7129 continue;
7130 }
7131 }
7132 skip_children:
7133 if (cur->next != NULL) {
7134 cur = cur->next;
7135 continue;
7136 }
7137
7138 do {
7139 cur = cur->parent;
7140 if (cur == NULL)
7141 break;
7142 if (cur == root) {
7143 cur = NULL;
7144 break;
7145 }
7146 if (cur->next != NULL) {
7147 cur = cur->next;
7148 break;
7149 }
7150 } while (cur != NULL);
7151 }
7152 if (delete != NULL) {
7153 xmlUnlinkNode(delete);
7154 xmlFreeNode(delete);
7155 delete = NULL;
7156 }
7157}
7158
William M. Brack2f2a6632004-08-20 23:09:47 +00007159
7160/**
7161 * xmlSchemaImportSchema
7162 *
7163 * @ctxt: a schema validation context
7164 * @schemaLocation: an URI defining where to find the imported schema
7165 *
7166 * import a XML schema
7167 * *WARNING* this interface is highly subject to change
7168 *
7169 * Returns -1 in case of error and 1 in case of success.
7170 */
7171#if 0
7172static xmlSchemaImportPtr
7173xmlSchemaImportSchema(xmlSchemaParserCtxtPtr ctxt,
7174 const xmlChar *schemaLocation)
7175{
7176 xmlSchemaImportPtr import;
7177 xmlSchemaParserCtxtPtr newctxt;
7178
7179 newctxt = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
7180 if (newctxt == NULL) {
7181 xmlSchemaPErrMemory(ctxt, "allocating schema parser context",
7182 NULL);
7183 return (NULL);
7184 }
7185 memset(newctxt, 0, sizeof(xmlSchemaParserCtxt));
7186 /* Keep the same dictionnary for parsing, really */
7187 xmlDictReference(ctxt->dict);
7188 newctxt->dict = ctxt->dict;
7189 newctxt->includes = 0;
7190 newctxt->URL = xmlDictLookup(newctxt->dict, schemaLocation, -1);
7191
7192 xmlSchemaSetParserErrors(newctxt, ctxt->error, ctxt->warning,
7193 ctxt->userData);
7194
7195 import = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
7196 if (import == NULL) {
7197 xmlSchemaPErrMemory(NULL, "allocating imported schema",
7198 NULL);
7199 xmlSchemaFreeParserCtxt(newctxt);
7200 return (NULL);
7201 }
7202
7203 memset(import, 0, sizeof(xmlSchemaImport));
7204 import->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
7205 import->schema = xmlSchemaParse(newctxt);
7206
7207 if (import->schema == NULL) {
7208 /* FIXME use another error enum here ? */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00007209 xmlSchemaPErr(ctxt, NULL, XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00007210 "Failed to import schema from location \"%s\".\n",
7211 schemaLocation, NULL);
7212
7213 xmlSchemaFreeParserCtxt(newctxt);
7214 /* The schemaLocation is held by the dictionary.
7215 if (import->schemaLocation != NULL)
7216 xmlFree((xmlChar *)import->schemaLocation);
7217 */
7218 xmlFree(import);
7219 return NULL;
7220 }
7221
7222 xmlSchemaFreeParserCtxt(newctxt);
7223 return import;
7224}
7225#endif
7226
7227static void
7228xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
7229{
7230 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
7231 schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
7232
7233 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
7234 schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
7235
7236 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
7237 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
7238 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
7239 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
7240 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
7241 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
7242 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
7243 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
7244
7245 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
7246 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
7247 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
7248 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
7249 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
7250 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
7251}
7252
7253static void
7254xmlSchemaParseSchemaDefaults(xmlSchemaParserCtxtPtr ctxt,
7255 xmlSchemaPtr schema,
7256 xmlNodePtr node)
7257{
7258 xmlAttrPtr attr;
7259 const xmlChar *val;
7260
7261 attr = xmlSchemaGetPropNode(node, "elementFormDefault");
7262 if (attr != NULL) {
7263 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7264 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
7265 XML_SCHEMAS_QUALIF_ELEM) != 0) {
7266 xmlSchemaPSimpleTypeErr(ctxt,
7267 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
7268 NULL, NULL, (xmlNodePtr) attr, NULL,
7269 "(qualified | unqualified)", val, NULL, NULL, NULL);
7270 }
7271 }
7272
7273 attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
7274 if (attr != NULL) {
7275 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7276 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
7277 XML_SCHEMAS_QUALIF_ATTR) != 0) {
7278 xmlSchemaPSimpleTypeErr(ctxt,
7279 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
7280 NULL, NULL, (xmlNodePtr) attr, NULL,
7281 "(qualified | unqualified)", val, NULL, NULL, NULL);
7282 }
7283 }
7284
7285 attr = xmlSchemaGetPropNode(node, "finalDefault");
7286 if (attr != NULL) {
7287 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7288 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
7289 XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
7290 XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
7291 -1,
7292 XML_SCHEMAS_FINAL_DEFAULT_LIST,
7293 XML_SCHEMAS_FINAL_DEFAULT_UNION) != 0) {
7294 xmlSchemaPSimpleTypeErr(ctxt,
7295 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7296 NULL, NULL, (xmlNodePtr) attr, NULL,
7297 "(#all | List of (extension | restriction | list | union))",
7298 val, NULL, NULL, NULL);
7299 }
7300 }
7301
7302 attr = xmlSchemaGetPropNode(node, "blockDefault");
7303 if (attr != NULL) {
7304 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7305 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
7306 XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
7307 XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
7308 XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1) != 0) {
7309 xmlSchemaPSimpleTypeErr(ctxt,
7310 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7311 NULL, NULL, (xmlNodePtr) attr, NULL,
7312 "(#all | List of (extension | restriction | substitution))",
7313 val, NULL, NULL, NULL);
7314 }
7315 }
7316}
7317
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007318/**
7319 * xmlSchemaParseSchemaTopLevel:
7320 * @ctxt: a schema validation context
7321 * @schema: the schemas
7322 * @nodes: the list of top level nodes
7323 *
7324 * Returns the internal XML Schema structure built from the resource or
7325 * NULL in case of error
7326 */
7327static void
7328xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
7329 xmlSchemaPtr schema, xmlNodePtr nodes)
7330{
7331 xmlNodePtr child;
7332 xmlSchemaAnnotPtr annot;
7333
7334 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
7335 return;
7336
7337 child = nodes;
7338 while ((IS_SCHEMA(child, "include")) ||
7339 (IS_SCHEMA(child, "import")) ||
7340 (IS_SCHEMA(child, "redefine")) ||
7341 (IS_SCHEMA(child, "annotation"))) {
7342 if (IS_SCHEMA(child, "annotation")) {
7343 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7344 if (schema->annot == NULL)
7345 schema->annot = annot;
7346 else
7347 xmlSchemaFreeAnnot(annot);
7348 } else if (IS_SCHEMA(child, "import")) {
7349 xmlSchemaParseImport(ctxt, schema, child);
7350 } else if (IS_SCHEMA(child, "include")) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00007351 ctxt->includes++;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007352 xmlSchemaParseInclude(ctxt, schema, child);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00007353 ctxt->includes--;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007354 } else if (IS_SCHEMA(child, "redefine")) {
7355 TODO
7356 }
7357 child = child->next;
7358 }
7359 while (child != NULL) {
7360 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007361 xmlSchemaParseComplexType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007362 child = child->next;
7363 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007364 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007365 child = child->next;
7366 } else if (IS_SCHEMA(child, "element")) {
7367 xmlSchemaParseElement(ctxt, schema, child, 1);
7368 child = child->next;
7369 } else if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00007370 xmlSchemaParseAttribute(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007371 child = child->next;
7372 } else if (IS_SCHEMA(child, "attributeGroup")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007373 xmlSchemaParseAttributeGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007374 child = child->next;
7375 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007376 xmlSchemaParseGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007377 child = child->next;
7378 } else if (IS_SCHEMA(child, "notation")) {
7379 xmlSchemaParseNotation(ctxt, schema, child);
7380 child = child->next;
7381 } else {
7382 xmlSchemaPErr2(ctxt, NULL, child,
7383 XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007384 "Unexpected element \"%s\" as child of <schema>.\n",
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007385 child->name, NULL);
7386 child = child->next;
7387 }
7388 while (IS_SCHEMA(child, "annotation")) {
7389 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7390 if (schema->annot == NULL)
7391 schema->annot = annot;
7392 else
7393 xmlSchemaFreeAnnot(annot);
7394 child = child->next;
7395 }
7396 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00007397 ctxt->parentItem = NULL;
7398 ctxt->ctxtType = NULL;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007399}
7400
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007401static xmlSchemaImportPtr
7402xmlSchemaAddImport(xmlSchemaParserCtxtPtr ctxt,
7403 xmlHashTablePtr *imports,
7404 const xmlChar *nsName)
7405{
7406 xmlSchemaImportPtr ret;
7407
7408 if (*imports == NULL) {
Daniel Veillardb9e2f262005-01-23 23:48:34 +00007409 *imports = xmlHashCreateDict(10, ctxt->dict);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007410 if (*imports == NULL) {
7411 xmlSchemaPCustomErr(ctxt,
7412 XML_SCHEMAP_FAILED_BUILD_IMPORT,
7413 NULL, NULL, (xmlNodePtr) ctxt->doc,
7414 "Internal error: failed to build the import table",
7415 NULL);
7416 return (NULL);
7417 }
7418 }
7419 ret = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
7420 if (ret == NULL) {
7421 xmlSchemaPErrMemory(NULL, "allocating import struct", NULL);
7422 return (NULL);
7423 }
7424 memset(ret, 0, sizeof(xmlSchemaImport));
7425 if (nsName == NULL)
7426 nsName = XML_SCHEMAS_NO_NAMESPACE;
7427 xmlHashAddEntry(*imports, nsName, ret);
7428
7429 return (ret);
7430}
7431
7432static int
7433xmlSchemaAcquireSchemaDoc(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007434 xmlSchemaPtr schema,
7435 xmlNodePtr node,
7436 const xmlChar *nsName,
7437 const xmlChar *location,
7438 xmlDocPtr *doc,
7439 const xmlChar **targetNamespace,
7440 int absolute)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007441{
7442 xmlParserCtxtPtr parserCtxt;
7443 xmlSchemaImportPtr import;
7444 const xmlChar *ns;
7445 xmlNodePtr root;
7446
7447 /*
7448 * NOTE: This will be used for <import>, <xsi:schemaLocation> and
7449 * <xsi:noNamespaceSchemaLocation>.
7450 */
7451 *doc = NULL;
7452 /*
7453 * Given that the schemaLocation [attribute] is only a hint, it is open
7454 * to applications to ignore all but the first <import> for a given
7455 * namespace, regardless of the ·actual value· of schemaLocation, but
7456 * such a strategy risks missing useful information when new
7457 * schemaLocations are offered.
7458 *
7459 * XSV (ver 2.5-2) does use the first <import> which resolves to a valid schema.
7460 * Xerces-J (ver 2.5.1) ignores all but the first given <import> - regardless if
7461 * valid or not.
7462 * We will follow XSV here.
7463 */
7464 if (location == NULL) {
7465 /*
7466 * Schema Document Location Strategy:
7467 *
7468 * 3 Based on the namespace name, identify an existing schema document,
7469 * either as a resource which is an XML document or a <schema> element
7470 * information item, in some local schema repository;
7471 *
7472 * 5 Attempt to resolve the namespace name to locate such a resource.
7473 *
7474 * NOTE: Those stategies are not supported, so we will skip.
7475 */
7476 return (0);
7477 }
7478 if (nsName == NULL)
7479 ns = XML_SCHEMAS_NO_NAMESPACE;
7480 else
7481 ns = nsName;
7482
7483 import = xmlHashLookup(schema->schemasImports, ns);
7484 if (import != NULL) {
7485 /*
7486 * There was a valid resource for the specified namespace already
7487 * defined, so skip.
7488 * TODO: This might be changed someday to allow import of
7489 * components from multiple documents for a single target namespace.
7490 */
7491 return (0);
7492 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007493
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007494 /*
7495 * Schema Document Location Strategy:
7496 *
7497 * 2 Based on the location URI, identify an existing schema document,
7498 * either as a resource which is an XML document or a <schema> element
7499 * information item, in some local schema repository;
7500 *
7501 * 4 Attempt to resolve the location URI, to locate a resource on the
7502 * web which is or contains or references a <schema> element;
7503 * TODO: Hmm, I don't know if the reference stuff in 4. will work.
7504 *
7505 */
7506 if ((absolute == 0) && (node != NULL)) {
7507 xmlChar *base, *URI;
7508
7509 base = xmlNodeGetBase(node->doc, node);
7510 if (base == NULL) {
7511 URI = xmlBuildURI(location, node->doc->URL);
7512 } else {
7513 URI = xmlBuildURI(location, base);
7514 xmlFree(base);
7515 }
7516 if (URI != NULL) {
7517 location = xmlDictLookup(ctxt->dict, URI, -1);
7518 xmlFree(URI);
7519 }
7520 }
7521 parserCtxt = xmlNewParserCtxt();
7522 if (parserCtxt == NULL) {
7523 xmlSchemaPErrMemory(NULL, "xmlSchemaParseImport: "
7524 "allocating a parser context", NULL);
7525 return(-1);
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00007526 }
7527
7528 if ((ctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
7529 xmlDictFree(parserCtxt->dict);
7530 parserCtxt->dict = ctxt->dict;
7531 xmlDictReference(parserCtxt->dict);
7532 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007533
7534 *doc = xmlCtxtReadFile(parserCtxt, (const char *) location,
7535 NULL, SCHEMAS_PARSE_OPTIONS);
7536
7537 /*
7538 * 2.1 The referent is (a fragment of) a resource which is an
7539 * XML document (see clause 1.1), which in turn corresponds to
7540 * a <schema> element information item in a well-formed information
7541 * set, which in turn corresponds to a valid schema.
7542 * TODO: What to do with the "fragment" stuff?
7543 *
7544 * 2.2 The referent is a <schema> element information item in
7545 * a well-formed information set, which in turn corresponds
7546 * to a valid schema.
7547 * NOTE: 2.2 won't apply, since only XML documents will be processed
7548 * here.
7549 */
7550 if (*doc == NULL) {
7551 xmlErrorPtr lerr;
7552 /*
7553 * It is *not* an error for the application schema reference
7554 * strategy to fail.
7555 *
7556 * If the doc is NULL and the parser error is an IO error we
7557 * will assume that the resource could not be located or accessed.
7558 *
7559 * TODO: Try to find specific error codes to react only on
7560 * localisation failures.
7561 *
7562 * TODO, FIXME: Check the spec: is a namespace added to the imported
7563 * namespaces, even if the schemaLocation did not provide
7564 * a resource? I guess so, since omitting the "schemaLocation"
7565 * attribute, imports a namespace as well.
7566 */
7567 lerr = xmlGetLastError();
7568 if ((lerr != NULL) && (lerr->domain == XML_FROM_IO)) {
7569 xmlFreeParserCtxt(parserCtxt);
7570 return(0);
7571 }
7572
7573 xmlSchemaPCustomErr(ctxt,
7574 XML_SCHEMAP_SRC_IMPORT_2_1,
7575 NULL, NULL, node,
7576 "Failed to parse the resource '%s' for import",
7577 location);
7578 xmlFreeParserCtxt(parserCtxt);
7579 return(XML_SCHEMAP_SRC_IMPORT_2_1);
7580 }
7581 xmlFreeParserCtxt(parserCtxt);
7582
7583 root = xmlDocGetRootElement(*doc);
7584 if (root == NULL) {
7585 xmlSchemaPCustomErr(ctxt,
7586 XML_SCHEMAP_SRC_IMPORT_2_1,
7587 NULL, NULL, node,
7588 "The XML document '%s' to be imported has no document "
7589 "element", location);
7590 xmlFreeDoc(*doc);
7591 *doc = NULL;
7592 return (XML_SCHEMAP_SRC_IMPORT_2_1);
7593 }
7594
7595 xmlSchemaCleanupDoc(ctxt, root);
7596
7597 if (!IS_SCHEMA(root, "schema")) {
7598 xmlSchemaPCustomErr(ctxt,
7599 XML_SCHEMAP_SRC_IMPORT_2_1,
7600 NULL, NULL, node,
7601 "The XML document '%s' to be imported is not a XML schema document",
7602 location);
7603 xmlFreeDoc(*doc);
7604 *doc = NULL;
7605 return (XML_SCHEMAP_SRC_IMPORT_2_1);
7606 }
7607 *targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
7608 /*
7609 * Schema Representation Constraint: Import Constraints and Semantics
7610 */
7611 if (nsName == NULL) {
7612 if (*targetNamespace != NULL) {
7613 xmlSchemaPCustomErr(ctxt,
7614 XML_SCHEMAP_SRC_IMPORT_3_2,
7615 NULL, NULL, node,
7616 "The XML schema to be imported is not expected "
7617 "to have a target namespace; this differs from "
7618 "its target namespace of '%s'", *targetNamespace);
7619 xmlFreeDoc(*doc);
7620 *doc = NULL;
7621 return (XML_SCHEMAP_SRC_IMPORT_3_2);
7622 }
7623 } else {
7624 if (*targetNamespace == NULL) {
7625 xmlSchemaPCustomErr(ctxt,
7626 XML_SCHEMAP_SRC_IMPORT_3_1,
7627 NULL, NULL, node,
7628 "The XML schema to be imported is expected to have a target "
7629 "namespace of '%s'", nsName);
7630 xmlFreeDoc(*doc);
7631 *doc = NULL;
7632 return (XML_SCHEMAP_SRC_IMPORT_3_1);
7633 } else if (!xmlStrEqual(*targetNamespace, nsName)) {
7634 xmlSchemaPCustomErrExt(ctxt,
7635 XML_SCHEMAP_SRC_IMPORT_3_1,
7636 NULL, NULL, node,
7637 "The XML schema to be imported is expected to have a "
7638 "target namespace of '%s'; this differs from "
7639 "its target namespace of '%s'",
7640 nsName, *targetNamespace, NULL);
7641 xmlFreeDoc(*doc);
7642 *doc = NULL;
7643 return (XML_SCHEMAP_SRC_IMPORT_3_1);
7644 }
7645 }
7646
7647 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports), nsName);
7648 if (import == NULL) {
7649 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT,
7650 NULL, NULL, NULL,
7651 "Internal error: xmlSchemaAcquireSchemaDoc, "
7652 "failed to build import table", NULL);
7653 xmlFreeDoc(*doc);
7654 *doc = NULL;
7655 return (-1);
7656 }
7657 import->schemaLocation = location;
7658 import->doc = *doc;
7659 return (0);
7660}
William M. Brack2f2a6632004-08-20 23:09:47 +00007661
7662/**
7663 * xmlSchemaParseImport:
7664 * @ctxt: a schema validation context
7665 * @schema: the schema being built
7666 * @node: a subtree containing XML Schema informations
7667 *
7668 * parse a XML schema Import definition
7669 * *WARNING* this interface is highly subject to change
7670 *
7671 * Returns 0 in case of success, a positive error code if
7672 * not valid and -1 in case of an internal error.
7673 */
7674static int
7675xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
7676 xmlNodePtr node)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007677{
7678 xmlNodePtr child;
7679 const xmlChar *namespace = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00007680 const xmlChar *schemaLocation = NULL;
7681 const xmlChar *targetNamespace, *oldTNS, *url;
7682 xmlAttrPtr attr;
7683 xmlDocPtr doc;
7684 xmlNodePtr root;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007685 int flags, ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00007686
7687
7688 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7689 return (-1);
7690
7691 /*
7692 * Check for illegal attributes.
7693 */
7694 attr = node->properties;
7695 while (attr != NULL) {
7696 if (attr->ns == NULL) {
7697 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7698 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
7699 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
7700 xmlSchemaPIllegalAttrErr(ctxt,
7701 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7702 NULL, NULL, attr);
7703 }
7704 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7705 xmlSchemaPIllegalAttrErr(ctxt,
7706 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7707 NULL, NULL, attr);
7708 }
7709 attr = attr->next;
7710 }
7711 /*
7712 * Extract and validate attributes.
7713 */
7714 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
7715 "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
7716 &namespace) != 0) {
7717 xmlSchemaPSimpleTypeErr(ctxt,
7718 XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI,
7719 NULL, NULL, node,
7720 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
7721 NULL, namespace, NULL, NULL, NULL);
7722 return (XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI);
7723 }
7724
7725 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
7726 "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
7727 &schemaLocation) != 0) {
7728 xmlSchemaPSimpleTypeErr(ctxt,
7729 XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI,
7730 NULL, NULL, node,
7731 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
7732 NULL, namespace, NULL, NULL, NULL);
7733 return (XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI);
7734 }
7735 /*
7736 * And now for the children...
7737 */
7738 child = node->children;
7739 if (IS_SCHEMA(child, "annotation")) {
7740 /*
7741 * the annotation here is simply discarded ...
7742 */
7743 child = child->next;
7744 }
7745 if (child != NULL) {
7746 xmlSchemaPContentErr(ctxt,
7747 XML_SCHEMAP_UNKNOWN_IMPORT_CHILD,
7748 NULL, NULL, node, child, NULL,
7749 "(annotation?)");
7750 }
7751 /*
7752 * Apply additional constraints.
7753 */
7754 if (namespace != NULL) {
7755 /*
7756 * 1.1 If the namespace [attribute] is present, then its ·actual value·
7757 * must not match the ·actual value· of the enclosing <schema>'s
7758 * targetNamespace [attribute].
7759 */
7760 if (xmlStrEqual(schema->targetNamespace, namespace)) {
7761 xmlSchemaPCustomErr(ctxt,
7762 XML_SCHEMAP_SRC_IMPORT_1_1,
7763 NULL, NULL, node,
7764 "The value of the attribute 'namespace' must not match "
7765 "the target namespace '%s' of the importing schema",
7766 schema->targetNamespace);
7767 return (XML_SCHEMAP_SRC_IMPORT_1_1);
7768 }
7769 } else {
7770 /*
7771 * 1.2 If the namespace [attribute] is not present, then the enclosing
7772 * <schema> must have a targetNamespace [attribute].
7773 */
7774 if (schema->targetNamespace == NULL) {
7775 xmlSchemaPCustomErr(ctxt,
7776 XML_SCHEMAP_SRC_IMPORT_1_2,
7777 NULL, NULL, node,
7778 "The attribute 'namespace' must be existent if "
7779 "the importing schema has no target namespace",
7780 NULL);
7781 return (XML_SCHEMAP_SRC_IMPORT_1_2);
7782 }
7783 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007784 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007785 * Locate and aquire the schema document.
William M. Brack2f2a6632004-08-20 23:09:47 +00007786 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007787 ret = xmlSchemaAcquireSchemaDoc(ctxt, schema, node, namespace,
7788 schemaLocation, &doc, &targetNamespace, 0);
7789 if (ret != 0) {
7790 if (doc != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00007791 xmlFreeDoc(doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007792 return (ret);
7793 } else if (doc != NULL) {
7794 /*
7795 * Save and reset the context & schema.
7796 */
7797 url = ctxt->URL;
7798 /* TODO: Is using the doc->URL here correct? */
7799 ctxt->URL = doc->URL;
7800 flags = schema->flags;
7801 oldTNS = schema->targetNamespace;
7802 /*
7803 * Parse the schema.
7804 */
7805 root = xmlDocGetRootElement(doc);
7806 xmlSchemaClearSchemaDefaults(schema);
7807 xmlSchemaParseSchemaDefaults(ctxt, schema, root);
7808 schema->targetNamespace = targetNamespace;
7809 xmlSchemaParseSchemaTopLevel(ctxt, schema, root->children);
7810 /*
7811 * Restore the context & schema.
7812 */
7813 schema->flags = flags;
7814 schema->targetNamespace = oldTNS;
7815 ctxt->URL = url;
William M. Brack2f2a6632004-08-20 23:09:47 +00007816 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007817
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007818 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +00007819}
7820
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007821/**
7822 * xmlSchemaParseInclude:
7823 * @ctxt: a schema validation context
7824 * @schema: the schema being built
7825 * @node: a subtree containing XML Schema informations
7826 *
7827 * parse a XML schema Include definition
7828 *
William M. Bracke7091952004-05-11 15:09:58 +00007829 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007830 * 1 in case of success.
7831 */
7832static int
7833xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
7834 xmlNodePtr node)
7835{
7836 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007837 const xmlChar *schemaLocation, *targetNamespace;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007838 xmlDocPtr doc;
7839 xmlNodePtr root;
7840 xmlSchemaIncludePtr include;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007841 int wasConvertingNs = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00007842 xmlAttrPtr attr;
7843 int saveFlags;
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00007844 xmlParserCtxtPtr parserCtxt;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007845
7846
7847 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7848 return (-1);
7849
7850 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00007851 * Check for illegal attributes.
7852 */
7853 attr = node->properties;
7854 while (attr != NULL) {
7855 if (attr->ns == NULL) {
7856 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7857 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
7858 xmlSchemaPIllegalAttrErr(ctxt,
7859 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7860 NULL, NULL, attr);
7861 }
7862 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7863 xmlSchemaPIllegalAttrErr(ctxt,
7864 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7865 NULL, NULL, attr);
7866 }
7867 attr = attr->next;
7868 }
7869 /*
7870 * Extract and validate attributes.
7871 */
7872 /*
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007873 * Preliminary step, extract the URI-Reference for the include and
7874 * make an URI from the base.
7875 */
William M. Brack2f2a6632004-08-20 23:09:47 +00007876 attr = xmlSchemaGetPropNode(node, "schemaLocation");
7877 if (attr != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007878 xmlChar *base = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00007879 xmlChar *uri = NULL;
7880
7881 if (xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
7882 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &schemaLocation) != 0)
7883 return (-1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007884 base = xmlNodeGetBase(node->doc, node);
7885 if (base == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007886 uri = xmlBuildURI(schemaLocation, node->doc->URL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007887 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00007888 uri = xmlBuildURI(schemaLocation, base);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007889 xmlFree(base);
7890 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007891 if (uri != NULL) {
7892 schemaLocation = xmlDictLookup(ctxt->dict, uri, -1);
7893 xmlFree(uri);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007894 }
7895 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00007896 xmlSchemaPMissingAttrErr(ctxt,
7897 XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI,
7898 NULL, NULL, node, "schemaLocation", NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007899 return (-1);
7900 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007901 /*
7902 * And now for the children...
7903 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007904 child = node->children;
7905 while (IS_SCHEMA(child, "annotation")) {
7906 /*
7907 * the annotations here are simply discarded ...
7908 */
7909 child = child->next;
7910 }
7911 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007912 xmlSchemaPContentErr(ctxt,
7913 XML_SCHEMAP_UNKNOWN_INCLUDE_CHILD,
7914 NULL, NULL, node, child, NULL,
7915 "(annotation?)");
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007916 }
7917
7918 /*
7919 * First step is to parse the input document into an DOM/Infoset
7920 */
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00007921 /*
7922 * TODO: Use xmlCtxtReadFile to share the dictionary.
7923 */
7924 parserCtxt = xmlNewParserCtxt();
7925 if (parserCtxt == NULL) {
7926 xmlSchemaPErrMemory(NULL, "xmlSchemaParseInclude: "
7927 "allocating a parser context", NULL);
7928 return(-1);
7929 }
7930
7931 if ((ctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
7932 xmlDictFree(parserCtxt->dict);
7933 parserCtxt->dict = ctxt->dict;
7934 xmlDictReference(parserCtxt->dict);
7935 }
7936
7937 doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
7938 NULL, SCHEMAS_PARSE_OPTIONS);
7939 xmlFreeParserCtxt(parserCtxt);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007940 if (doc == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007941 /*
7942 * TODO: It is not an error for the ·actual value· of the
7943 * schemaLocation [attribute] to fail to resolve it all, in which
7944 * case no corresponding inclusion is performed.
7945 * So do we need a warning report here?
7946 */
7947 xmlSchemaPCustomErr(ctxt,
7948 XML_SCHEMAP_FAILED_LOAD,
7949 NULL, NULL, node,
7950 "Failed to load the document '%s' for inclusion", schemaLocation);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007951 return(-1);
7952 }
7953
7954 /*
7955 * Then extract the root of the schema
7956 */
7957 root = xmlDocGetRootElement(doc);
7958 if (root == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007959 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007960 XML_SCHEMAP_NOROOT,
William M. Brack2f2a6632004-08-20 23:09:47 +00007961 NULL, NULL, node,
7962 "The included document '%s' has no document "
7963 "element", schemaLocation);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007964 xmlFreeDoc(doc);
7965 return (-1);
7966 }
7967
7968 /*
7969 * Remove all the blank text nodes
7970 */
7971 xmlSchemaCleanupDoc(ctxt, root);
7972
7973 /*
7974 * Check the schemas top level element
7975 */
7976 if (!IS_SCHEMA(root, "schema")) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007977 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007978 XML_SCHEMAP_NOT_SCHEMA,
William M. Brack2f2a6632004-08-20 23:09:47 +00007979 NULL, NULL, node,
7980 "The document '%s' to be included is not a schema document",
7981 schemaLocation);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007982 xmlFreeDoc(doc);
7983 return (-1);
7984 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007985
William M. Brack2f2a6632004-08-20 23:09:47 +00007986 targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007987 /*
7988 * 2.1 SII has a targetNamespace [attribute], and its ·actual
7989 * value· is identical to the ·actual value· of the targetNamespace
7990 * [attribute] of SIIÂ’ (which must have such an [attribute]).
7991 */
7992 if (targetNamespace != NULL) {
7993 if (schema->targetNamespace == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007994 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007995 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00007996 NULL, NULL, node,
7997 "The target namespace of the included schema "
7998 "'%s' has to be absent, since the including schema "
7999 "has no target namespace",
8000 schemaLocation);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008001 xmlFreeDoc(doc);
8002 return (-1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008003 } else if (!xmlStrEqual(targetNamespace, schema->targetNamespace)) {
8004 xmlSchemaPCustomErrExt(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008005 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00008006 NULL, NULL, node,
8007 "The target namespace '%s' of the included schema '%s' "
8008 "differs from '%s' of the including schema",
8009 targetNamespace, schemaLocation, schema->targetNamespace);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008010 xmlFreeDoc(doc);
8011 return (-1);
8012 }
8013 } else if (schema->targetNamespace != NULL) {
8014 if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
8015 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
8016 } else
8017 wasConvertingNs = 1;
8018 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008019 /*
8020 * register the include
8021 */
8022 include = (xmlSchemaIncludePtr) xmlMalloc(sizeof(xmlSchemaInclude));
8023 if (include == NULL) {
8024 xmlSchemaPErrMemory(ctxt, "allocating included schema", NULL);
8025 xmlFreeDoc(doc);
8026 return (-1);
8027 }
8028
8029 memset(include, 0, sizeof(xmlSchemaInclude));
8030 include->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
8031 include->doc = doc;
8032 include->next = schema->includes;
8033 schema->includes = include;
8034
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008035 /*
8036 * parse the declarations in the included file like if they
8037 * were in the original file.
Daniel Veillardc0826a72004-08-10 14:17:33 +00008038 */
8039 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00008040 * TODO: The complete validation of the <schema> element is not done.
Daniel Veillardc0826a72004-08-10 14:17:33 +00008041 */
William M. Brack2f2a6632004-08-20 23:09:47 +00008042 /*
8043 * The default values ("blockDefault", "elementFormDefault", etc.)
8044 * are set to the values of the included schema and restored afterwards.
8045 */
8046 saveFlags = schema->flags;
8047 xmlSchemaClearSchemaDefaults(schema);
8048 xmlSchemaParseSchemaDefaults(ctxt, schema, root);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008049 xmlSchemaParseSchemaTopLevel(ctxt, schema, root->children);
William M. Brack2f2a6632004-08-20 23:09:47 +00008050 schema->flags = saveFlags;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008051 /*
8052 * Remove the converting flag.
8053 */
William M. Brack2f2a6632004-08-20 23:09:47 +00008054 if ((wasConvertingNs == 0) &&
8055 (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS))
Daniel Veillardc0826a72004-08-10 14:17:33 +00008056 schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008057 return (1);
8058}
8059
8060/**
Daniel Veillard4255d502002-04-16 15:50:10 +00008061 * xmlSchemaParseChoice:
8062 * @ctxt: a schema validation context
8063 * @schema: the schema being built
8064 * @node: a subtree containing XML Schema informations
8065 *
8066 * parse a XML schema Choice definition
8067 * *WARNING* this interface is highly subject to change
8068 *
William M. Bracke7091952004-05-11 15:09:58 +00008069 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00008070 * 1 in case of success.
8071 */
8072static xmlSchemaTypePtr
8073xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008074 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008075{
8076 xmlSchemaTypePtr type, subtype, last = NULL;
8077 xmlNodePtr child = NULL;
8078 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00008079 xmlAttrPtr attr;
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00008080 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00008081
8082 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8083 return (NULL);
8084
8085
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008086 snprintf((char *) name, 30, "#ch%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008087 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00008088 if (type == NULL)
8089 return (NULL);
8090 type->node = node;
8091 type->type = XML_SCHEMA_TYPE_CHOICE;
William M. Brack2f2a6632004-08-20 23:09:47 +00008092 /*
8093 * Check for illegal attributes.
8094 */
8095 attr = node->properties;
8096 while (attr != NULL) {
8097 if (attr->ns == NULL) {
8098 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8099 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
8100 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
8101 xmlSchemaPIllegalAttrErr(ctxt,
8102 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8103 NULL, type, attr);
8104 }
8105 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8106 xmlSchemaPIllegalAttrErr(ctxt,
8107 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8108 NULL, type, attr);
8109 }
8110 attr = attr->next;
8111 }
8112 /*
8113 * Extract and validate attributes.
8114 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008115 type->id = xmlSchemaGetProp(ctxt, node, "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008116 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
8117 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
8118 "(nonNegativeInteger | unbounded)");
William M. Brack2f2a6632004-08-20 23:09:47 +00008119 /*
8120 * And now for the children...
8121 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00008122 oldcontainer = ctxt->container;
8123 ctxt->container = (const xmlChar *) name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008124 child = node->children;
8125 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008126 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8127 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008128 }
8129 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008130 (IS_SCHEMA(child, "group")) ||
8131 (IS_SCHEMA(child, "any")) ||
8132 (IS_SCHEMA(child, "choice")) ||
8133 (IS_SCHEMA(child, "sequence"))) {
8134 subtype = NULL;
8135 if (IS_SCHEMA(child, "element")) {
8136 subtype = (xmlSchemaTypePtr)
8137 xmlSchemaParseElement(ctxt, schema, child, 0);
8138 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008139 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008140 } else if (IS_SCHEMA(child, "any")) {
8141 subtype = xmlSchemaParseAny(ctxt, schema, child);
8142 } else if (IS_SCHEMA(child, "sequence")) {
8143 subtype = xmlSchemaParseSequence(ctxt, schema, child);
8144 } else if (IS_SCHEMA(child, "choice")) {
8145 subtype = xmlSchemaParseChoice(ctxt, schema, child);
8146 }
8147 if (subtype != NULL) {
8148 if (last == NULL) {
8149 type->subtypes = subtype;
8150 last = subtype;
8151 } else {
8152 last->next = subtype;
8153 last = subtype;
8154 }
8155 last->next = NULL;
8156 }
8157 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008158 }
8159 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008160 /* TODO: error code. */
8161 xmlSchemaPContentErr(ctxt,
8162 XML_SCHEMAP_UNKNOWN_CHOICE_CHILD,
8163 NULL, type, node, child, NULL,
8164 "(annotation?, (element | group | choice | sequence | any)*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00008165 }
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00008166 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00008167 return (type);
8168}
8169
8170/**
8171 * xmlSchemaParseSequence:
8172 * @ctxt: a schema validation context
8173 * @schema: the schema being built
8174 * @node: a subtree containing XML Schema informations
8175 *
8176 * parse a XML schema Sequence definition
8177 * *WARNING* this interface is highly subject to change
8178 *
William M. Bracke7091952004-05-11 15:09:58 +00008179 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00008180 * 1 in case of success.
8181 */
8182static xmlSchemaTypePtr
8183xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008184 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008185{
8186 xmlSchemaTypePtr type, subtype, last = NULL;
8187 xmlNodePtr child = NULL;
8188 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00008189 xmlAttrPtr attr;
8190 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00008191
8192 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8193 return (NULL);
8194
William M. Brack2f2a6632004-08-20 23:09:47 +00008195 oldcontainer = ctxt->container;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008196 snprintf((char *) name, 30, "#seq%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008197 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00008198 if (type == NULL)
8199 return (NULL);
8200 type->node = node;
8201 type->type = XML_SCHEMA_TYPE_SEQUENCE;
William M. Brack2f2a6632004-08-20 23:09:47 +00008202 /*
8203 * Check for illegal attributes.
8204 */
8205 attr = node->properties;
8206 while (attr != NULL) {
8207 if (attr->ns == NULL) {
8208 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8209 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
8210 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
8211 xmlSchemaPIllegalAttrErr(ctxt,
8212 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8213 NULL, type, attr);
8214 }
8215 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8216 xmlSchemaPIllegalAttrErr(ctxt,
8217 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8218 NULL, type, attr);
8219 }
8220 attr = attr->next;
8221 }
8222 /*
8223 * Extract and validate attributes.
8224 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008225 type->id = xmlSchemaGetProp(ctxt, node, "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008226 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
8227 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
8228 "(nonNegativeInteger | unbounded)");
William M. Brack2f2a6632004-08-20 23:09:47 +00008229 /*
8230 * And now for the children...
8231 */
8232 ctxt->container = (const xmlChar *) name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008233 child = node->children;
8234 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008235 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8236 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008237 }
8238 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008239 (IS_SCHEMA(child, "group")) ||
8240 (IS_SCHEMA(child, "any")) ||
8241 (IS_SCHEMA(child, "choice")) ||
8242 (IS_SCHEMA(child, "sequence"))) {
8243 subtype = NULL;
8244 if (IS_SCHEMA(child, "element")) {
8245 subtype = (xmlSchemaTypePtr)
8246 xmlSchemaParseElement(ctxt, schema, child, 0);
8247 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008248 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008249 } else if (IS_SCHEMA(child, "any")) {
8250 subtype = xmlSchemaParseAny(ctxt, schema, child);
8251 } else if (IS_SCHEMA(child, "choice")) {
8252 subtype = xmlSchemaParseChoice(ctxt, schema, child);
8253 } else if (IS_SCHEMA(child, "sequence")) {
8254 subtype = xmlSchemaParseSequence(ctxt, schema, child);
8255 }
8256 if (subtype != NULL) {
8257 if (last == NULL) {
8258 type->subtypes = subtype;
8259 last = subtype;
8260 } else {
8261 last->next = subtype;
8262 last = subtype;
8263 }
8264 last->next = NULL;
8265 }
8266 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008267 }
8268 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008269 xmlSchemaPContentErr(ctxt,
8270 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
8271 NULL, type, node, child, NULL,
8272 "(annotation?, (element | group | choice | sequence | any)*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00008273 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008274 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00008275
8276 return (type);
8277}
8278
8279/**
8280 * xmlSchemaParseRestriction:
8281 * @ctxt: a schema validation context
8282 * @schema: the schema being built
8283 * @node: a subtree containing XML Schema informations
Daniel Veillard4255d502002-04-16 15:50:10 +00008284 *
8285 * parse a XML schema Restriction definition
8286 * *WARNING* this interface is highly subject to change
8287 *
8288 * Returns the type definition or NULL in case of error
8289 */
8290static xmlSchemaTypePtr
8291xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00008292 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008293{
Daniel Veillard01fa6152004-06-29 17:04:39 +00008294 xmlSchemaTypePtr type, subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00008295 xmlNodePtr child = NULL;
8296 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008297 const xmlChar *oldcontainer;
William M. Brack2f2a6632004-08-20 23:09:47 +00008298 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00008299
8300 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8301 return (NULL);
8302
8303 oldcontainer = ctxt->container;
8304
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008305 snprintf((char *) name, 30, "#restr%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008306 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00008307 if (type == NULL)
8308 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00008309 type->type = XML_SCHEMA_TYPE_RESTRICTION;
Daniel Veillard4255d502002-04-16 15:50:10 +00008310 type->node = node;
William M. Brack2f2a6632004-08-20 23:09:47 +00008311 /*
8312 * Check for illegal attributes.
8313 */
8314 attr = node->properties;
8315 while (attr != NULL) {
8316 if (attr->ns == NULL) {
8317 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8318 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
8319 xmlSchemaPIllegalAttrErr(ctxt,
8320 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8321 NULL, type, attr);
8322 }
8323 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8324 xmlSchemaPIllegalAttrErr(ctxt,
8325 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8326 NULL, type, attr);
8327 }
8328 attr = attr->next;
8329 }
8330 /*
8331 * Extract and validate attributes.
8332 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008333 type->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00008334 /*
8335 * Attribute "base".
8336 */
Daniel Veillard4255d502002-04-16 15:50:10 +00008337 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
Daniel Veillard01fa6152004-06-29 17:04:39 +00008338 if ((type->base == NULL) &&
William M. Brack2f2a6632004-08-20 23:09:47 +00008339 (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX)) {
8340 /* TODO: Think about the error code. */
8341 xmlSchemaPMissingAttrErr(ctxt,
8342 XML_SCHEMAP_RESTRICTION_NONAME_NOREF,
8343 NULL, type, node, "base", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008344 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008345 /*
8346 * And now for the children...
8347 */
Daniel Veillard4255d502002-04-16 15:50:10 +00008348 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008349 child = node->children;
8350 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008351 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8352 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008353 }
8354 subtype = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008355 if (ctxt->parentItem->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
8356 if (IS_SCHEMA(child, "all")) {
8357 subtype = (xmlSchemaTypePtr)
8358 xmlSchemaParseAll(ctxt, schema, child);
8359 child = child->next;
8360 type->subtypes = subtype;
8361 } else if (IS_SCHEMA(child, "choice")) {
8362 subtype = xmlSchemaParseChoice(ctxt, schema, child);
8363 child = child->next;
8364 type->subtypes = subtype;
8365 } else if (IS_SCHEMA(child, "sequence")) {
8366 subtype = (xmlSchemaTypePtr)
8367 xmlSchemaParseSequence(ctxt, schema, child);
8368 child = child->next;
8369 type->subtypes = subtype;
8370 } else if (IS_SCHEMA(child, "group")) {
8371 subtype = (xmlSchemaTypePtr)
8372 xmlSchemaParseGroup(ctxt, schema, child, 0);
8373 child = child->next;
8374 type->subtypes = subtype;
8375 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008376 } else if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_SIMPLE) {
8377 if (IS_SCHEMA(child, "simpleType")) {
8378 if (type->base != NULL) {
8379 /*
8380 * src-restriction-base-or-simpleType
8381 * Either the base [attribute] or the simpleType [child] of the
8382 * <restriction> element must be present, but not both.
8383 */
8384 xmlSchemaPContentErr(ctxt,
8385 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
8386 NULL, NULL, type->node, child,
8387 "The attribute 'base' and the <simpleType> child are "
8388 "mutually exclusive", NULL);
8389 } else {
8390 subtype = (xmlSchemaTypePtr)
8391 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
8392 type->baseType = subtype;
8393 }
8394 child = child->next;
8395 }
8396 } else if (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00008397 if (IS_SCHEMA(child, "simpleType")) {
8398 subtype = (xmlSchemaTypePtr)
8399 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008400 type->subtypes = subtype;
8401 child = child->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00008402 }
8403 }
8404 if ((ctxt->ctxtType->type == XML_SCHEMA_TYPE_SIMPLE) ||
8405 (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
8406 xmlSchemaFacetPtr facet, lastfacet = NULL;
8407
Daniel Veillard01fa6152004-06-29 17:04:39 +00008408 /*
8409 * Add the facets to the parent simpleType/complexType.
8410 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00008411 /*
8412 * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
8413 * Simple Type Definition Schema Representation Constraint:
8414 * *Single Facet Value*
8415 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00008416 while ((IS_SCHEMA(child, "minInclusive")) ||
8417 (IS_SCHEMA(child, "minExclusive")) ||
8418 (IS_SCHEMA(child, "maxInclusive")) ||
8419 (IS_SCHEMA(child, "maxExclusive")) ||
8420 (IS_SCHEMA(child, "totalDigits")) ||
8421 (IS_SCHEMA(child, "fractionDigits")) ||
8422 (IS_SCHEMA(child, "pattern")) ||
8423 (IS_SCHEMA(child, "enumeration")) ||
8424 (IS_SCHEMA(child, "whiteSpace")) ||
8425 (IS_SCHEMA(child, "length")) ||
8426 (IS_SCHEMA(child, "maxLength")) ||
8427 (IS_SCHEMA(child, "minLength"))) {
8428 facet = xmlSchemaParseFacet(ctxt, schema, child);
8429 if (facet != NULL) {
8430 if (lastfacet == NULL)
8431 ctxt->ctxtType->facets = facet;
8432 else
8433 lastfacet->next = facet;
8434 lastfacet = facet;
8435 lastfacet->next = NULL;
8436 }
8437 child = child->next;
8438 }
8439 /*
8440 * Create links for derivation and validation.
8441 */
8442 if (lastfacet != NULL) {
8443 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
8444
8445 facet = ctxt->ctxtType->facets;
8446 do {
8447 facetLink = (xmlSchemaFacetLinkPtr) xmlMalloc(sizeof(xmlSchemaFacetLink));
8448 if (facetLink == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008449 xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008450 xmlFree(facetLink);
8451 return (NULL);
8452 }
8453 facetLink->facet = facet;
8454 facetLink->next = NULL;
8455 if (lastFacetLink == NULL)
8456 ctxt->ctxtType->facetSet = facetLink;
8457 else
8458 lastFacetLink->next = facetLink;
8459 lastFacetLink = facetLink;
8460 facet = facet->next;
8461 } while (facet != NULL);
8462 }
8463 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008464 if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX) {
8465 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
8466 if (IS_SCHEMA(child, "anyAttribute")) {
8467 ctxt->ctxtType->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
8468 child = child->next;
8469 }
8470 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008471 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008472 /* TODO: Think about the error code. */
8473 if (ctxt->parentItem->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
8474 xmlSchemaPContentErr(ctxt,
8475 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
8476 NULL, type, node, child, NULL,
8477 "annotation?, (group | all | choice | sequence)?, "
8478 "((attribute | attributeGroup)*, anyAttribute?))");
8479 } else if (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
8480 xmlSchemaPContentErr(ctxt,
8481 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
8482 NULL, type, node, child, NULL,
8483 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
8484 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
8485 "length | minLength | maxLength | enumeration | whiteSpace | "
8486 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
8487 } else {
8488 /* Simple type */
8489 xmlSchemaPContentErr(ctxt,
8490 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
8491 NULL, type, node, child, NULL,
8492 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
8493 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
8494 "length | minLength | maxLength | enumeration | whiteSpace | "
8495 "pattern)*))");
8496 }
8497 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008498 ctxt->container = oldcontainer;
8499 return (type);
8500}
8501
8502/**
8503 * xmlSchemaParseExtension:
8504 * @ctxt: a schema validation context
8505 * @schema: the schema being built
8506 * @node: a subtree containing XML Schema informations
8507 *
8508 * parse a XML schema Extension definition
8509 * *WARNING* this interface is highly subject to change
8510 *
8511 * Returns the type definition or NULL in case of error
8512 */
8513static xmlSchemaTypePtr
8514xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008515 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008516{
8517 xmlSchemaTypePtr type, subtype;
8518 xmlNodePtr child = NULL;
8519 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008520 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00008521
8522 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8523 return (NULL);
8524
8525 oldcontainer = ctxt->container;
8526
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008527 snprintf((char *) name, 30, "#ext%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008528 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00008529 if (type == NULL)
8530 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00008531 type->type = XML_SCHEMA_TYPE_EXTENSION;
Daniel Veillard4255d502002-04-16 15:50:10 +00008532 type->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008533 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00008534 ctxt->container = name;
8535
8536 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
8537 if (type->base == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008538 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_EXTENSION_NO_BASE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008539 "<extension>: The attribute \"base\" is missing.\n",
8540 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008541 }
8542 child = node->children;
8543 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008544 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8545 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008546 }
8547 subtype = NULL;
8548
8549 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008550 subtype = xmlSchemaParseAll(ctxt, schema, child);
8551 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008552 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008553 subtype = xmlSchemaParseChoice(ctxt, schema, child);
8554 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008555 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008556 subtype = xmlSchemaParseSequence(ctxt, schema, child);
8557 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008558 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008559 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008560 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008561 }
8562 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008563 type->subtypes = subtype;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008564 if ((ctxt->ctxtType != NULL) &&
8565 (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX)) {
8566 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
8567 if (IS_SCHEMA(child, "anyAttribute")) {
8568 ctxt->ctxtType->attributeWildcard =
8569 xmlSchemaParseAnyAttribute(ctxt, schema, child);
8570 child = child->next;
8571 }
8572 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008573 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008574 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008575 XML_SCHEMAP_UNKNOWN_EXTENSION_CHILD,
8576 "<extension> has unexpected content.\n", type->name,
8577 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008578 }
8579 ctxt->container = oldcontainer;
8580 return (type);
8581}
8582
8583/**
8584 * xmlSchemaParseSimpleContent:
8585 * @ctxt: a schema validation context
8586 * @schema: the schema being built
8587 * @node: a subtree containing XML Schema informations
8588 *
8589 * parse a XML schema SimpleContent definition
8590 * *WARNING* this interface is highly subject to change
8591 *
8592 * Returns the type definition or NULL in case of error
8593 */
8594static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008595xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
8596 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008597{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008598 xmlSchemaTypePtr type, subtype, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00008599 xmlNodePtr child = NULL;
8600 xmlChar name[30];
8601
8602 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8603 return (NULL);
8604
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008605 snprintf((char *) name, 30, "#SC%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008606 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00008607 if (type == NULL)
8608 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00008609 type->type = XML_SCHEMA_TYPE_SIMPLE_CONTENT;
Daniel Veillard4255d502002-04-16 15:50:10 +00008610 type->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008611 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00008612
8613 child = node->children;
8614 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008615 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8616 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008617 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008618 oldParentItem = ctxt->parentItem;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008619 ctxt->parentItem = type;
8620 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00008621 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008622 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00008623 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008624 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008625 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008626 subtype = (xmlSchemaTypePtr)
8627 xmlSchemaParseExtension(ctxt, schema, child);
8628 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008629 }
8630 type->subtypes = subtype;
8631 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008632 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008633 XML_SCHEMAP_UNKNOWN_SIMPLECONTENT_CHILD,
8634 "<simpleContent> has unexpected content.\n",
8635 NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008636 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008637 ctxt->parentItem = oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00008638 return (type);
8639}
8640
8641/**
8642 * xmlSchemaParseComplexContent:
8643 * @ctxt: a schema validation context
8644 * @schema: the schema being built
8645 * @node: a subtree containing XML Schema informations
8646 *
8647 * parse a XML schema ComplexContent definition
8648 * *WARNING* this interface is highly subject to change
8649 *
8650 * Returns the type definition or NULL in case of error
8651 */
8652static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008653xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
8654 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008655{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008656 xmlSchemaTypePtr type, subtype, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00008657 xmlNodePtr child = NULL;
8658 xmlChar name[30];
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008659 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00008660
8661 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8662 return (NULL);
8663
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008664 snprintf((char *) name, 30, "#CC%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008665 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00008666 if (type == NULL)
8667 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00008668 type->type = XML_SCHEMA_TYPE_COMPLEX_CONTENT;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008669 type->node = node;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008670 /*
8671 * Check for illegal attributes.
8672 */
8673 attr = node->properties;
8674 while (attr != NULL) {
8675 if (attr->ns == NULL) {
8676 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8677 (!xmlStrEqual(attr->name, BAD_CAST "mixed")))
8678 {
8679 xmlSchemaPIllegalAttrErr(ctxt,
8680 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8681 NULL, NULL, attr);
8682 }
8683 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8684 xmlSchemaPIllegalAttrErr(ctxt,
8685 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8686 NULL, NULL, attr);
8687 }
8688 attr = attr->next;
8689 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008690 type->id = xmlSchemaGetProp(ctxt, node, "id");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008691 /*
8692 * Handle attribute 'mixed'.
8693 */
8694 if (xmlGetBooleanProp(ctxt, NULL, type, node, "mixed", 0)) {
8695 if ((ctxt->ctxtType->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
8696 ctxt->ctxtType->flags |= XML_SCHEMAS_TYPE_MIXED;
8697 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008698 child = node->children;
8699 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008700 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8701 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008702 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008703 oldParentItem = ctxt->parentItem;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008704 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008705 subtype = NULL;
8706 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008707 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00008708 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008709 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008710 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008711 subtype = (xmlSchemaTypePtr)
8712 xmlSchemaParseExtension(ctxt, schema, child);
8713 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008714 }
8715 type->subtypes = subtype;
8716 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008717 xmlSchemaPContentErr(ctxt,
8718 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8719 NULL, NULL, node, child,
8720 NULL, "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +00008721 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008722 ctxt->parentItem = oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00008723 return (type);
8724}
8725
8726/**
8727 * xmlSchemaParseComplexType:
8728 * @ctxt: a schema validation context
8729 * @schema: the schema being built
8730 * @node: a subtree containing XML Schema informations
8731 *
8732 * parse a XML schema Complex Type definition
8733 * *WARNING* this interface is highly subject to change
8734 *
8735 * Returns the type definition or NULL in case of error
8736 */
8737static xmlSchemaTypePtr
8738xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00008739 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00008740{
Daniel Veillard01fa6152004-06-29 17:04:39 +00008741 xmlSchemaTypePtr type, subtype, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00008742 xmlNodePtr child = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008743 const xmlChar *name = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00008744 const xmlChar *oldcontainer;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008745 xmlAttrPtr attr;
8746 const xmlChar *attrValue;
8747 xmlChar *des = NULL; /* The reported designation. */
Daniel Veillard1a380b82004-10-21 16:00:06 +00008748 char buf[40];
8749
Daniel Veillard4255d502002-04-16 15:50:10 +00008750
8751 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8752 return (NULL);
8753
Daniel Veillard01fa6152004-06-29 17:04:39 +00008754 ctxtType = ctxt->ctxtType;
8755
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008756 if (topLevel) {
8757 attr = xmlSchemaGetPropNode(node, "name");
8758 if (attr == NULL) {
8759 xmlSchemaPMissingAttrErr(ctxt,
8760 XML_SCHEMAP_S4S_ATTR_MISSING,
8761 (xmlChar **) &xmlSchemaElemDesCT, NULL, node,
8762 "name", NULL);
8763 return (NULL);
8764 } else if (xmlSchemaPValAttrNode(ctxt,
8765 (xmlChar **) &xmlSchemaElemDesCT, NULL, attr,
8766 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
8767 return (NULL);
8768 }
8769 }
8770
8771 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008772 /*
8773 * Parse as local complex type definition.
8774 */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008775 snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008776 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
8777 if (type == NULL)
8778 return (NULL);
8779 name = (const xmlChar *) buf;
8780 type->node = node;
8781 type->type = XML_SCHEMA_TYPE_COMPLEX;
8782 /*
8783 * TODO: We need the target namespace.
8784 */
8785 } else {
8786 /*
8787 * Parse as global complex type definition.
8788 */
William M. Brack2f2a6632004-08-20 23:09:47 +00008789 type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace, node);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008790 if (type == NULL)
8791 return (NULL);
8792 type->node = node;
8793 type->type = XML_SCHEMA_TYPE_COMPLEX;
8794 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
8795 /*
8796 * Set defaults.
8797 */
8798 type->flags |= XML_SCHEMAS_TYPE_FINAL_DEFAULT;
8799 type->flags |= XML_SCHEMAS_TYPE_BLOCK_DEFAULT;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00008800 }
8801 type->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008802 /*
8803 * Handle attributes.
8804 */
8805 attr = node->properties;
8806 while (attr != NULL) {
8807 if (attr->ns == NULL) {
8808 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
8809 /*
8810 * Attribute "id".
8811 */
8812 type->id = xmlSchemaGetProp(ctxt, node, "id");
8813 } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
8814 /*
8815 * Attribute "mixed".
8816 */
8817 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
8818 (xmlNodePtr) attr))
8819 type->flags |= XML_SCHEMAS_TYPE_MIXED;
8820 } else if (topLevel) {
8821 /*
8822 * Attributes of global complex type definitions.
8823 */
8824 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
8825 /* Pass. */
8826 } else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
8827 /*
8828 * Attribute "abstract".
8829 */
8830 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
8831 (xmlNodePtr) attr))
8832 type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
8833 } else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
8834 /*
8835 * Attribute "final".
8836 */
8837 attrValue = xmlSchemaGetNodeContent(ctxt,
8838 (xmlNodePtr) attr);
8839 if (xmlSchemaPValAttrBlockFinal(attrValue,
8840 &(type->flags),
8841 -1,
8842 XML_SCHEMAS_TYPE_FINAL_EXTENSION,
8843 XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
8844 -1, -1, -1) != 0)
8845 {
8846 xmlSchemaPSimpleTypeErr(ctxt,
8847 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8848 &des, type, (xmlNodePtr) attr,
8849 NULL,
8850 "(#all | List of (extension | restriction))",
8851 attrValue, NULL, NULL, NULL);
8852 }
8853 } else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
8854 /*
8855 * Attribute "block".
8856 */
8857 attrValue = xmlSchemaGetNodeContent(ctxt,
8858 (xmlNodePtr) attr);
8859 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
8860 -1,
8861 XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
8862 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
8863 -1, -1, -1) != 0) {
8864 xmlSchemaPSimpleTypeErr(ctxt,
8865 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8866 &des, type, (xmlNodePtr) attr,
8867 NULL,
8868 "(#all | List of (extension | restriction)) ",
8869 attrValue, NULL, NULL, NULL);
8870 }
8871 } else {
8872 xmlSchemaPIllegalAttrErr(ctxt,
8873 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8874 &des, type, attr);
8875 }
8876 } else {
8877 xmlSchemaPIllegalAttrErr(ctxt,
8878 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8879 &des, type, attr);
8880 }
8881 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8882 xmlSchemaPIllegalAttrErr(ctxt,
8883 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8884 &des, type, attr);
8885 }
8886 attr = attr->next;
8887 }
8888 /*
8889 * Set as default for attribute wildcards.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008890 * This will be only changed if a complex type
8891 * inherits an attribute wildcard from a base type.
8892 */
8893 type->flags |= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008894 /*
8895 * And now for the children...
8896 */
8897 oldcontainer = ctxt->container;
8898 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008899 child = node->children;
8900 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008901 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8902 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008903 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00008904 ctxt->ctxtType = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008905 if (IS_SCHEMA(child, "simpleContent")) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008906 /*
8907 * 3.4.3 : 2.2
8908 * Specifying mixed='true' when the <simpleContent>
8909 * alternative is chosen has no effect
8910 */
William M. Bracke7091952004-05-11 15:09:58 +00008911 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
8912 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008913 type->subtypes = xmlSchemaParseSimpleContent(ctxt, schema, child);
8914 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008915 } else if (IS_SCHEMA(child, "complexContent")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008916 type->subtypes = xmlSchemaParseComplexContent(ctxt, schema, child);
8917 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008918 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008919 subtype = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008920 /*
8921 * Parse model groups.
8922 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008923 if (IS_SCHEMA(child, "all")) {
8924 subtype = xmlSchemaParseAll(ctxt, schema, child);
8925 child = child->next;
8926 } else if (IS_SCHEMA(child, "choice")) {
8927 subtype = xmlSchemaParseChoice(ctxt, schema, child);
8928 child = child->next;
8929 } else if (IS_SCHEMA(child, "sequence")) {
8930 subtype = xmlSchemaParseSequence(ctxt, schema, child);
8931 child = child->next;
8932 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008933 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008934 child = child->next;
8935 }
8936 if (subtype != NULL)
8937 type->subtypes = subtype;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008938 /*
8939 * Parse attribute decls/refs.
8940 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008941 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008942 /*
8943 * Parse attribute wildcard.
8944 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008945 if (IS_SCHEMA(child, "anyAttribute")) {
8946 type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
8947 child = child->next;
8948 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008949 }
8950 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008951 xmlSchemaPContentErr(ctxt,
8952 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8953 &des, type, node, child,
8954 NULL, "(annotation?, (simpleContent | complexContent | "
8955 "((group | all | choice | sequence)?, ((attribute | "
8956 "attributeGroup)*, anyAttribute?))))");
Daniel Veillard4255d502002-04-16 15:50:10 +00008957 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008958 FREE_AND_NULL(des);
Daniel Veillard4255d502002-04-16 15:50:10 +00008959 ctxt->container = oldcontainer;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008960 ctxt->ctxtType = ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00008961 return (type);
8962}
8963
Daniel Veillard4255d502002-04-16 15:50:10 +00008964/**
8965 * xmlSchemaParseSchema:
8966 * @ctxt: a schema validation context
8967 * @node: a subtree containing XML Schema informations
8968 *
8969 * parse a XML schema definition from a node set
8970 * *WARNING* this interface is highly subject to change
8971 *
8972 * Returns the internal XML Schema structure built from the resource or
8973 * NULL in case of error
8974 */
8975static xmlSchemaPtr
8976xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
8977{
8978 xmlSchemaPtr schema = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008979 const xmlChar *val;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00008980 int nberrors;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008981 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00008982
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008983 /*
8984 * This one is called by xmlSchemaParse only and is used if
8985 * the schema to be parsed was specified via the API; i.e. not
8986 * automatically by the validated instance document.
8987 */
Daniel Veillard4255d502002-04-16 15:50:10 +00008988 if ((ctxt == NULL) || (node == NULL))
8989 return (NULL);
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00008990 nberrors = ctxt->nberrors;
8991 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00008992 if (IS_SCHEMA(node, "schema")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008993 xmlSchemaImportPtr import;
8994
Daniel Veillard4255d502002-04-16 15:50:10 +00008995 schema = xmlSchemaNewSchema(ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008996 if (schema == NULL)
8997 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008998 /*
8999 * Disable build of list of items.
9000 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00009001 attr = xmlSchemaGetPropNode(node, "targetNamespace");
9002 if (attr != NULL) {
9003 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
9004 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &val);
9005 /*
9006 * TODO: Should we proceed with an invalid target namespace?
9007 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009008 schema->targetNamespace = xmlDictLookup(ctxt->dict, val, -1);
9009 } else {
9010 schema->targetNamespace = NULL;
9011 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009012 /*
9013 * Add the current ns name and location to the import table;
9014 * this is needed to have a consistent mechanism, regardless
9015 * if all schemata are constructed dynamically fired by the
9016 * instance or if the schema to be used was specified via
9017 * the API.
9018 */
9019 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports),
9020 schema->targetNamespace);
9021 if (import == NULL) {
9022 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT,
9023 NULL, NULL, (xmlNodePtr) ctxt->doc,
9024 "Internal error: xmlSchemaParseSchema, "
9025 "failed to add an import entry", NULL);
9026 xmlSchemaFree(schema);
9027 schema = NULL;
9028 return (NULL);
9029 }
9030 import->schemaLocation = ctxt->URL;
9031 /*
9032 * NOTE: We won't set the doc here, otherwise it will be freed
9033 * if the import struct is freed.
9034 * import->doc = ctxt->doc;
9035 */
9036
Daniel Veillardc0826a72004-08-10 14:17:33 +00009037 /* TODO: Check id. */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009038 schema->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00009039 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
9040 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &(schema->version));
9041
William M. Brack2f2a6632004-08-20 23:09:47 +00009042 xmlSchemaParseSchemaDefaults(ctxt, schema, node);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009043 xmlSchemaParseSchemaTopLevel(ctxt, schema, node->children);
9044 } else {
9045 xmlDocPtr doc;
9046
9047 doc = node->doc;
9048
9049 if ((doc != NULL) && (doc->URL != NULL)) {
9050 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
9051 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009052 "The file \"%s\" is not a XML schema.\n", doc->URL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009053 } else {
9054 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
9055 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009056 "The file is not a XML schema.\n", NULL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009057 }
9058 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009059 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00009060 if (ctxt->nberrors != 0) {
9061 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009062 xmlSchemaFree(schema);
9063 schema = NULL;
9064 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00009065 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009066 if (schema != NULL)
9067 schema->counter = ctxt->counter;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00009068 ctxt->nberrors = nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00009069#ifdef DEBUG
9070 if (schema == NULL)
9071 xmlGenericError(xmlGenericErrorContext,
9072 "xmlSchemaParse() failed\n");
9073#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00009074 return (schema);
9075}
9076
9077/************************************************************************
9078 * *
9079 * Validating using Schemas *
9080 * *
9081 ************************************************************************/
9082
9083/************************************************************************
9084 * *
9085 * Reading/Writing Schemas *
9086 * *
9087 ************************************************************************/
9088
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009089#if 0 /* Will be enabled if it is clear what options are needed. */
9090/**
9091 * xmlSchemaParserCtxtSetOptions:
9092 * @ctxt: a schema parser context
9093 * @options: a combination of xmlSchemaParserOption
9094 *
9095 * Sets the options to be used during the parse.
9096 *
9097 * Returns 0 in case of success, -1 in case of an
9098 * API error.
9099 */
9100static int
9101xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
9102 int options)
9103
9104{
9105 int i;
9106
9107 if (ctxt == NULL)
9108 return (-1);
9109 /*
9110 * WARNING: Change the start value if adding to the
9111 * xmlSchemaParseOption.
9112 */
9113 for (i = 1; i < (int) sizeof(int) * 8; i++) {
9114 if (options & 1<<i) {
9115 return (-1);
9116 }
9117 }
9118 ctxt->options = options;
9119 return (0);
9120}
9121
9122/**
9123 * xmlSchemaValidCtxtGetOptions:
9124 * @ctxt: a schema parser context
9125 *
9126 * Returns the option combination of the parser context.
9127 */
9128static int
9129xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
9130
9131{
9132 if (ctxt == NULL)
9133 return (-1);
9134 else
9135 return (ctxt->options);
9136}
9137
9138 void *curItems; /* used for dynamic addition of schemata */
9139 int nbCurItems; /* used for dynamic addition of schemata */
9140 int sizeCurItems; /* used for dynamic addition of schemata */
9141
9142#endif
9143
Daniel Veillard4255d502002-04-16 15:50:10 +00009144/**
9145 * xmlSchemaNewParserCtxt:
9146 * @URL: the location of the schema
9147 *
9148 * Create an XML Schemas parse context for that file/resource expected
9149 * to contain an XML Schemas file.
9150 *
9151 * Returns the parser context or NULL in case of error
9152 */
9153xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009154xmlSchemaNewParserCtxt(const char *URL)
9155{
Daniel Veillard4255d502002-04-16 15:50:10 +00009156 xmlSchemaParserCtxtPtr ret;
9157
9158 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009159 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009160
9161 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9162 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009163 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009164 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009165 return (NULL);
9166 }
9167 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009168 ret->dict = xmlDictCreate();
9169 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00009170 ret->includes = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00009171 return (ret);
9172}
9173
9174/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009175 * xmlSchemaNewParserCtxtUseDict:
9176 * @URL: the location of the schema
9177 * @dict: the dictionary to be used
9178 *
9179 * Create an XML Schemas parse context for that file/resource expected
9180 * to contain an XML Schemas file.
9181 *
9182 * Returns the parser context or NULL in case of error
9183 */
9184static xmlSchemaParserCtxtPtr
9185xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
9186{
9187 xmlSchemaParserCtxtPtr ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009188 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009189 if (URL == NULL)
9190 return (NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009191 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009192
9193 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9194 if (ret == NULL) {
9195 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
9196 NULL);
9197 return (NULL);
9198 }
9199 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
9200 ret->dict = dict;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009201 xmlDictReference(dict);
9202 if (URL != NULL)
9203 ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009204 ret->includes = 0;
9205 return (ret);
9206}
9207
9208
9209/**
Daniel Veillard6045c902002-10-09 21:13:59 +00009210 * xmlSchemaNewMemParserCtxt:
9211 * @buffer: a pointer to a char array containing the schemas
9212 * @size: the size of the array
9213 *
9214 * Create an XML Schemas parse context for that memory buffer expected
9215 * to contain an XML Schemas file.
9216 *
9217 * Returns the parser context or NULL in case of error
9218 */
9219xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009220xmlSchemaNewMemParserCtxt(const char *buffer, int size)
9221{
Daniel Veillard6045c902002-10-09 21:13:59 +00009222 xmlSchemaParserCtxtPtr ret;
9223
9224 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009225 return (NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00009226
9227 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9228 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009229 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009230 NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00009231 return (NULL);
9232 }
9233 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
9234 ret->buffer = buffer;
9235 ret->size = size;
William M. Brackcf9eadf2003-12-25 13:24:05 +00009236 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +00009237 return (ret);
9238}
9239
9240/**
Daniel Veillard9d751502003-10-29 13:21:47 +00009241 * xmlSchemaNewDocParserCtxt:
9242 * @doc: a preparsed document tree
9243 *
9244 * Create an XML Schemas parse context for that document.
9245 * NB. The document may be modified during the parsing process.
9246 *
9247 * Returns the parser context or NULL in case of error
9248 */
9249xmlSchemaParserCtxtPtr
9250xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
9251{
9252 xmlSchemaParserCtxtPtr ret;
9253
9254 if (doc == NULL)
9255 return (NULL);
9256
9257 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9258 if (ret == NULL) {
9259 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
9260 NULL);
9261 return (NULL);
9262 }
9263 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
9264 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +00009265 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +00009266 /* The application has responsibility for the document */
9267 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +00009268
9269 return (ret);
9270}
9271
9272/**
Daniel Veillard4255d502002-04-16 15:50:10 +00009273 * xmlSchemaFreeParserCtxt:
9274 * @ctxt: the schema parser context
9275 *
9276 * Free the resources associated to the schema parser context
9277 */
9278void
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009279xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
9280{
Daniel Veillard4255d502002-04-16 15:50:10 +00009281 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009282 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +00009283 if (ctxt->doc != NULL && !ctxt->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009284 xmlFreeDoc(ctxt->doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009285 if (ctxt->assemble != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009286 xmlFree((xmlSchemaTypePtr *) ctxt->assemble->items);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009287 xmlFree(ctxt->assemble);
9288 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009289 if (ctxt->vctxt != NULL) {
9290 xmlSchemaFreeValidCtxt(ctxt->vctxt);
9291 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009292 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00009293 xmlFree(ctxt);
9294}
9295
9296/************************************************************************
9297 * *
9298 * Building the content models *
9299 * *
9300 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009301
Daniel Veillard4255d502002-04-16 15:50:10 +00009302/**
9303 * xmlSchemaBuildAContentModel:
9304 * @type: the schema type definition
9305 * @ctxt: the schema parser context
9306 * @name: the element name whose content is being built
9307 *
9308 * Generate the automata sequence needed for that type
9309 */
9310static void
9311xmlSchemaBuildAContentModel(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009312 xmlSchemaParserCtxtPtr ctxt,
9313 const xmlChar * name)
9314{
Daniel Veillard4255d502002-04-16 15:50:10 +00009315 if (type == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009316 xmlGenericError(xmlGenericErrorContext,
9317 "Found unexpected type = NULL in %s content model\n",
9318 name);
9319 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00009320 }
9321 switch (type->type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009322 case XML_SCHEMA_TYPE_ANY: {
9323 xmlAutomataStatePtr start, end;
9324 xmlSchemaWildcardPtr wild;
9325 xmlSchemaWildcardNsPtr ns;
Daniel Veillard32370232002-10-16 14:08:14 +00009326
Daniel Veillardc0826a72004-08-10 14:17:33 +00009327 wild = type->attributeWildcard;
9328
9329 if (wild == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00009330 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009331 "Internal error: xmlSchemaBuildAContentModel, "
9332 "no wildcard on xsd:any.\n", NULL, NULL);
9333 return;
9334 }
9335
9336 start = ctxt->state;
9337 end = xmlAutomataNewState(ctxt->am);
9338
9339 if (type->maxOccurs == 1) {
9340 if (wild->any == 1) {
9341 /*
9342 * We need to add both transitions:
9343 *
9344 * 1. the {"*", "*"} for elements in a namespace.
9345 */
9346 ctxt->state =
9347 xmlAutomataNewTransition2(ctxt->am,
9348 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
9349 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9350 /*
9351 * 2. the {"*"} for elements in no namespace.
9352 */
9353 ctxt->state =
9354 xmlAutomataNewTransition2(ctxt->am,
9355 start, NULL, BAD_CAST "*", NULL, type);
9356 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9357
9358 } else if (wild->nsSet != NULL) {
9359 ns = wild->nsSet;
9360 do {
9361 ctxt->state = start;
9362 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9363 ctxt->state, NULL, BAD_CAST "*", ns->value, type);
9364 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9365 ns = ns->next;
9366 } while (ns != NULL);
9367
9368 } else if (wild->negNsSet != NULL) {
9369 xmlAutomataStatePtr deadEnd;
9370
9371 deadEnd = xmlAutomataNewState(ctxt->am);
9372 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9373 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, type);
9374 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9375 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
9376 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9377 }
9378 } else {
9379 int counter;
9380 xmlAutomataStatePtr hop;
9381 int maxOccurs =
9382 type->maxOccurs == UNBOUNDED ? UNBOUNDED : type->maxOccurs - 1;
9383 int minOccurs =
9384 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
9385
9386 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
9387 hop = xmlAutomataNewState(ctxt->am);
9388 if (wild->any == 1) {
9389 ctxt->state =
9390 xmlAutomataNewTransition2(ctxt->am,
9391 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
9392 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
9393 ctxt->state =
9394 xmlAutomataNewTransition2(ctxt->am,
9395 start, NULL, BAD_CAST "*", NULL, type);
9396 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
9397 } else if (wild->nsSet != NULL) {
9398 ns = wild->nsSet;
9399 do {
9400 ctxt->state =
9401 xmlAutomataNewTransition2(ctxt->am,
9402 start, NULL, BAD_CAST "*", ns->value, type);
9403 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
9404 ns = ns->next;
9405 } while (ns != NULL);
9406
9407 } else if (wild->negNsSet != NULL) {
9408 xmlAutomataStatePtr deadEnd;
9409
9410 deadEnd = xmlAutomataNewState(ctxt->am);
9411 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9412 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, type);
9413 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9414 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
9415 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
9416 }
9417 xmlAutomataNewCountedTrans(ctxt->am, hop, start, counter);
9418 xmlAutomataNewCounterTrans(ctxt->am, hop, end, counter);
9419 }
9420 if (type->minOccurs == 0) {
9421 xmlAutomataNewEpsilon(ctxt->am, start, end);
9422 }
9423 ctxt->state = end;
9424 break;
9425 }
9426 case XML_SCHEMA_TYPE_ELEMENT:{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009427 xmlAutomataStatePtr oldstate;
9428 xmlSchemaElementPtr particle, elemDecl;
Daniel Veillard32370232002-10-16 14:08:14 +00009429
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009430 /*
9431 * IMPORTANT: This puts element declarations
9432 * (and never element decl. references) into the
9433 * automaton. This is crucial and should not be changed,
9434 * since validating functions rely now on it.
9435 */
9436 particle = (xmlSchemaElementPtr) type;
9437 if (particle->ref != NULL) {
9438 if (particle->refDecl == NULL) {
9439 /*
9440 * Skip content model creation if the reference
9441 * did not resolve to a declaration.
9442 */
9443 break;
9444 } else {
9445 /*
9446 * Referenced global element declaration.
9447 */
9448 elemDecl = particle->refDecl;
9449 }
9450 } else {
9451 /*
9452 * Anonymous element declaration.
9453 */
9454 elemDecl = particle;
9455 }
9456
9457 oldstate = ctxt->state;
9458
9459 if (particle->maxOccurs >= UNBOUNDED) {
9460 if (particle->minOccurs > 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009461 xmlAutomataStatePtr tmp;
9462 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00009463
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009464 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009465 oldstate, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009466 oldstate = ctxt->state;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009467 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009468 particle->minOccurs - 1, UNBOUNDED);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00009469 ctxt->state =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009470 xmlAutomataNewTransition2(ctxt->am,
9471 ctxt->state, NULL,
9472 elemDecl->name,
9473 elemDecl->targetNamespace,
9474 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009475 tmp = ctxt->state;
9476 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009477 counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009478 ctxt->state =
9479 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009480 counter);
Daniel Veillard32370232002-10-16 14:08:14 +00009481
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009482 } else {
9483 ctxt->state =
9484 xmlAutomataNewTransition2(ctxt->am,
9485 ctxt->state, NULL,
9486 elemDecl->name,
9487 elemDecl->targetNamespace,
9488 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009489 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
9490 oldstate);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009491 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009492 /* basically an elem* */
9493 xmlAutomataNewEpsilon(ctxt->am, oldstate,
9494 ctxt->state);
9495 }
9496 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009497 } else if ((particle->maxOccurs > 1) || (particle->minOccurs > 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009498 xmlAutomataStatePtr tmp;
9499 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00009500
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009501 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
9502 oldstate, NULL);
9503 oldstate = ctxt->state;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009504 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009505 particle->minOccurs - 1,
9506 particle->maxOccurs - 1);
9507 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9508 ctxt->state,
9509 NULL,
9510 elemDecl->name,
9511 elemDecl->targetNamespace,
9512 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009513 tmp = ctxt->state;
9514 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009515 counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009516 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, tmp,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009517 NULL, counter);
9518 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009519 /* basically an elem? */
9520 xmlAutomataNewEpsilon(ctxt->am, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009521 ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009522 }
Daniel Veillardb39bc392002-10-26 19:29:51 +00009523
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009524 } else {
9525 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9526 ctxt->state,
9527 NULL,
9528 elemDecl->name,
9529 elemDecl->targetNamespace,
9530 (xmlSchemaTypePtr) elemDecl);
9531 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009532 /* basically an elem? */
9533 xmlAutomataNewEpsilon(ctxt->am, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009534 ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009535 }
9536 }
9537 break;
9538 }
9539 case XML_SCHEMA_TYPE_SEQUENCE:{
9540 xmlSchemaTypePtr subtypes;
Daniel Veillardb39bc392002-10-26 19:29:51 +00009541
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009542 /*
9543 * If max and min occurances are default (1) then
9544 * simply iterate over the subtypes
9545 */
9546 if ((type->minOccurs == 1) && (type->maxOccurs == 1)) {
9547 subtypes = type->subtypes;
9548 while (subtypes != NULL) {
9549 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
9550 subtypes = subtypes->next;
9551 }
9552 } else {
9553 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00009554
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009555 if (type->maxOccurs >= UNBOUNDED) {
9556 if (type->minOccurs > 1) {
9557 xmlAutomataStatePtr tmp;
9558 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00009559
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009560 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
9561 oldstate,
9562 NULL);
9563 oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00009564
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009565 counter = xmlAutomataNewCounter(ctxt->am,
9566 type->
9567 minOccurs - 1,
9568 UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +00009569
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009570 subtypes = type->subtypes;
9571 while (subtypes != NULL) {
9572 xmlSchemaBuildAContentModel(subtypes, ctxt,
9573 name);
9574 subtypes = subtypes->next;
9575 }
9576 tmp = ctxt->state;
9577 xmlAutomataNewCountedTrans(ctxt->am, tmp,
9578 oldstate, counter);
9579 ctxt->state =
9580 xmlAutomataNewCounterTrans(ctxt->am, tmp,
9581 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +00009582
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009583 } else {
9584 subtypes = type->subtypes;
9585 while (subtypes != NULL) {
9586 xmlSchemaBuildAContentModel(subtypes, ctxt,
9587 name);
9588 subtypes = subtypes->next;
9589 }
9590 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
9591 oldstate);
9592 if (type->minOccurs == 0) {
9593 xmlAutomataNewEpsilon(ctxt->am, oldstate,
9594 ctxt->state);
9595 }
9596 }
9597 } else if ((type->maxOccurs > 1)
9598 || (type->minOccurs > 1)) {
9599 xmlAutomataStatePtr tmp;
9600 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00009601
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009602 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
9603 oldstate,
9604 NULL);
9605 oldstate = ctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +00009606
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009607 counter = xmlAutomataNewCounter(ctxt->am,
9608 type->minOccurs -
9609 1,
9610 type->maxOccurs -
9611 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00009612
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009613 subtypes = type->subtypes;
9614 while (subtypes != NULL) {
9615 xmlSchemaBuildAContentModel(subtypes, ctxt,
9616 name);
9617 subtypes = subtypes->next;
9618 }
9619 tmp = ctxt->state;
9620 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
9621 counter);
9622 ctxt->state =
9623 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
9624 counter);
9625 if (type->minOccurs == 0) {
9626 xmlAutomataNewEpsilon(ctxt->am, oldstate,
9627 ctxt->state);
9628 }
Daniel Veillardb509f152002-04-17 16:28:10 +00009629
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009630 } else {
9631 subtypes = type->subtypes;
9632 while (subtypes != NULL) {
9633 xmlSchemaBuildAContentModel(subtypes, ctxt,
9634 name);
9635 subtypes = subtypes->next;
9636 }
9637 if (type->minOccurs == 0) {
9638 xmlAutomataNewEpsilon(ctxt->am, oldstate,
9639 ctxt->state);
9640 }
9641 }
9642 }
9643 break;
9644 }
9645 case XML_SCHEMA_TYPE_CHOICE:{
9646 xmlSchemaTypePtr subtypes;
9647 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +00009648
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009649 start = ctxt->state;
9650 end = xmlAutomataNewState(ctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +00009651
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009652 /*
9653 * iterate over the subtypes and remerge the end with an
9654 * epsilon transition
9655 */
9656 if (type->maxOccurs == 1) {
9657 subtypes = type->subtypes;
9658 while (subtypes != NULL) {
9659 ctxt->state = start;
9660 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
9661 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9662 subtypes = subtypes->next;
9663 }
9664 } else {
9665 int counter;
9666 xmlAutomataStatePtr hop;
9667 int maxOccurs = type->maxOccurs == UNBOUNDED ?
9668 UNBOUNDED : type->maxOccurs - 1;
9669 int minOccurs =
9670 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +00009671
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009672 /*
9673 * use a counter to keep track of the number of transtions
9674 * which went through the choice.
9675 */
9676 counter =
9677 xmlAutomataNewCounter(ctxt->am, minOccurs,
9678 maxOccurs);
9679 hop = xmlAutomataNewState(ctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +00009680
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009681 subtypes = type->subtypes;
9682 while (subtypes != NULL) {
9683 ctxt->state = start;
9684 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
9685 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
9686 subtypes = subtypes->next;
9687 }
9688 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
9689 counter);
9690 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
9691 counter);
9692 }
9693 if (type->minOccurs == 0) {
9694 xmlAutomataNewEpsilon(ctxt->am, start, end);
9695 }
9696 ctxt->state = end;
9697 break;
9698 }
9699 case XML_SCHEMA_TYPE_ALL:{
9700 xmlAutomataStatePtr start;
9701 xmlSchemaTypePtr subtypes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009702
Daniel Veillard3646d642004-06-02 19:19:14 +00009703 xmlSchemaElementPtr elem;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009704 int lax;
9705
9706 subtypes = type->subtypes;
9707 if (subtypes == NULL)
9708 break;
9709 start = ctxt->state;
9710 while (subtypes != NULL) {
9711 ctxt->state = start;
William M. Brack9989c7d2004-05-12 14:39:38 +00009712 /*
9713 * the following 'if' was needed to fix bug 139897
9714 * not quite sure why it only needs to be done for
9715 * elements with a 'ref', but it seems to work ok.
9716 */
9717 if (subtypes->ref != NULL)
9718 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009719 elem = (xmlSchemaElementPtr) subtypes;
9720 /*
9721 * NOTE: The {max occurs} of all the particles in the
9722 * {particles} of the group must be 0 or 1.
9723 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009724 if ((elem->minOccurs == 1) && (elem->maxOccurs == 1)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009725 xmlAutomataNewOnceTrans2(ctxt->am, ctxt->state,
9726 ctxt->state,
9727 elem->name,
9728 elem->targetNamespace,
9729 1, 1, subtypes);
9730 } else if ((elem->minOccurs == 0) &&
9731 (elem->maxOccurs == 1)) {
9732
9733 xmlAutomataNewCountTrans2(ctxt->am, ctxt->state,
9734 ctxt->state,
9735 elem->name,
9736 elem->targetNamespace,
9737 0,
9738 1,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009739 subtypes);
9740 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009741 /*
9742 * NOTE: if maxOccurs == 0 then no transition will be
9743 * created.
9744 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009745 subtypes = subtypes->next;
9746 }
9747 lax = type->minOccurs == 0;
9748 ctxt->state =
9749 xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL,
9750 lax);
9751 break;
9752 }
9753 case XML_SCHEMA_TYPE_RESTRICTION:
9754 if (type->subtypes != NULL)
9755 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
9756 break;
9757 case XML_SCHEMA_TYPE_EXTENSION:
9758 if (type->baseType != NULL) {
9759 xmlSchemaTypePtr subtypes;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009760
9761 /*
9762 * TODO: Circular definitions will be checked at the
9763 * constraint level. So remove this when the complex type
9764 * constraints are implemented.
9765 */
Daniel Veillardf7627552004-04-22 07:15:40 +00009766 if (type->recurse) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009767 /* TODO: Change the error code. */
9768 xmlSchemaPCustomErr(ctxt,
9769 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
9770 NULL, type, type->node,
9771 "This item is circular", NULL);
Daniel Veillardf7627552004-04-22 07:15:40 +00009772 return;
9773 }
9774 type->recurse = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009775 xmlSchemaBuildAContentModel(type->baseType, ctxt, name);
Daniel Veillardf7627552004-04-22 07:15:40 +00009776 type->recurse = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009777 subtypes = type->subtypes;
9778 while (subtypes != NULL) {
9779 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
9780 subtypes = subtypes->next;
9781 }
9782 } else if (type->subtypes != NULL)
9783 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
9784 break;
9785 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00009786 /*
9787 * Handle model group definition references.
9788 * NOTE: type->subtypes is the referenced model grop definition;
9789 * and type->subtypes->subtypes is the model group (i.e. <all> or
9790 * <choice> or <sequence>).
9791 */
9792 if ((type->ref != NULL) && (type->subtypes != NULL) &&
9793 (type->subtypes->subtypes != NULL)) {
9794 xmlSchemaTypePtr modelGr;
9795 xmlAutomataStatePtr start, end;
9796
9797 modelGr = type->subtypes->subtypes;
9798 start = ctxt->state;
9799 end = xmlAutomataNewState(ctxt->am);
9800 if (type->maxOccurs == 1) {
9801 ctxt->state = start;
9802 xmlSchemaBuildAContentModel(modelGr, ctxt, name);
9803 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9804 } else {
9805 int counter;
9806 xmlAutomataStatePtr hop;
9807 int maxOccurs = type->maxOccurs == UNBOUNDED ?
9808 UNBOUNDED : type->maxOccurs - 1;
9809 int minOccurs =
9810 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
9811
9812 counter =
9813 xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
9814 hop = xmlAutomataNewState(ctxt->am);
9815 ctxt->state = start;
9816 xmlSchemaBuildAContentModel(modelGr, ctxt, name);
9817 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
9818 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
9819 counter);
9820 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
9821 counter);
9822 }
9823 if (type->minOccurs == 0) {
9824 xmlAutomataNewEpsilon(ctxt->am, start, end);
9825 }
9826 ctxt->state = end;
9827 break;
9828 }
9829 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009830 case XML_SCHEMA_TYPE_COMPLEX:
9831 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
9832 if (type->subtypes != NULL)
9833 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
9834 break;
William M. Brack2f2a6632004-08-20 23:09:47 +00009835 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
9836 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009837 default:
9838 xmlGenericError(xmlGenericErrorContext,
9839 "Found unexpected type %d in %s content model\n",
9840 type->type, name);
9841 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00009842 }
9843}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009844
Daniel Veillard4255d502002-04-16 15:50:10 +00009845/**
9846 * xmlSchemaBuildContentModel:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009847 * @type: the type definition (or reference)
Daniel Veillard4255d502002-04-16 15:50:10 +00009848 * @ctxt: the schema parser context
Daniel Veillarda84c0b32003-06-02 16:58:46 +00009849 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +00009850 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009851 * Builds the content model of the complex type.
Daniel Veillard4255d502002-04-16 15:50:10 +00009852 */
9853static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009854xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009855 xmlSchemaParserCtxtPtr ctxt,
9856 const xmlChar * name)
9857{
Daniel Veillard4255d502002-04-16 15:50:10 +00009858 xmlAutomataStatePtr start;
9859
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009860 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) || (type->ref != NULL) ||
9861 (type->contentType == XML_SCHEMA_CONTENT_BASIC) ||
9862 (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
9863 (type->contModel != NULL))
9864 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +00009865
9866#ifdef DEBUG_CONTENT
9867 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009868 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00009869#endif
9870
Daniel Veillard4255d502002-04-16 15:50:10 +00009871 ctxt->am = xmlNewAutomata();
9872 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009873 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009874 "Cannot create automata for complex tpye %s\n", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009875 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00009876 }
9877 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009878 xmlSchemaBuildAContentModel(type, ctxt, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00009879 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009880 type->contModel = xmlAutomataCompile(ctxt->am);
9881 if (type->contModel == NULL) {
9882 xmlSchemaPCustomErr(ctxt,
9883 XML_SCHEMAP_INTERNAL,
9884 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009885 "Failed to compile the content model", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009886 } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00009887 xmlSchemaPCustomErr(ctxt,
9888 XML_SCHEMAP_NOT_DETERMINISTIC,
9889 /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009890 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009891 "The content model is not determinist", NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +00009892 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +00009893#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009894 xmlGenericError(xmlGenericErrorContext,
9895 "Content model of %s:\n", name);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009896 xmlRegexpPrint(stderr, type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00009897#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +00009898 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00009899 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00009900 xmlFreeAutomata(ctxt->am);
9901 ctxt->am = NULL;
9902}
9903
9904/**
9905 * xmlSchemaRefFixupCallback:
9906 * @elem: the schema element context
9907 * @ctxt: the schema parser context
9908 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00009909 * Resolves the references of an element declaration
9910 * or particle, which has an element declaration as it's
9911 * term.
Daniel Veillard4255d502002-04-16 15:50:10 +00009912 */
9913static void
9914xmlSchemaRefFixupCallback(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009915 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009916 const xmlChar * name ATTRIBUTE_UNUSED,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009917 const xmlChar * context ATTRIBUTE_UNUSED,
9918 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00009919{
Daniel Veillardc0826a72004-08-10 14:17:33 +00009920 if ((ctxt == NULL) || (elem == NULL) ||
9921 ((elem != NULL) && (elem->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009922 return;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009923 elem->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
Daniel Veillard4255d502002-04-16 15:50:10 +00009924 if (elem->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009925 xmlSchemaElementPtr elemDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00009926
Daniel Veillardc0826a72004-08-10 14:17:33 +00009927 /*
9928 * TODO: Evaluate, what errors could occur if the declaration is not
9929 * found. It might be possible that the "typefixup" might crash if
9930 * no ref declaration was found.
9931 */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00009932 elemDecl = xmlSchemaGetElem(ctxt->schema, elem->ref, elem->refNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009933 if (elemDecl == NULL) {
9934 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009935 XML_SCHEMAP_SRC_RESOLVE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009936 NULL, (xmlSchemaTypePtr) elem, elem->node,
9937 "ref", elem->ref, elem->refNs,
9938 XML_SCHEMA_TYPE_ELEMENT, NULL);
9939 } else
9940 elem->refDecl = elemDecl;
9941 } else {
9942 if ((elem->subtypes == NULL) && (elem->namedType != NULL)) {
9943 xmlSchemaTypePtr type;
9944
9945 /* (type definition) ... otherwise the type definition ·resolved·
9946 * to by the ·actual value· of the type [attribute] ...
9947 */
9948 type = xmlSchemaGetType(ctxt->schema, elem->namedType,
9949 elem->namedTypeNs);
9950 if (type == NULL) {
9951 xmlSchemaPResCompAttrErr(ctxt,
9952 XML_SCHEMAP_SRC_RESOLVE,
9953 NULL, (xmlSchemaTypePtr) elem, elem->node,
9954 "type", elem->namedType, elem->namedTypeNs,
9955 XML_SCHEMA_TYPE_BASIC, "type definition");
9956 } else
9957 elem->subtypes = type;
9958 }
9959 if (elem->substGroup != NULL) {
9960 xmlSchemaElementPtr substHead;
9961
9962 /*
9963 * FIXME TODO: Do we need a new field in _xmlSchemaElement for
9964 * substitutionGroup?
9965 */
9966 substHead = xmlSchemaGetElem(ctxt->schema, elem->substGroup,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00009967 elem->substGroupNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009968 if (substHead == NULL) {
9969 xmlSchemaPResCompAttrErr(ctxt,
9970 XML_SCHEMAP_SRC_RESOLVE,
9971 NULL, (xmlSchemaTypePtr) elem, NULL,
9972 "substitutionGroup", elem->substGroup, elem->substGroupNs,
9973 XML_SCHEMA_TYPE_ELEMENT, NULL);
9974 } else {
9975 xmlSchemaRefFixupCallback(substHead, ctxt, NULL, NULL, NULL);
9976 /*
9977 * (type definition)...otherwise the {type definition} of the
9978 * element declaration ·resolved· to by the ·actual value· of
9979 * the substitutionGroup [attribute], if present
9980 */
9981 if (elem->subtypes == NULL)
9982 elem->subtypes = substHead->subtypes;
9983 }
9984 }
9985 if ((elem->subtypes == NULL) && (elem->namedType == NULL) &&
9986 (elem->substGroup == NULL))
9987 elem->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
9988 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009989}
9990
William M. Bracke7091952004-05-11 15:09:58 +00009991/**
9992 * xmlSchemaParseListRefFixup:
9993 * @type: the schema type definition
9994 * @ctxt: the schema parser context
9995 *
9996 * Fixup of the itemType reference of the list type.
9997 */
Daniel Veillard377e1a92004-04-16 16:30:05 +00009998static void
William M. Bracke7091952004-05-11 15:09:58 +00009999xmlSchemaParseListRefFixup(xmlSchemaTypePtr type, xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010000{
Daniel Veillardc0826a72004-08-10 14:17:33 +000010001
Daniel Veillard01fa6152004-06-29 17:04:39 +000010002 if (((type->base == NULL) &&
10003 (type->subtypes == NULL)) ||
10004 ((type->base != NULL) &&
10005 (type->subtypes != NULL))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010006 /*
10007 * src-list-itemType-or-simpleType
10008 * Either the itemType [attribute] or the <simpleType> [child] of
10009 * the <list> element must be present, but not both.
Daniel Veillard01fa6152004-06-29 17:04:39 +000010010 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000010011 /*
10012 * TODO: Move this to the parse function.
10013 */
10014 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010015 XML_SCHEMAP_SRC_LIST_ITEMTYPE_OR_SIMPLETYPE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010016 NULL, type, type->node,
10017 "The attribute 'itemType' and the <simpleType> child "
10018 "are mutually exclusive", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010019 } else if (type->base!= NULL) {
10020 type->subtypes = xmlSchemaGetType(ctxt->schema, type->base, type->baseNs);
10021 if (type->subtypes == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010022 xmlSchemaPResCompAttrErr(ctxt,
10023 XML_SCHEMAP_SRC_RESOLVE,
10024 NULL, type, type->node,
10025 "itemType", type->base, type->baseNs,
10026 XML_SCHEMA_TYPE_SIMPLE, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010027 }
10028 }
10029 if ((type->subtypes != NULL) &&
10030 (type->subtypes->contentType == XML_SCHEMA_CONTENT_UNKNOWN))
10031 xmlSchemaTypeFixup(type->subtypes, ctxt, NULL);
William M. Bracke7091952004-05-11 15:09:58 +000010032}
10033
10034/**
10035 * xmlSchemaParseUnionRefCheck:
10036 * @typeDecl: the schema type definition
10037 * @ctxt: the schema parser context
10038 *
Daniel Veillard01fa6152004-06-29 17:04:39 +000010039 * Checks and builds the memberTypes of the union type.
10040 * Returns -1 in case of an internal error, 0 otherwise.
William M. Bracke7091952004-05-11 15:09:58 +000010041 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010042static int
William M. Bracke7091952004-05-11 15:09:58 +000010043xmlSchemaParseUnionRefCheck(xmlSchemaTypePtr type,
Daniel Veillard377e1a92004-04-16 16:30:05 +000010044 xmlSchemaParserCtxtPtr ctxt)
10045{
Daniel Veillardc0826a72004-08-10 14:17:33 +000010046
Daniel Veillard01fa6152004-06-29 17:04:39 +000010047 xmlSchemaTypeLinkPtr link, lastLink = NULL, prevLink, subLink, newLink;
10048 xmlSchemaTypePtr memberType, ctxtType;
Daniel Veillard377e1a92004-04-16 16:30:05 +000010049
Daniel Veillard01fa6152004-06-29 17:04:39 +000010050 /* 1 If the <union> alternative is chosen, then [Definition:]
10051 * define the explicit members as the type definitions ·resolved·
10052 * to by the items in the ·actual value· of the memberTypes [attribute],
10053 * if any, followed by the type definitions corresponding to the
10054 * <simpleType>s among the [children] of <union>, if any.
10055 */
Daniel Veillard377e1a92004-04-16 16:30:05 +000010056
Daniel Veillard01fa6152004-06-29 17:04:39 +000010057 if (type->type != XML_SCHEMA_TYPE_UNION)
10058 return (-1);
10059 if (ctxt->ctxtType == NULL) {
10060 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010061 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010062 "Internal error: xmlSchemaParseUnionRefCheck, no parent type "
10063 "available", NULL, NULL);
10064 return (-1);
10065 }
10066 /*
10067 * src-union-memberTypes-or-simpleTypes
10068 * Either the memberTypes [attribute] of the <union> element must
10069 * be non-empty or there must be at least one simpleType [child].
10070 */
10071 if ((type->base == NULL) &&
10072 (type->subtypes == NULL)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010073 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010074 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010075 NULL, NULL, type->node,
10076 "Either the attribute 'memberTypes' must be non-empty "
10077 "or there must be at least one <simpleType> child", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010078 }
10079
10080 ctxtType = ctxt->ctxtType;
10081 if (type->base != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010082 xmlAttrPtr attr;
10083 const xmlChar *cur, *end;
10084 xmlChar *tmp;
10085 const xmlChar *localName, *uri;
10086
10087 attr = xmlSchemaGetPropNode(type->node, "memberTypes");
Daniel Veillard01fa6152004-06-29 17:04:39 +000010088 cur = type->base;
10089 do {
10090 while (IS_BLANK_CH(*cur))
10091 cur++;
10092 end = cur;
10093 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
10094 end++;
10095 if (end == cur)
10096 break;
10097 tmp = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +000010098 xmlSchemaPValAttrNodeQNameValue(ctxt, ctxt->schema, NULL,
10099 NULL, attr, BAD_CAST tmp, &uri, NULL, &localName);
10100 memberType = xmlSchemaGetType(ctxt->schema, localName, uri);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010101 if (memberType == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010102 xmlSchemaPResCompAttrErr(ctxt,
10103 XML_SCHEMAP_UNKNOWN_MEMBER_TYPE,
10104 NULL, NULL, type->node, "memberTypes", localName, uri,
10105 XML_SCHEMA_TYPE_SIMPLE, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010106 } else {
10107 if (memberType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
10108 xmlSchemaTypeFixup(memberType, ctxt, NULL);
10109 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
10110 if (link == NULL) {
10111 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
10112 return (-1);
10113 }
10114 link->type = memberType;
10115 link->next = NULL;
10116 if (lastLink == NULL)
10117 ctxtType->memberTypes = link;
10118 else
10119 lastLink->next = link;
10120 lastLink = link;
10121 }
10122 xmlFree(tmp);
10123 cur = end;
10124 } while (*cur != 0);
10125 }
10126 /*
10127 * Add local simple types,
10128 */
10129 memberType = type->subtypes;
10130 while (memberType != NULL) {
10131 if (memberType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
10132 xmlSchemaTypeFixup(memberType, ctxt, NULL);
10133 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
10134 if (link == NULL) {
10135 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
10136 return (-1);
10137 }
10138 link->type = memberType;
10139 link->next = NULL;
10140 if (lastLink == NULL)
10141 ctxtType->memberTypes = link;
10142 else
10143 lastLink->next = link;
10144 lastLink = link;
10145 memberType = memberType->next;
10146 }
10147 /*
10148 * The actual value is then formed by replacing any union type
10149 * definition in the ·explicit members· with the members of their
10150 * {member type definitions}, in order.
10151 */
10152 link = ctxtType->memberTypes;
10153 while (link != NULL) {
10154 if (link->type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
10155 subLink = link->type->memberTypes;
10156 if (subLink != NULL) {
10157 link->type = subLink->type;
10158 if (subLink->next != NULL) {
10159 lastLink = link->next;
10160 subLink = subLink->next;
10161 prevLink = link;
10162 while (subLink != NULL) {
10163 newLink = (xmlSchemaTypeLinkPtr)
10164 xmlMalloc(sizeof(xmlSchemaTypeLink));
10165 if (newLink == NULL) {
10166 xmlSchemaPErrMemory(ctxt, "allocating a type link",
10167 NULL);
10168 return (-1);
10169 }
10170 newLink->type = memberType;
10171 prevLink->next = newLink;
10172 prevLink = newLink;
10173 newLink->next = lastLink;
10174
10175 subLink = subLink->next;
10176 }
10177 }
10178 }
10179 }
10180 link = link->next;
10181 }
10182
10183 return (0);
Daniel Veillard377e1a92004-04-16 16:30:05 +000010184}
10185
Daniel Veillard4255d502002-04-16 15:50:10 +000010186/**
Daniel Veillard3646d642004-06-02 19:19:14 +000010187 * xmlSchemaIsDerivedFromBuiltInType:
10188 * @ctxt: the schema parser context
10189 * @type: the type definition
10190 * @valType: the value type
10191 *
10192 *
10193 * Returns 1 if the type has the given value type, or
10194 * is derived from such a type.
10195 */
William M. Brack803812b2004-06-03 02:11:24 +000010196static int
Daniel Veillard3646d642004-06-02 19:19:14 +000010197xmlSchemaIsDerivedFromBuiltInType(xmlSchemaParserCtxtPtr ctxt,
10198 xmlSchemaTypePtr type, int valType)
10199{
10200 /* TODO: Check if this works in every case. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010201 if ((type->type == XML_SCHEMA_TYPE_BASIC) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000010202 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000010203 if (type->builtInType == valType)
Daniel Veillard3646d642004-06-02 19:19:14 +000010204 return(1);
10205 } else if (type->type == XML_SCHEMA_TYPE_ATTRIBUTE) {
10206 if (((xmlSchemaAttributePtr) type)->subtypes != NULL)
10207 return(xmlSchemaIsDerivedFromBuiltInType(ctxt,
10208 ((xmlSchemaAttributePtr) type)->subtypes, valType));
10209 } else if ((type->type == XML_SCHEMA_TYPE_RESTRICTION) ||
10210 (type->type == XML_SCHEMA_TYPE_EXTENSION)) {
10211 if (type->baseType != NULL)
10212 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->baseType,
10213 valType));
10214 } else if ((type->subtypes != NULL) &&
10215 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX) ||
10216 (type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
10217 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE) ||
10218 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
10219 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->subtypes,
10220 valType));
10221 }
10222
10223 return (0);
10224}
10225
10226/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000010227 * xmlSchemaIsDerivedFromBuiltInType:
10228 * @type: the simpleType definition
10229 *
10230 * Returns the primitive type of the given type or
10231 * NULL in case of error.
10232 */
10233static xmlSchemaTypePtr
10234xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
10235{
10236 while (type != NULL) {
10237 if (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE)
10238 return (type);
10239 type = type->baseType;
10240 }
10241
10242 return (NULL);
10243}
10244
10245
10246/**
Daniel Veillard3646d642004-06-02 19:19:14 +000010247 * xmlSchemaBuildAttributeUsesOwned:
10248 * @ctxt: the schema parser context
10249 * @type: the complex type definition
10250 * @cur: the attribute declaration list
10251 * @lastUse: the top of the attribute use list
10252 *
10253 * Builds the attribute uses list on the given complex type.
10254 * This one is supposed to be called by
10255 * xmlSchemaBuildAttributeValidation only.
10256 */
10257static int
10258xmlSchemaBuildAttributeUsesOwned(xmlSchemaParserCtxtPtr ctxt,
10259 xmlSchemaAttributePtr cur,
10260 xmlSchemaAttributeLinkPtr *uses,
10261 xmlSchemaAttributeLinkPtr *lastUse)
10262{
10263 xmlSchemaAttributeLinkPtr tmp;
10264 while (cur != NULL) {
10265 if (cur->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
10266 /*
10267 * W3C: "2 The {attribute uses} of the attribute groups ·resolved·
10268 * to by the ·actual value·s of the ref [attribute] of the
10269 * <attributeGroup> [children], if any."
10270 */
10271 if (xmlSchemaBuildAttributeUsesOwned(ctxt,
10272 ((xmlSchemaAttributeGroupPtr) cur)->attributes, uses,
10273 lastUse) == -1) {
10274 return (-1);
10275 }
10276 } else {
10277 /* W3C: "1 The set of attribute uses corresponding to the
10278 * <attribute> [children], if any."
10279 */
10280 tmp = (xmlSchemaAttributeLinkPtr)
10281 xmlMalloc(sizeof(xmlSchemaAttributeLink));
10282 if (tmp == NULL) {
10283 xmlSchemaPErrMemory(ctxt, "building attribute uses", NULL);
10284 return (-1);
10285 }
10286 tmp->attr = cur;
10287 tmp->next = NULL;
10288 if (*uses == NULL)
10289 *uses = tmp;
10290 else
10291 (*lastUse)->next = tmp;
10292 *lastUse = tmp;
10293 }
10294 cur = cur->next;
10295 }
10296 return (0);
10297}
10298
Daniel Veillard50355f02004-06-08 17:52:16 +000010299/**
10300 * xmlSchemaCloneWildcardNsConstraints:
10301 * @ctxt: the schema parser context
10302 * @dest: the destination wildcard
10303 * @source: the source wildcard
10304 *
10305 * Clones the namespace constraints of source
10306 * and assignes them to dest.
10307 * Returns -1 on internal error, 0 otherwise.
10308 */
Daniel Veillard3646d642004-06-02 19:19:14 +000010309static int
10310xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
10311 xmlSchemaWildcardPtr *dest,
10312 xmlSchemaWildcardPtr source)
10313{
10314 xmlSchemaWildcardNsPtr cur, tmp, last;
10315
10316 if ((source == NULL) || (*dest == NULL))
10317 return(-1);
10318 (*dest)->any = source->any;
10319 cur = source->nsSet;
10320 last = NULL;
10321 while (cur != NULL) {
10322 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
10323 if (tmp == NULL)
10324 return(-1);
10325 tmp->value = cur->value;
10326 if (last == NULL)
10327 (*dest)->nsSet = tmp;
10328 else
10329 last->next = tmp;
10330 last = tmp;
10331 cur = cur->next;
10332 }
10333 if ((*dest)->negNsSet != NULL)
10334 xmlSchemaFreeWildcardNsSet((*dest)->negNsSet);
10335 if (source->negNsSet != NULL) {
10336 (*dest)->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
10337 if ((*dest)->negNsSet == NULL)
10338 return(-1);
10339 (*dest)->negNsSet->value = source->negNsSet->value;
10340 } else
10341 (*dest)->negNsSet = NULL;
10342 return(0);
10343}
10344
Daniel Veillard50355f02004-06-08 17:52:16 +000010345/**
10346 * xmlSchemaUnionWildcards:
10347 * @ctxt: the schema parser context
10348 * @completeWild: the first wildcard
10349 * @curWild: the second wildcard
10350 *
10351 * Unions the namespace constraints of the given wildcards.
10352 * @completeWild will hold the resulting union.
10353 * Returns a positive error code on failure, -1 in case of an
10354 * internal error, 0 otherwise.
10355 */
Daniel Veillard3646d642004-06-02 19:19:14 +000010356static int
10357xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
10358 xmlSchemaWildcardPtr completeWild,
10359 xmlSchemaWildcardPtr curWild)
10360{
10361 xmlSchemaWildcardNsPtr cur, curB, tmp;
10362
10363 /*
10364 * 1 If O1 and O2 are the same value, then that value must be the
10365 * value.
10366 */
10367 if ((completeWild->any == curWild->any) &&
10368 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
10369 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
10370
10371 if ((completeWild->negNsSet == NULL) ||
10372 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
10373
10374 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000010375 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000010376
10377 /*
10378 * Check equality of sets.
10379 */
10380 cur = completeWild->nsSet;
10381 while (cur != NULL) {
10382 found = 0;
10383 curB = curWild->nsSet;
10384 while (curB != NULL) {
10385 if (cur->value == curB->value) {
10386 found = 1;
10387 break;
10388 }
10389 curB = curB->next;
10390 }
10391 if (!found)
10392 break;
10393 cur = cur->next;
10394 }
10395 if (found)
10396 return(0);
10397 } else
10398 return(0);
10399 }
10400 }
10401 /*
10402 * 2 If either O1 or O2 is any, then any must be the value
10403 */
Daniel Veillard50355f02004-06-08 17:52:16 +000010404 if (completeWild->any != curWild->any) {
Daniel Veillard3646d642004-06-02 19:19:14 +000010405 if (completeWild->any == 0) {
10406 completeWild->any = 1;
10407 if (completeWild->nsSet != NULL) {
10408 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
10409 completeWild->nsSet = NULL;
10410 }
10411 if (completeWild->negNsSet != NULL) {
10412 xmlFree(completeWild->negNsSet);
10413 completeWild->negNsSet = NULL;
10414 }
10415 }
Daniel Veillard50355f02004-06-08 17:52:16 +000010416 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000010417 }
10418 /*
10419 * 3 If both O1 and O2 are sets of (namespace names or ·absent·),
10420 * then the union of those sets must be the value.
10421 */
10422 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
10423 int found;
10424 xmlSchemaWildcardNsPtr start;
10425
10426 cur = curWild->nsSet;
10427 start = completeWild->nsSet;
10428 while (cur != NULL) {
10429 found = 0;
10430 curB = start;
10431 while (curB != NULL) {
10432 if (cur->value == curB->value) {
10433 found = 1;
10434 break;
10435 }
10436 curB = curB->next;
10437 }
10438 if (!found) {
10439 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
10440 if (tmp == NULL)
10441 return (-1);
10442 tmp->value = cur->value;
10443 tmp->next = completeWild->nsSet;
10444 completeWild->nsSet = tmp;
10445 }
10446 cur = cur->next;
10447 }
10448
10449 return(0);
10450 }
10451 /*
10452 * 4 If the two are negations of different values (namespace names
10453 * or ·absent·), then a pair of not and ·absent· must be the value.
10454 */
10455 if ((completeWild->negNsSet != NULL) &&
10456 (curWild->negNsSet != NULL) &&
10457 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
10458 completeWild->negNsSet->value = NULL;
Daniel Veillard50355f02004-06-08 17:52:16 +000010459
10460 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +000010461 }
10462 /*
10463 * 5.
10464 */
10465 if (((completeWild->negNsSet != NULL) &&
10466 (completeWild->negNsSet->value != NULL) &&
10467 (curWild->nsSet != NULL)) ||
10468 ((curWild->negNsSet != NULL) &&
10469 (curWild->negNsSet->value != NULL) &&
10470 (completeWild->nsSet != NULL))) {
10471
10472 int nsFound, absentFound = 0;
10473
10474 if (completeWild->nsSet != NULL) {
10475 cur = completeWild->nsSet;
10476 curB = curWild->negNsSet;
10477 } else {
10478 cur = curWild->nsSet;
10479 curB = completeWild->negNsSet;
10480 }
10481 nsFound = 0;
10482 while (cur != NULL) {
10483 if (cur->value == NULL)
10484 absentFound = 1;
10485 else if (cur->value == curB->value)
10486 nsFound = 1;
10487 if (nsFound && absentFound)
10488 break;
10489 cur = cur->next;
10490 }
10491
10492 if (nsFound && absentFound) {
10493 /*
10494 * 5.1 If the set S includes both the negated namespace
10495 * name and ·absent·, then any must be the value.
10496 */
10497 completeWild->any = 1;
10498 if (completeWild->nsSet != NULL) {
10499 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
10500 completeWild->nsSet = NULL;
10501 }
10502 if (completeWild->negNsSet != NULL) {
10503 xmlFree(completeWild->negNsSet);
10504 completeWild->negNsSet = NULL;
10505 }
10506 } else if (nsFound && (!absentFound)) {
10507 /*
10508 * 5.2 If the set S includes the negated namespace name
10509 * but not ·absent·, then a pair of not and ·absent· must
10510 * be the value.
10511 */
10512 if (completeWild->nsSet != NULL) {
10513 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
10514 completeWild->nsSet = NULL;
10515 }
10516 if (completeWild->negNsSet == NULL) {
10517 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
10518 if (completeWild->negNsSet == NULL)
10519 return (-1);
10520 }
10521 completeWild->negNsSet->value = NULL;
10522 } else if ((!nsFound) && absentFound) {
10523 /*
10524 * 5.3 If the set S includes ·absent· but not the negated
10525 * namespace name, then the union is not expressible.
10526 */
10527 xmlSchemaPErr(ctxt, completeWild->node,
10528 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010529 "The union of the wilcard is not expressible.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +000010530 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000010531 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +000010532 } else if ((!nsFound) && (!absentFound)) {
10533 /*
10534 * 5.4 If the set S does not include either the negated namespace
10535 * name or ·absent·, then whichever of O1 or O2 is a pair of not
10536 * and a namespace name must be the value.
10537 */
10538 if (completeWild->negNsSet == NULL) {
10539 if (completeWild->nsSet != NULL) {
10540 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
10541 completeWild->nsSet = NULL;
10542 }
10543 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
10544 if (completeWild->negNsSet == NULL)
10545 return (-1);
10546 completeWild->negNsSet->value = curWild->negNsSet->value;
10547 }
10548 }
10549 return (0);
10550 }
10551 /*
10552 * 6.
10553 */
10554 if (((completeWild->negNsSet != NULL) &&
10555 (completeWild->negNsSet->value == NULL) &&
10556 (curWild->nsSet != NULL)) ||
10557 ((curWild->negNsSet != NULL) &&
10558 (curWild->negNsSet->value == NULL) &&
10559 (completeWild->nsSet != NULL))) {
10560
10561 if (completeWild->nsSet != NULL) {
10562 cur = completeWild->nsSet;
10563 } else {
10564 cur = curWild->nsSet;
10565 }
10566 while (cur != NULL) {
10567 if (cur->value == NULL) {
10568 /*
10569 * 6.1 If the set S includes ·absent·, then any must be the
10570 * value.
10571 */
10572 completeWild->any = 1;
10573 if (completeWild->nsSet != NULL) {
10574 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
10575 completeWild->nsSet = NULL;
10576 }
10577 if (completeWild->negNsSet != NULL) {
10578 xmlFree(completeWild->negNsSet);
10579 completeWild->negNsSet = NULL;
10580 }
10581 return (0);
10582 }
10583 cur = cur->next;
10584 }
10585 if (completeWild->negNsSet == NULL) {
10586 /*
10587 * 6.2 If the set S does not include ·absent·, then a pair of not
10588 * and ·absent· must be the value.
10589 */
10590 if (completeWild->nsSet != NULL) {
10591 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
10592 completeWild->nsSet = NULL;
10593 }
10594 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
10595 if (completeWild->negNsSet == NULL)
10596 return (-1);
10597 completeWild->negNsSet->value = NULL;
10598 }
10599 return (0);
10600 }
10601 return (0);
10602
10603}
10604
Daniel Veillard50355f02004-06-08 17:52:16 +000010605/**
10606 * xmlSchemaIntersectWildcards:
10607 * @ctxt: the schema parser context
10608 * @completeWild: the first wildcard
10609 * @curWild: the second wildcard
10610 *
10611 * Intersects the namespace constraints of the given wildcards.
10612 * @completeWild will hold the resulting intersection.
10613 * Returns a positive error code on failure, -1 in case of an
10614 * internal error, 0 otherwise.
10615 */
Daniel Veillard3646d642004-06-02 19:19:14 +000010616static int
10617xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
10618 xmlSchemaWildcardPtr completeWild,
10619 xmlSchemaWildcardPtr curWild)
10620{
William M. Brack803812b2004-06-03 02:11:24 +000010621 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000010622
10623 /*
10624 * 1 If O1 and O2 are the same value, then that value must be the
10625 * value.
10626 */
10627 if ((completeWild->any == curWild->any) &&
10628 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
10629 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
10630
10631 if ((completeWild->negNsSet == NULL) ||
10632 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
10633
10634 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000010635 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000010636
10637 /*
10638 * Check equality of sets.
10639 */
10640 cur = completeWild->nsSet;
10641 while (cur != NULL) {
10642 found = 0;
10643 curB = curWild->nsSet;
10644 while (curB != NULL) {
10645 if (cur->value == curB->value) {
10646 found = 1;
10647 break;
10648 }
10649 curB = curB->next;
10650 }
10651 if (!found)
10652 break;
10653 cur = cur->next;
10654 }
10655 if (found)
10656 return(0);
10657 } else
10658 return(0);
10659 }
10660 }
10661 /*
10662 * 2 If either O1 or O2 is any, then the other must be the value.
10663 */
10664 if ((completeWild->any != curWild->any) && (completeWild->any)) {
10665 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
10666 return(-1);
10667 return(0);
10668 }
10669 /*
10670 * 3 If either O1 or O2 is a pair of not and a value (a namespace
10671 * name or ·absent·) and the other is a set of (namespace names or
10672 * ·absent·), then that set, minus the negated value if it was in
10673 * the set, minus ·absent· if it was in the set, must be the value.
10674 */
10675 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
10676 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
10677 const xmlChar *neg;
10678
10679 if (completeWild->nsSet == NULL) {
10680 neg = completeWild->negNsSet->value;
10681 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
10682 return(-1);
10683 } else
10684 neg = curWild->negNsSet->value;
10685 /*
10686 * Remove absent and negated.
10687 */
10688 prev = NULL;
10689 cur = completeWild->nsSet;
10690 while (cur != NULL) {
10691 if (cur->value == NULL) {
10692 if (prev == NULL)
10693 completeWild->nsSet = cur->next;
10694 else
10695 prev->next = cur->next;
10696 xmlFree(cur);
10697 break;
10698 }
10699 prev = cur;
10700 cur = cur->next;
10701 }
10702 if (neg != NULL) {
10703 prev = NULL;
10704 cur = completeWild->nsSet;
10705 while (cur != NULL) {
10706 if (cur->value == neg) {
10707 if (prev == NULL)
10708 completeWild->nsSet = cur->next;
10709 else
10710 prev->next = cur->next;
10711 xmlFree(cur);
10712 break;
10713 }
10714 prev = cur;
10715 cur = cur->next;
10716 }
10717 }
10718
10719 return(0);
10720 }
10721 /*
10722 * 4 If both O1 and O2 are sets of (namespace names or ·absent·),
10723 * then the intersection of those sets must be the value.
10724 */
10725 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
10726 int found;
10727
10728 cur = completeWild->nsSet;
10729 prev = NULL;
10730 while (cur != NULL) {
10731 found = 0;
10732 curB = curWild->nsSet;
10733 while (curB != NULL) {
10734 if (cur->value == curB->value) {
10735 found = 1;
10736 break;
10737 }
10738 curB = curB->next;
10739 }
10740 if (!found) {
10741 if (prev == NULL)
10742 completeWild->nsSet = cur->next;
10743 else
10744 prev->next = cur->next;
10745 tmp = cur->next;
10746 xmlFree(cur);
10747 cur = tmp;
10748 continue;
10749 }
10750 prev = cur;
10751 cur = cur->next;
10752 }
10753
10754 return(0);
10755 }
10756 /* 5 If the two are negations of different namespace names,
10757 * then the intersection is not expressible
10758 */
10759 if ((completeWild->negNsSet != NULL) &&
10760 (curWild->negNsSet != NULL) &&
10761 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
10762 (completeWild->negNsSet->value != NULL) &&
10763 (curWild->negNsSet->value != NULL)) {
10764
10765 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010766 "The intersection of the wilcard is not expressible.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +000010767 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000010768 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +000010769 }
10770 /*
10771 * 6 If the one is a negation of a namespace name and the other
10772 * is a negation of ·absent·, then the one which is the negation
10773 * of a namespace name must be the value.
10774 */
10775 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
10776 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
10777 (completeWild->negNsSet->value == NULL)) {
10778 completeWild->negNsSet->value = curWild->negNsSet->value;
10779 }
10780 return(0);
10781}
10782
Daniel Veillard50355f02004-06-08 17:52:16 +000010783/**
10784 * xmlSchemaIsWildcardNsConstraintSubset:
10785 * @ctxt: the schema parser context
10786 * @wildA: the first wildcard
10787 * @wildB: the second wildcard
10788 *
10789 * Returns 1 if the namespace constraint of @wildA is an intensional
10790 * subset of @wildB, 0 otherwise.
10791 */
10792static int
Daniel Veillardc0826a72004-08-10 14:17:33 +000010793xmlSchemaIsWildcardNsConstraintSubset(xmlSchemaWildcardPtr wildA,
10794 xmlSchemaWildcardPtr wildB)
Daniel Veillard50355f02004-06-08 17:52:16 +000010795{
Daniel Veillard3646d642004-06-02 19:19:14 +000010796
Daniel Veillard50355f02004-06-08 17:52:16 +000010797 /*
10798 * Schema Component Constraint: Wildcard Subset
10799 */
10800 /*
10801 * 1 super must be any.
10802 */
10803 if (wildB->any)
10804 return (1);
10805 /*
10806 * 2.1 sub must be a pair of not and a namespace name or ·absent·.
10807 * 2.2 super must be a pair of not and the same value.
10808 */
10809 if ((wildA->negNsSet != NULL) &&
10810 (wildB->negNsSet != NULL) &&
10811 (wildA->negNsSet->value == wildA->negNsSet->value))
10812 return (1);
10813 /*
10814 * 3.1 sub must be a set whose members are either namespace names or ·absent·.
10815 */
10816 if (wildA->nsSet != NULL) {
10817 /*
10818 * 3.2.1 super must be the same set or a superset thereof.
10819 */
10820 if (wildB->nsSet != NULL) {
10821 xmlSchemaWildcardNsPtr cur, curB;
10822 int found = 0;
10823
10824 cur = wildA->nsSet;
10825 while (cur != NULL) {
10826 found = 0;
10827 curB = wildB->nsSet;
10828 while (curB != NULL) {
10829 if (cur->value == curB->value) {
10830 found = 1;
10831 break;
10832 }
10833 curB = curB->next;
10834 }
10835 if (!found)
10836 return (0);
10837 cur = cur->next;
10838 }
10839 if (found)
10840 return (1);
10841 } else if (wildB->negNsSet != NULL) {
10842 xmlSchemaWildcardNsPtr cur;
10843 /*
10844 * 3.2.2 super must be a pair of not and a namespace name or
10845 * ·absent· and that value must not be in sub's set.
10846 */
10847 cur = wildA->nsSet;
10848 while (cur != NULL) {
10849 if (cur->value == wildB->negNsSet->value)
10850 return (0);
10851 cur = cur->next;
10852 }
10853 return (1);
10854 }
10855 }
10856 return (0);
10857}
10858
10859/**
10860 * xmlSchemaBuildCompleteAttributeWildcard:
10861 * @ctxt: the schema parser context
10862 * @attrs: the attribute list
10863 * @completeWild: the resulting complete wildcard
10864 *
10865 * Returns -1 in case of an internal error, 0 otherwise.
10866 */
10867static int
10868xmlSchemaBuildCompleteAttributeWildcard(xmlSchemaParserCtxtPtr ctxt,
10869 xmlSchemaAttributePtr attrs,
10870 xmlSchemaWildcardPtr *completeWild)
Daniel Veillard3646d642004-06-02 19:19:14 +000010871{
10872 while (attrs != NULL) {
10873 if (attrs->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
10874 xmlSchemaAttributeGroupPtr group;
10875
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010876 group = (xmlSchemaAttributeGroupPtr) attrs;
10877 /*
10878 * Handle attribute group references.
10879 */
10880 if (group->ref != NULL) {
10881 if (group->refItem == NULL) {
10882 /*
10883 * TODO: Should we raise a warning here?
10884 */
10885 /*
10886 * The referenced attribute group definition could not
10887 * be resolved beforehand, so skip.
10888 */
10889 attrs = attrs->next;
10890 continue;
10891 } else
10892 group = group->refItem;
10893 }
10894 /*
10895 * For every attribute group definition, an intersected wildcard
10896 * will be created (assumed that a wildcard exists on the
10897 * particular attr. gr. def. or on any contained attr. gr. def
10898 * at all).
10899 * The flag XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED ensures
10900 * that the intersection will be performed only once.
10901 */
Daniel Veillard3646d642004-06-02 19:19:14 +000010902 if ((group->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
10903 if (group->attributes != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000010904 if (xmlSchemaBuildCompleteAttributeWildcard(ctxt,
10905 group->attributes, &group->attributeWildcard) == -1)
10906 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000010907 }
10908 group->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
10909 }
10910 if (group->attributeWildcard != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000010911 if (*completeWild == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000010912 /*
10913 * Copy the first encountered wildcard as context, except for the annotation.
10914 */
Daniel Veillard50355f02004-06-08 17:52:16 +000010915 *completeWild = xmlSchemaAddWildcard(ctxt);
10916 (*completeWild)->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
10917 if (xmlSchemaCloneWildcardNsConstraints(ctxt,
10918 completeWild, group->attributeWildcard) == -1)
10919 return (-1);
10920 (*completeWild)->processContents = group->attributeWildcard->processContents;
Daniel Veillard3646d642004-06-02 19:19:14 +000010921 /*
10922 * Although the complete wildcard might not correspond to any
10923 * node in the schema, we will save this context node.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010924 * TODO: Hmm, is this sane?
Daniel Veillard3646d642004-06-02 19:19:14 +000010925 */
Daniel Veillard50355f02004-06-08 17:52:16 +000010926 (*completeWild)->node = group->attributeWildcard->node;
10927
10928 } else if (xmlSchemaIntersectWildcards(ctxt, *completeWild, group->attributeWildcard) == -1) {
10929 xmlSchemaFreeWildcard(*completeWild);
10930 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000010931 }
10932 }
10933 }
10934 attrs = attrs->next;
10935 }
10936
Daniel Veillard50355f02004-06-08 17:52:16 +000010937 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000010938}
10939
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010940static int
10941xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributePtr item,
10942 int *fixed,
10943 const xmlChar **value,
10944 xmlSchemaValPtr *val)
10945{
10946 *fixed = 0;
10947 *value = NULL;
10948 if (val != 0)
10949 *val = NULL;
10950
10951 if (item->defValue == NULL)
10952 item = item->refDecl;
10953
10954 if (item == NULL)
10955 return (0);
10956
10957 if (item->defValue != NULL) {
10958 *value = item->defValue;
10959 if (val != 0)
10960 *val = item->defVal;
10961 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
10962 *fixed = 1;
10963 return (1);
10964 }
10965 return (0);
10966}
Daniel Veillard3646d642004-06-02 19:19:14 +000010967/**
10968 * xmlSchemaMatchesWildcardNs:
10969 * @wild: the wildcard
10970 * @ns: the namespace
10971 *
10972 *
10973 * Returns 1 if the given namespace matches the wildcard,
10974 * 0 otherwise.
10975 */
10976static int
10977xmlSchemaMatchesWildcardNs(xmlSchemaWildcardPtr wild, const xmlChar* ns)
10978{
10979 if (wild == NULL)
10980 return(0);
10981
10982 if (wild->any)
10983 return(1);
10984 else if (wild->nsSet != NULL) {
10985 xmlSchemaWildcardNsPtr cur;
10986
10987 cur = wild->nsSet;
10988 while (cur != NULL) {
10989 if (xmlStrEqual(cur->value, ns))
10990 return(1);
10991 cur = cur->next;
10992 }
10993 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
10994 (!xmlStrEqual(wild->negNsSet->value, ns)))
10995 return(1);
10996
10997 return(0);
10998}
10999
11000/**
11001 * xmlSchemaBuildAttributeValidation:
11002 * @ctxt: the schema parser context
11003 * @type: the complex type definition
11004 *
11005 *
11006 * Builds the wildcard and the attribute uses on the given complex type.
11007 * Returns -1 if an internal error occurs, 0 otherwise.
11008 */
11009static int
11010xmlSchemaBuildAttributeValidation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaTypePtr type)
11011{
11012 xmlSchemaTypePtr baseType = NULL;
11013 xmlSchemaAttributeLinkPtr cur, base, tmp, id = NULL, prev = NULL, uses = NULL,
William M. Brack803812b2004-06-03 02:11:24 +000011014 lastUse = NULL, lastBaseUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000011015 xmlSchemaAttributePtr attrs;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011016 xmlSchemaTypePtr anyType;
Daniel Veillard50355f02004-06-08 17:52:16 +000011017 int baseIsAnyType = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011018 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000011019 int err = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000011020
Daniel Veillard01fa6152004-06-29 17:04:39 +000011021 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Daniel Veillard3646d642004-06-02 19:19:14 +000011022 /*
11023 * Complex Type Definition with complex content Schema Component.
11024 *
11025 * Attribute uses.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011026 * TODO: Add checks for absent referenced attribute declarations and
11027 * simple types.
Daniel Veillard3646d642004-06-02 19:19:14 +000011028 */
11029 if (type->attributeUses != NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011030 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011031 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillard3646d642004-06-02 19:19:14 +000011032 "attribute uses already builded.\n",
11033 NULL, NULL);
11034 return (-1);
11035 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011036 if (type->baseType == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011037 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011038 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011039 "complex type '%s' has no base type.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011040 type->name, NULL);
11041 return (-1);
11042 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011043 baseType = type->baseType;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011044 if (baseType == anyType)
11045 baseIsAnyType = 1;
11046 /*
11047 * Inherit the attribute uses of the base type.
11048 */
11049 /*
11050 * NOTE: It is allowed to "extend" the anyType complex type.
11051 */
11052 if (!baseIsAnyType) {
11053 if (baseType != NULL) {
11054 for (cur = baseType->attributeUses; cur != NULL; cur = cur->next) {
11055 tmp = (xmlSchemaAttributeLinkPtr)
11056 xmlMalloc(sizeof(xmlSchemaAttributeLink));
11057 if (tmp == NULL) {
11058 xmlSchemaPErrMemory(ctxt,
11059 "building attribute uses of complexType", NULL);
11060 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000011061 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011062 tmp->attr = cur->attr;
11063 tmp->next = NULL;
11064 if (type->attributeUses == NULL) {
11065 type->attributeUses = tmp;
11066 } else
11067 lastBaseUse->next = tmp;
11068 lastBaseUse = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000011069 }
11070 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011071 }
11072 if ((type->subtypes != NULL) &&
11073 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
11074 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011075 /*
11076 * type --> (<simpleContent>|<complexContent>)
11077 * --> (<restriction>|<extension>) --> attributes
11078 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011079 attrs = type->subtypes->subtypes->attributes;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011080 } else {
11081 /* Short hand form of the complexType. */
11082 attrs = type->attributes;
11083 }
11084 /*
11085 * Handle attribute wildcards.
11086 */
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000011087 err = xmlSchemaBuildCompleteAttributeWildcard(ctxt,
11088 attrs, &type->attributeWildcard);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011089 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011090 * NOTE: During the parse time, the wildcard is created on the complexType
11091 * directly, if encountered in a <restriction> or <extension> element.
Daniel Veillard01fa6152004-06-29 17:04:39 +000011092 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011093 if (err == -1) {
11094 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
11095 "Internal error: xmlSchemaBuildAttributeValidation: "
11096 "failed to build an intersected attribute wildcard.\n",
11097 NULL, NULL);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000011098 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011099 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011100
11101 if ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
11102 ((baseIsAnyType) ||
11103 ((baseType != NULL) &&
11104 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
11105 (baseType->attributeWildcard != NULL)))) {
11106 if (type->attributeWildcard != NULL) {
11107 /*
11108 * Union the complete wildcard with the base wildcard.
11109 */
11110 if (xmlSchemaUnionWildcards(ctxt, type->attributeWildcard,
11111 baseType->attributeWildcard) == -1)
11112 return (-1);
11113 } else {
11114 /*
11115 * Just inherit the wildcard.
11116 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011117 /*
11118 * NOTE: This is the only case where an attribute
11119 * wildcard is shared.
11120 */
11121 if (type->flags & XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD)
11122 type->flags ^= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011123 type->attributeWildcard = baseType->attributeWildcard;
Daniel Veillard50355f02004-06-08 17:52:16 +000011124 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011125 }
11126
11127 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
11128 if (type->attributeWildcard != NULL) {
11129 /*
11130 * Derivation Valid (Restriction, Complex)
11131 * 4.1 The {base type definition} must also have one.
11132 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011133 if (baseType->attributeWildcard == NULL) {
11134 xmlSchemaPCustomErr(ctxt,
11135 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
11136 NULL, type, NULL,
11137 "The type has an attribute wildcard, "
11138 "but the base type %s does not have one",
11139 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11140 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011141 return (1);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011142 } else if (xmlSchemaIsWildcardNsConstraintSubset(
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011143 type->attributeWildcard, baseType->attributeWildcard) == 0) {
11144 /* 4.2 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011145 xmlSchemaPCustomErr(ctxt,
11146 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
11147 NULL, type, NULL,
11148 "The attribute wildcard is not a valid "
11149 "subset of the wildcard in the base type %s",
11150 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11151 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011152 return (1);
11153 }
11154 /* 4.3 Unless the {base type definition} is the ·ur-type
11155 * definition·, the complex type definition's {attribute
11156 * wildcard}'s {process contents} must be identical to or
11157 * stronger than the {base type definition}'s {attribute
11158 * wildcard}'s {process contents}, where strict is stronger
11159 * than lax is stronger than skip.
11160 */
11161 if ((type->baseType != anyType) &&
11162 (type->attributeWildcard->processContents <
11163 baseType->attributeWildcard->processContents)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011164 xmlSchemaPCustomErr(ctxt,
11165 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
11166 NULL, type, NULL,
11167 "The 'process contents' of the attribute wildcard is weaker than "
11168 "the one in the base type %s",
11169 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11170 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011171 return (1);
11172 }
11173 }
11174 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
11175 /*
11176 * Derivation Valid (Extension)
11177 * At this point the type and the base have both, either
11178 * no wildcard or a wildcard.
11179 */
11180 if ((baseType->attributeWildcard != NULL) &&
11181 (baseType->attributeWildcard != type->attributeWildcard)) {
11182 /* 1.3 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011183 if (xmlSchemaIsWildcardNsConstraintSubset(
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011184 baseType->attributeWildcard, type->attributeWildcard) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011185 xmlSchemaPCustomErr(ctxt,
11186 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
11187 NULL, type, NULL,
11188 "The attribute wildcard is not a valid "
11189 "superset of the one in the base type %s",
11190 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11191 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011192 return (1);
11193 }
11194 }
11195 }
11196
Daniel Veillard3646d642004-06-02 19:19:14 +000011197 /*
11198 * Gather attribute uses defined by this type.
11199 */
11200 if (attrs != NULL) {
11201 if (xmlSchemaBuildAttributeUsesOwned(ctxt, attrs,
11202 &uses, &lastUse) == -1) {
11203 return (-1);
11204 }
11205 }
11206 /* 3.4.6 -> Complex Type Definition Properties Correct 4.
11207 * "Two distinct attribute declarations in the {attribute uses} must
11208 * not have identical {name}s and {target namespace}s."
11209 *
11210 * For "extension" this is done further down.
11211 */
11212 if ((uses != NULL) && ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
11213 cur = uses;
11214 while (cur != NULL) {
11215 tmp = cur->next;
11216 while (tmp != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011217 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
11218 xmlSchemaGetAttrName(tmp->attr))) &&
11219 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
11220 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
11221
11222 xmlSchemaPAttrUseErr(ctxt,
11223 XML_SCHEMAP_CT_PROPS_CORRECT_4,
11224 NULL, type, NULL, cur->attr,
11225 "Duplicate attribute use %s specified",
11226 xmlSchemaFormatNsUriLocal(&str,
11227 xmlSchemaGetAttrTargetNsURI(tmp->attr),
11228 xmlSchemaGetAttrName(tmp->attr))
11229 );
11230 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000011231 break;
11232 }
11233 tmp = tmp->next;
11234 }
11235 cur = cur->next;
11236 }
11237 }
11238 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
11239 /*
11240 * Derive by restriction.
11241 */
11242 if (baseIsAnyType) {
11243 type->attributeUses = uses;
11244 } else {
11245 int found;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011246 const xmlChar *bEffValue;
11247 int effFixed;
Daniel Veillard3646d642004-06-02 19:19:14 +000011248
11249 cur = uses;
11250 while (cur != NULL) {
11251 found = 0;
11252 base = type->attributeUses;
11253 while (base != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011254 if (xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
11255 xmlSchemaGetAttrName(base->attr)) &&
11256 xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
11257 xmlSchemaGetAttrTargetNsURI(base->attr))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011258
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011259 found = 1;
11260
Daniel Veillard3646d642004-06-02 19:19:14 +000011261 if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
11262 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
11263 /*
11264 * derivation-ok-restriction 2.1.1
Daniel Veillardc0826a72004-08-10 14:17:33 +000011265 */
11266 xmlSchemaPAttrUseErr(ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000011267 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011268 NULL, type, NULL, cur->attr,
11269 "The 'optional' use is inconsistent with a matching "
11270 "'required' use of the base type", NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000011271 } else if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
11272 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
11273 /*
11274 * derivation-ok-restriction 3
11275 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011276 xmlSchemaPCustomErr(ctxt,
11277 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
11278 NULL, type, NULL,
11279 "A matching attribute use for the 'required' "
11280 "attribute use %s of the base type is missing",
11281 xmlSchemaFormatNsUriLocal(&str,
11282 xmlSchemaGetAttrTargetNsURI(base->attr),
11283 xmlSchemaGetAttrName(base->attr)));
11284 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000011285 } else {
11286 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011287 * 2.1.3 [Definition:] Let the effective value
11288 * constraint of an attribute use be its {value
11289 * constraint}, if present, otherwise its {attribute
11290 * declaration}'s {value constraint} .
11291 */
11292 xmlSchemaGetEffectiveValueConstraint(base->attr, &effFixed,
11293 &bEffValue, 0);
11294 /*
11295 * 2.1.3 ... one of the following must be true
11296 *
11297 * 2.1.3.1 B's ·effective value constraint· is
11298 * ·absent· or default.
11299 */
11300 if ((bEffValue != NULL) &&
11301 (effFixed == 1)) {
11302 const xmlChar *rEffValue = NULL;
11303
11304 xmlSchemaGetEffectiveValueConstraint(base->attr, &effFixed,
11305 &rEffValue, 0);
11306 /*
11307 * 2.1.3.2 R's ·effective value constraint· is
11308 * fixed with the same string as B's.
11309 */
11310 if ((effFixed == 0) ||
11311 (! xmlStrEqual(rEffValue, bEffValue))) {
11312 xmlSchemaPAttrUseErr(ctxt,
11313 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
11314 NULL, type, NULL, cur->attr,
11315 "The effective value constraint of the "
11316 "attribute use is inconsistent with "
11317 "its correspondent of the base type",
11318 NULL);
11319 }
11320 }
11321 /*
11322 * TODO: derivation-ok-restriction 2.1.2 ({type definition} must be validly derived)
11323 */
11324 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000011325 * Override the attribute use.
11326 */
11327 base->attr = cur->attr;
11328 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011329
Daniel Veillard3646d642004-06-02 19:19:14 +000011330 break;
11331 }
11332 base = base->next;
11333 }
11334
11335 if (!found) {
11336 if (cur->attr->occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
11337 /*
11338 * derivation-ok-restriction 2.2
11339 */
11340 if ((type->attributeWildcard != NULL) &&
11341 xmlSchemaMatchesWildcardNs(type->attributeWildcard,
11342 cur->attr->targetNamespace))
11343 found = 1;
11344
11345 if (!found) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011346 xmlSchemaPAttrUseErr(ctxt,
11347 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
11348 NULL, type, NULL, cur->attr,
11349 "Neither a matching attribute use, "
11350 "nor a matching wildcard in the base type does exist",
11351 NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000011352 } else {
11353 /*
11354 * Add the attribute use.
11355 *
11356 * Note that this may lead to funny derivation error reports, if
11357 * multiple equal attribute uses exist; but this is not
11358 * allowed anyway, and it will be reported beforehand.
11359 */
11360 tmp = cur;
11361 if (prev != NULL)
11362 prev->next = cur->next;
11363 else
11364 uses = cur->next;
11365 cur = cur->next;
11366 if (type->attributeUses == NULL) {
11367 type->attributeUses = tmp;
11368 } else
11369 lastBaseUse->next = tmp;
11370 lastBaseUse = tmp;
11371
11372 continue;
11373 }
11374 }
11375 }
11376 prev = cur;
11377 cur = cur->next;
11378 }
11379 if (uses != NULL)
11380 xmlSchemaFreeAttributeUseList(uses);
11381 }
11382 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
11383 /*
11384 * The spec allows only appending, and not other kinds of extensions.
11385 *
11386 * This ensures: Schema Component Constraint: Derivation Valid (Extension) : 1.2
11387 */
11388 if (uses != NULL) {
11389 if (type->attributeUses == NULL) {
11390 type->attributeUses = uses;
11391 } else
11392 lastBaseUse->next = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000011393 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011394 } else {
11395 /*
Daniel Veillard50355f02004-06-08 17:52:16 +000011396 * Derive implicitely from the ur-type.
11397 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011398 type->attributeUses = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000011399 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011400 /*
11401 * 3.4.6 -> Complex Type Definition Properties Correct
11402 */
11403 if (type->attributeUses != NULL) {
11404 cur = type->attributeUses;
11405 prev = NULL;
11406 while (cur != NULL) {
11407 /*
11408 * 4. Two distinct attribute declarations in the {attribute uses} must
11409 * not have identical {name}s and {target namespace}s.
Daniel Veillard50355f02004-06-08 17:52:16 +000011410 *
Daniel Veillard3646d642004-06-02 19:19:14 +000011411 * Note that this was already done for "restriction" and types derived from
11412 * the ur-type.
Daniel Veillard50355f02004-06-08 17:52:16 +000011413 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011414 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
11415 tmp = cur->next;
11416 while (tmp != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011417 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
11418 xmlSchemaGetAttrName(tmp->attr))) &&
11419 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
11420 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011421
Daniel Veillardc0826a72004-08-10 14:17:33 +000011422 xmlSchemaPAttrUseErr(ctxt,
11423 XML_SCHEMAP_CT_PROPS_CORRECT_4,
11424 NULL, type, NULL, tmp->attr,
11425 "Duplicate attribute use specified", NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000011426 break;
11427 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011428 tmp = tmp->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000011429 }
11430 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011431 /*
11432 * 5. Two distinct attribute declarations in the {attribute uses} must
11433 * not have {type definition}s which are or are derived from ID.
11434 */
11435 if ((cur->attr->subtypes != NULL) &&
Daniel Veillard01fa6152004-06-29 17:04:39 +000011436 (xmlSchemaIsDerivedFromBuiltInType(ctxt, (xmlSchemaTypePtr) cur->attr, XML_SCHEMAS_ID))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011437 if (id != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011438 xmlSchemaPAttrUseErr(ctxt,
11439 XML_SCHEMAP_CT_PROPS_CORRECT_5,
11440 NULL, type, NULL, cur->attr,
11441 "There must not exist more than one attribute use, "
11442 "declared of type 'ID' or derived from it",
11443 NULL);
11444 FREE_AND_NULL(str)
Daniel Veillard50355f02004-06-08 17:52:16 +000011445 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011446 id = cur;
11447 }
11448 /*
11449 * Remove "prohibited" attribute uses. The reason this is done at this late
11450 * stage is to be able to catch dublicate attribute uses. So we had to keep
11451 * prohibited uses in the list as well.
11452 */
11453 if (cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
11454 tmp = cur;
11455 if (prev == NULL)
11456 type->attributeUses = cur->next;
11457 else
11458 prev->next = cur->next;
11459 cur = cur->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000011460 xmlFree(tmp);
Daniel Veillard3646d642004-06-02 19:19:14 +000011461 } else {
11462 prev = cur;
11463 cur = cur->next;
11464 }
11465 }
11466 }
11467 /*
11468 * TODO: This check should be removed if we are 100% sure of
11469 * the base type attribute uses already being built.
11470 */
11471 if ((baseType != NULL) && (!baseIsAnyType) &&
11472 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
11473 (baseType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011474 xmlSchemaPErr(ctxt, baseType->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011475 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011476 "attribute uses not builded on base type '%s'.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +000011477 baseType->name, NULL);
11478 }
11479 return (0);
11480}
11481
11482/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000011483 * xmlSchemaTypeFinalContains:
11484 * @schema: the schema
11485 * @type: the type definition
11486 * @final: the final
11487 *
11488 * Evaluates if a type definition contains the given "final".
11489 * This does take "finalDefault" into account as well.
11490 *
11491 * Returns 1 if the type does containt the given "final",
11492 * 0 otherwise.
11493 */
11494static int
11495xmlSchemaTypeFinalContains(xmlSchemaPtr schema, xmlSchemaTypePtr type, int final)
11496{
11497 int tfinal = final, tflags = type->flags;
11498
11499 if (type == NULL)
11500 return (0);
11501 if (type->flags & XML_SCHEMAS_TYPE_FINAL_DEFAULT) {
11502 switch (final) {
11503 case XML_SCHEMAS_TYPE_FINAL_RESTRICTION:
11504 tfinal = XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
11505 break;
11506 case XML_SCHEMAS_TYPE_FINAL_EXTENSION:
11507 tfinal = XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
11508 break;
11509 case XML_SCHEMAS_TYPE_FINAL_LIST:
11510 tfinal = XML_SCHEMAS_FINAL_DEFAULT_LIST;
11511 break;
11512 case XML_SCHEMAS_TYPE_FINAL_UNION:
11513 tfinal = XML_SCHEMAS_FINAL_DEFAULT_UNION;
11514 break;
11515 }
11516 tflags = schema->flags;
11517 }
11518 if (tflags & tfinal)
11519 return (1);
11520 else
11521 return (0);
11522
11523}
11524
11525/**
11526 * xmlSchemaGetUnionSimpleTypeMemberTypes:
11527 * @type: the Union Simple Type
11528 *
11529 * Returns a list of member types of @type if existing,
11530 * returns NULL otherwise.
11531 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011532static xmlSchemaTypeLinkPtr
Daniel Veillard01fa6152004-06-29 17:04:39 +000011533xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
11534{
11535 while (type != NULL) {
11536 if (type->memberTypes != NULL)
11537 return (type->memberTypes);
11538 else
11539 type = type->baseType;
11540 }
11541 return (NULL);
11542}
11543
11544/**
11545 * xmlSchemaGetListSimpleTypeItemType:
11546 * @type: the simple type definition
11547 *
11548 * Returns the item type definition of the list simple type.
11549 */
11550static xmlSchemaTypePtr
11551xmlSchemaGetListSimpleTypeItemType(xmlSchemaTypePtr type)
11552{
11553 if ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)
11554 return (NULL);
11555 /*
11556 * Note: In libxml2, the built-in types do not reflect
11557 * the datatype hierarchy (yet?) - we have to treat them
11558 * in a special way.
11559 */
11560 if (type->type == XML_SCHEMA_TYPE_BASIC)
11561 return (xmlSchemaGetBuiltInListSimpleTypeItemType(type));
11562 if (type->subtypes->type == XML_SCHEMA_TYPE_LIST)
11563 /* 1 If the <list> alternative is chosen, then the type
11564 * definition ·resolved· to by the ·actual value· of the
11565 * itemType [attribute] of <list>, if present, otherwise
11566 * the type definition corresponding to the <simpleType>
11567 * among the [children] of <list>.
11568 */
11569 return (type->subtypes->subtypes);
11570 else {
11571 /* 2 If the <restriction> option is chosen, then the
11572 * {item type definition} of the {base type definition}.
11573 */
11574 return (xmlSchemaGetListSimpleTypeItemType(type->baseType));
11575 }
11576}
11577
11578/**
11579 * xmlSchemaCheckCOSSTDerivedOK:
11580 * @type: the derived simple type definition
11581 * @baseType: the base type definition
11582 *
11583 * Checks wheter @type can be validly
11584 * derived from @baseType.
11585 *
11586 * Returns 0 on success, an positive error code otherwise.
11587 */
11588static int
11589xmlSchemaCheckCOSSTDerivedOK(xmlSchemaPtr schema,
11590 xmlSchemaTypePtr type,
11591 xmlSchemaTypePtr baseType,
11592 int subset)
11593{
11594 /*
11595 * Schema Component Constraint: Type Derivation OK (Simple)
11596 *
11597 *
11598 * 1 They are the same type definition.
11599 * TODO: The identy check might have to be more complex than this.
11600 */
11601 if (type == baseType)
11602 return (0);
11603 /*
11604 * 2.1 restriction is not in the subset, or in the {final}
11605 * of its own {base type definition};
11606 */
11607 if ((subset & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) ||
11608 (xmlSchemaTypeFinalContains(schema,
11609 type->baseType, XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
11610 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
11611 }
11612 /* 2.2 */
11613 if (type->baseType == baseType) {
11614 /*
11615 * 2.2.1 D's ·base type definition· is B.
11616 */
11617 return (0);
11618 }
11619 /*
11620 * 2.2.2 D's ·base type definition· is not the ·ur-type definition·
11621 * and is validly derived from B given the subset, as defined by this
11622 * constraint.
11623 */
11624 if ((type->baseType != xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE)) &&
11625 (xmlSchemaCheckCOSSTDerivedOK(schema, type->baseType, baseType, subset) == 0)) {
11626 return (0);
11627 }
11628 /*
11629 * 2.2.3 D's {variety} is list or union and B is the ·simple ur-type
11630 * definition·.
11631 */
11632 if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
11633 (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)) &&
11634 (baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE))) {
11635 return (0);
11636 }
11637 /*
11638 * 2.2.4 B's {variety} is union and D is validly derived from a type
11639 * definition in B's {member type definitions} given the subset, as
11640 * defined by this constraint.
11641 *
11642 * NOTE: This seems not to involve built-in types, since there is no
11643 * built-in Union Simple Type.
11644 */
11645 if (baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
11646 xmlSchemaTypeLinkPtr cur;
11647
11648 cur = baseType->memberTypes;
11649 while (cur != NULL) {
11650 if (xmlSchemaCheckCOSSTDerivedOK(schema, type,
11651 cur->type, subset) == 0)
11652 return (0);
11653 cur = cur->next;
11654 }
11655 }
11656
11657 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
11658}
11659
11660
11661/**
11662 * xmlSchemaCheckSTPropsCorrect:
11663 * @ctxt: the schema parser context
11664 * @type: the simple type definition
11665 *
11666 * Checks st-props-correct.
11667 *
11668 * Returns 0 if the properties are correct,
11669 * if not, a positive error code and -1 on internal
11670 * errors.
11671 */
11672static int
11673xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
11674 xmlSchemaTypePtr type)
11675{
11676 xmlSchemaTypePtr baseType = type->baseType, anySimpleType,
11677 anyType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011678 xmlChar *str = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011679
Daniel Veillardc0826a72004-08-10 14:17:33 +000011680 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011681 /*
11682 * Schema Component Constraint: Simple Type Definition Properties Correct
11683 *
11684 * NOTE: This is somehow redundant, since we actually built a simple type
11685 * to have all the needed information; this acts as an self test.
11686 */
11687 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
11688 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
11689 /*
11690 * TODO: 1 The values of the properties of a simple type definition must be as
11691 * described in the property tableau in Datatype definition, modulo the
11692 * impact of Missing Sub-components (§5.3).
11693 */
11694 /* Base type: If the datatype has been ·derived· by ·restriction·
11695 * then the Simple Type Definition component from which it is ·derived·,
11696 * otherwise the Simple Type Definition for anySimpleType (§4.1.6).
11697 */
11698 if (baseType == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011699 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011700 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011701 NULL, type, NULL,
11702 "No base type existent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011703 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
11704 }
11705 if ((baseType->type != XML_SCHEMA_TYPE_SIMPLE) &&
11706 ((baseType->type != XML_SCHEMA_TYPE_BASIC) ||
11707 (baseType == anyType))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011708 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011709 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011710 NULL, type, NULL,
11711 "The base type %s is not a simple type",
11712 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11713 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011714 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
11715 }
11716 if ((baseType != anySimpleType) &&
11717 (type->subtypes->type != XML_SCHEMA_TYPE_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011718 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011719 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011720 NULL, type, NULL,
11721 "A type, derived by list or union, must have"
11722 "the simple ur-type definition as base type, not %s",
11723 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11724 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011725 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
11726 }
11727 /*
11728 * Variety: One of {atomic, list, union}.
11729 */
11730 if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
11731 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) &&
11732 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011733 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011734 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011735 NULL, type, NULL,
11736 "The variety is absent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011737 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
11738 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000011739 /* TODO: Finish this. Hmm, is this finished? */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011740
11741 /*
11742 * 2 All simple type definitions must be derived ultimately from the ·simple
11743 * ur-type definition (so· circular definitions are disallowed). That is, it
11744 * must be possible to reach a built-in primitive datatype or the ·simple
11745 * ur-type definition· by repeatedly following the {base type definition}.
11746 */
11747 baseType = type->baseType;
11748 while ((baseType != NULL) && (baseType->type != XML_SCHEMA_TYPE_BASIC)) {
11749 if (baseType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
11750 xmlSchemaTypeFixup(baseType, ctxt, NULL);
11751 if (baseType == anySimpleType)
11752 break;
11753 else if (baseType == type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011754 xmlSchemaPCustomErr(ctxt,
11755 XML_SCHEMAP_ST_PROPS_CORRECT_2,
11756 NULL, type, NULL,
11757 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011758 return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
11759 }
11760 baseType = baseType->baseType;
11761 }
11762 /*
11763 * 3 The {final} of the {base type definition} must not contain restriction.
11764 */
11765 if (xmlSchemaTypeFinalContains(ctxt->schema, baseType,
11766 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011767 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011768 XML_SCHEMAP_ST_PROPS_CORRECT_3,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011769 NULL, type, NULL,
11770 "The 'final' of its base type %s must not contain "
11771 "'restriction'",
11772 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11773 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011774 return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
11775 }
11776 return (0);
11777}
11778
11779/**
11780 * xmlSchemaCheckDerivationValidSimpleRestriction:
11781 * @ctxt: the schema parser context
11782 * @type: the simple type definition
11783 *
11784 * Checks if the given @type (simpleType) is derived
11785 * validly by restriction.
11786 *
11787 * Returns -1 on internal errors, 0 if the type is validly derived,
11788 * a positive error code otherwise.
11789 */
11790static int
11791xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011792 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011793{
Daniel Veillardc0826a72004-08-10 14:17:33 +000011794 xmlChar *str = NULL;
11795
11796 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011797
11798 if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
11799 xmlSchemaPErr(ctxt, type->node,
11800 XML_ERR_INTERNAL_ERROR,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011801 "xmlSchemaCheckDerivationValidSimpleRestriction: The given "
11802 "type '%s' is not a user-derived simpleType.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011803 type->name, NULL);
11804 return (-1);
11805 }
11806
11807 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
11808 xmlSchemaTypePtr primitive;
11809 /*
11810 * 1.1 The {base type definition} must be an atomic simple
11811 * type definition or a built-in primitive datatype.
11812 */
11813 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011814 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011815 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011816 NULL, type, NULL,
11817 "The base type %s is not an atomic simple type",
11818 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
11819 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011820 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
11821 }
11822 /* 1.2 The {final} of the {base type definition} must not contain
11823 * restriction.
11824 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011825 /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011826 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
11827 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011828 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011829 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011830 NULL, type, NULL,
11831 "The final of its base type %s must not contain 'restriction'",
11832 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
11833 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011834 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
11835 }
11836
11837 /*
11838 * 1.3.1 DF must be an allowed constraining facet for the {primitive
11839 * type definition}, as specified in the appropriate subsection of 3.2
11840 * Primitive datatypes.
11841 */
11842 if (type->facets != NULL) {
11843 xmlSchemaFacetPtr facet;
11844 int ok = 1;
11845
11846 primitive = xmlSchemaGetPrimitiveType(type);
11847 if (primitive == NULL) {
11848 xmlSchemaPErr(ctxt, type->node,
11849 XML_ERR_INTERNAL_ERROR,
11850 "xmlSchemaCheckDerivationValidSimpleRestriction: failed "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011851 "to get primitive type of type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011852 type->name, NULL);
11853 return (-1);
11854 }
11855 facet = type->facets;
11856 do {
11857 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011858 ok = 0;
11859 xmlSchemaPIllegalFacetAtomicErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011860 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011861 NULL, type, primitive, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011862 }
11863 facet = facet->next;
11864 } while (facet != NULL);
11865 if (ok == 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +000011866 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011867 }
11868 /*
11869 * TODO: 1.3.2 (facet derivation)
11870 */
11871 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
11872 xmlSchemaTypePtr itemType = NULL;
11873
11874 itemType = xmlSchemaGetListSimpleTypeItemType(type);
11875 if (itemType == NULL) {
11876 xmlSchemaPErr(ctxt, type->node,
11877 XML_ERR_INTERNAL_ERROR,
11878 "Internal error: xmlSchemaCheckDerivationValidSimpleRestriction: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011879 "failed to evaluate the item type of type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011880 type->name, NULL);
11881 return (-1);
11882 }
11883 /*
11884 * 2.1 The {item type definition} must have a {variety} of atomic or
11885 * union (in which case all the {member type definitions}
11886 * must be atomic).
11887 */
11888 if (((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
11889 ((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011890 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011891 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011892 NULL, type, NULL,
11893 "The item type %s must have a variety of atomic or union",
11894 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1));
11895 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011896 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
11897 } else if (itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
11898 xmlSchemaTypeLinkPtr member;
11899
11900 member = itemType->memberTypes;
11901 while (member != NULL) {
11902 if ((member->type->flags &
11903 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011904 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011905 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011906 NULL, type, NULL,
11907 "The item type is a union type, but the "
11908 "member type %s of this item type is not atomic",
11909 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
11910 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011911 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
11912 }
11913 member = member->next;
11914 }
11915 }
11916
11917 if (type->baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE)) {
11918 xmlSchemaFacetPtr facet;
11919 /*
11920 * This is the case if we have: <simpleType><list ..
11921 */
11922 /*
11923 * 2.3.1
11924 * 2.3.1.1 The {final} of the {item type definition} must not
11925 * contain list.
11926 */
11927 if (xmlSchemaTypeFinalContains(ctxt->schema,
11928 itemType, XML_SCHEMAS_TYPE_FINAL_LIST)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011929 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011930 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011931 NULL, type, NULL,
11932 "The final of its item type %s must not contain 'list'",
11933 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1));
11934 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011935 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
11936 }
11937 /*
11938 * 2.3.1.2 The {facets} must only contain the whiteSpace
11939 * facet component.
11940 */
11941 if (type->facets != NULL) {
11942 facet = type->facets;
11943 do {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011944 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
11945 xmlSchemaPIllegalFacetListUnionErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011946 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011947 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011948 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
11949 }
11950 facet = facet->next;
11951 } while (facet != NULL);
11952 }
11953 /*
11954 * TODO: Datatypes states:
11955 * A ·list· datatype can be ·derived· from an ·atomic· datatype
11956 * whose ·lexical space· allows space (such as string or anyURI)or
11957 * a ·union· datatype any of whose {member type definitions}'s
11958 * ·lexical space· allows space.
11959 */
11960 } else {
11961 /*
11962 * This is the case if we have: <simpleType><restriction ...
11963 */
11964 /*
11965 * 2.3.2
11966 * 2.3.2.1 The {base type definition} must have a {variety} of list.
11967 */
11968 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011969 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011970 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011971 NULL, type, NULL,
11972 "The base type %s must be a list type",
11973 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
11974 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011975 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
11976 }
11977 /*
11978 * 2.3.2.2 The {final} of the {base type definition} must not
11979 * contain restriction.
11980 */
11981 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
11982 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011983 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011984 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011985 NULL, type, NULL,
11986 "The final of the base type %s must not contain 'restriction'",
11987 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
11988 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011989 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
11990 }
11991 /*
11992 * 2.3.2.3 The {item type definition} must be validly derived
11993 * from the {base type definition}'s {item type definition} given
11994 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6).
11995 */
11996 {
11997 xmlSchemaTypePtr baseItemType;
11998
11999 baseItemType = xmlSchemaGetListSimpleTypeItemType(type->baseType);
12000 if (baseItemType == NULL) {
12001 xmlSchemaPErr(ctxt, type->node,
12002 XML_ERR_INTERNAL_ERROR,
12003 "xmlSchemaCheckDerivationValidSimpleRestriction: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012004 "List simple type '%s': Failed to "
12005 "evaluate the item type of its base type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012006 type->name, type->baseType->name);
12007 return (-1);
12008 }
12009 if ((itemType != baseItemType) &&
12010 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema, itemType,
12011 baseItemType, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012012 xmlChar *strBIT = NULL, *strBT = NULL;
12013 xmlSchemaPCustomErrExt(ctxt,
12014 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
12015 NULL, type, NULL,
12016 "The item type %s is not validly derived from the "
12017 "item type %s of the base type %s",
12018 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1),
12019 xmlSchemaFormatItemForReport(&strBIT, NULL, baseItemType, NULL, 1),
12020 xmlSchemaFormatItemForReport(&strBT, NULL, type->baseType, NULL, 1));
12021
12022 FREE_AND_NULL(str)
12023 FREE_AND_NULL(strBIT)
12024 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012025 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
12026 }
12027 }
12028
12029 if (type->facets != NULL) {
12030 xmlSchemaFacetPtr facet;
12031 int ok = 1;
12032 /*
12033 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
12034 * and enumeration facet components are allowed among the {facets}.
12035 */
12036 facet = type->facets;
12037 do {
12038 switch (facet->type) {
12039 case XML_SCHEMA_FACET_LENGTH:
12040 case XML_SCHEMA_FACET_MINLENGTH:
12041 case XML_SCHEMA_FACET_MAXLENGTH:
12042 case XML_SCHEMA_FACET_WHITESPACE:
12043 /*
12044 * TODO: 2.5.1.2 List datatypes
12045 * The value of ·whiteSpace· is fixed to the value collapse.
12046 */
12047 case XML_SCHEMA_FACET_PATTERN:
12048 case XML_SCHEMA_FACET_ENUMERATION:
12049 break;
12050 default: {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012051 xmlSchemaPIllegalFacetListUnionErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012052 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012053 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012054 /*
12055 * We could return, but it's nicer to report all
12056 * invalid facets.
12057 */
12058 ok = 0;
12059 }
12060 }
12061 facet = facet->next;
12062 } while (facet != NULL);
12063 if (ok == 0)
12064 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
12065 /*
12066 * TODO: 2.3.2.5 For each facet in the {facets} (call this DF), if there
12067 * is a facet of the same kind in the {facets} of the {base type
12068 * definition} (call this BF),then the DF's {value} must be a valid
12069 * restriction of BF's {value} as defined in [XML Schemas: Datatypes].
12070 */
12071 }
12072
12073
12074 }
12075 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
12076 /*
12077 * 3.1 The {member type definitions} must all have {variety} of
12078 * atomic or list.
12079 */
12080 xmlSchemaTypeLinkPtr member;
12081
12082 member = type->memberTypes;
12083 while (member != NULL) {
12084 if (((member->type->flags &
12085 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
12086 ((member->type->flags &
12087 XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012088 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012089 XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012090 NULL, type, NULL,
12091 "The member type %s is neither an atomic, nor a list type",
12092 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
12093 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012094 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
12095 }
12096 member = member->next;
12097 }
12098 /*
12099 * 3.3.1 If the {base type definition} is the ·simple ur-type
12100 * definition·
12101 */
12102 if (type->baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE)) {
12103 /*
12104 * 3.3.1.1 All of the {member type definitions} must have a
12105 * {final} which does not contain union.
12106 */
12107 member = type->memberTypes;
12108 while (member != NULL) {
12109 if (xmlSchemaTypeFinalContains(ctxt->schema, member->type,
12110 XML_SCHEMAS_TYPE_FINAL_UNION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012111 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012112 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012113 NULL, type, NULL,
12114 "The final of member type %s contains 'union'",
12115 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
12116 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012117 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
12118 }
12119 member = member->next;
12120 }
12121 /*
12122 * 3.3.1.2 The {facets} must be empty.
12123 */
12124 if (type->facetSet != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012125 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012126 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012127 NULL, type, NULL,
12128 "No facets allowed", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012129 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
12130 }
12131 } else {
12132 /*
12133 * 3.3.2.1 The {base type definition} must have a {variety} of union.
12134 */
12135 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012136 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012137 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012138 NULL, type, NULL,
12139 "The base type %s is not a union type",
12140 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
12141 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012142 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
12143 }
12144 /*
12145 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
12146 */
12147 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
12148 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012149 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012150 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012151 NULL, type, NULL,
12152 "The final of its base type %s must not contain 'restriction'",
12153 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
12154 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012155 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
12156 }
12157 /*
12158 * 3.3.2.3 The {member type definitions}, in order, must be validly
12159 * derived from the corresponding type definitions in the {base
12160 * type definition}'s {member type definitions} given the empty set,
12161 * as defined in Type Derivation OK (Simple) (§3.14.6).
12162 */
12163 {
12164 xmlSchemaTypeLinkPtr baseMember;
12165
12166 /*
12167 * OPTIMIZE: if the type is restricting, it has no local defined
12168 * member types and inherits the member types of the base type;
12169 * thus a check for equality can be skipped.
12170 */
12171 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000012172 * Even worse: I cannot see a scenario where a restricting
Daniel Veillard01fa6152004-06-29 17:04:39 +000012173 * union simple type can have other member types as the member
12174 * types of it's base type. This check seems not necessary with
12175 * respect to the derivation process in libxml2.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000012176 * But necessary if constructing types with an API.
Daniel Veillard01fa6152004-06-29 17:04:39 +000012177 */
12178 if (type->memberTypes != NULL) {
12179 member = type->memberTypes;
12180 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
12181 if ((member == NULL) && (baseMember != NULL)) {
12182 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012183 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012184 "Internal error: "
12185 "xmlSchemaCheckDerivationValidSimpleRestriction "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012186 "(3.3.2.3), union simple type '%s', unequal number "
Daniel Veillard01fa6152004-06-29 17:04:39 +000012187 "of member types in the base type\n",
12188 type->name, NULL);
12189 }
12190 while (member != NULL) {
12191 if (baseMember == NULL) {
12192 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012193 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012194 "Internal error: "
12195 "xmlSchemaCheckDerivationValidSimpleRestriction "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012196 "(3.3.2.3), union simple type '%s', unequal number "
12197 "of member types in the base type.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012198 type->name, NULL);
12199 }
12200 if ((member->type != baseMember->type) &&
12201 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema,
12202 member->type, baseMember->type, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012203 xmlChar *strBMT = NULL, *strBT = NULL;
12204
12205 xmlSchemaPCustomErrExt(ctxt,
12206 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
12207 NULL, type, NULL,
12208 "The member type %s is not validly derived from its "
12209 "corresponding member type %s of the base type %s",
12210 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1),
12211 xmlSchemaFormatItemForReport(&strBMT, NULL, baseMember->type, NULL, 1),
12212 xmlSchemaFormatItemForReport(&strBT, NULL, type->baseType, NULL, 1));
12213 FREE_AND_NULL(str)
12214 FREE_AND_NULL(strBMT)
12215 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012216 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
12217 }
12218 member = member->next;
12219 baseMember = baseMember->next;
12220 }
12221 }
12222 }
12223 /*
12224 * 3.3.2.4 Only pattern and enumeration facet components are
12225 * allowed among the {facets}.
12226 */
12227 if (type->facets != NULL) {
12228 xmlSchemaFacetPtr facet;
12229 int ok = 1;
12230
12231 facet = type->facets;
12232 do {
12233 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
12234 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012235 xmlSchemaPIllegalFacetListUnionErr(ctxt,
12236 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
12237 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012238 ok = 0;
12239 }
12240 facet = facet->next;
12241 } while (facet != NULL);
12242 if (ok == 0)
12243 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
12244
12245 }
12246 /*
12247 * TODO: 3.3.2.5 (facet derivation)
12248 */
12249 }
12250 }
12251
12252 return (0);
12253}
12254
12255/**
12256 * xmlSchemaCheckSRCSimpleType:
12257 * @ctxt: the schema parser context
12258 * @type: the simple type definition
12259 *
12260 * Checks crc-simple-type constraints.
12261 *
12262 * Returns 0 if the constraints are satisfied,
12263 * if not a positive error code and -1 on internal
12264 * errors.
12265 */
12266static int
12267xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
12268 xmlSchemaTypePtr type)
12269{
12270 /*
12271 * NOTE: src-simple-type 2-4 are redundant, since the checks
12272 * were are done for the corresponding <restriction>, <list> and <union>
12273 * elements, but W3C wants a <simpleType> error as well, so it gets one.
12274 * Maby this can be skipped in the future, if we get sure it's not needed.
12275 */
12276 if (type->subtypes == NULL) {
12277 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012278 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012279 "Internal error: xmlSchemaCheckSRCSimpleType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012280 "no subtype on simple type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012281 type->name, NULL);
12282 return (-1);
12283 }
12284 /*
12285 * src-simple-type.1 The corresponding simple type definition, if any,
12286 * must satisfy the conditions set out in Constraints on Simple Type
12287 * Definition Schema Components (§3.14.6).
12288 */
12289 if ((xmlSchemaCheckSTPropsCorrect(ctxt, type) != 0) ||
12290 (xmlSchemaCheckCOSSTRestricts(ctxt, type) != 0)) {
12291 /*
12292 * TODO: Removed this, since it got annoying to get an
12293 * extra error report, if anything failed until now.
12294 * Enable this if needed.
12295 */
12296 /*
12297 xmlSchemaPErr(ctxt, type->node,
12298 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012299 "Simple type '%s' does not satisfy the constraints "
Daniel Veillard01fa6152004-06-29 17:04:39 +000012300 "on simple type definitions.\n",
12301 type->name, NULL);
12302 */
12303 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_1);
12304 }
12305
12306 if (type->subtypes->type == XML_SCHEMA_TYPE_RESTRICTION) {
12307 /*
12308 * src-simple-type.2 If the <restriction> alternative is chosen,
12309 * either it must have a base [attribute] or a <simpleType> among its
12310 * [children], but not both.
12311 */
William M. Brack2f2a6632004-08-20 23:09:47 +000012312 /*
12313 * XML_SCHEMAP_SRC_SIMPLE_TYPE_2
12314 * NOTE: This was removed, since this will be already handled
12315 * in the parse function for <restriction>.
12316 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012317 } else if (type->subtypes->type == XML_SCHEMA_TYPE_LIST) {
12318 /* src-simple-type.3 If the <list> alternative is chosen, either it must have
12319 * an itemType [attribute] or a <simpleType> among its [children],
12320 * but not both.
12321 * NOTE: baseType is set to the local simple type definiton,
12322 * if existent, at parse time. This is a hack and not nice.
12323 */
William M. Brack2f2a6632004-08-20 23:09:47 +000012324 /*
12325 * TODO: Remove this, and add the check to the parse function of <list>.
12326 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012327 if (((type->subtypes->base == NULL) &&
12328 (type->baseType == NULL)) ||
12329 ((type->subtypes->base != NULL) &&
12330 (type->subtypes->baseType != NULL))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012331 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012332 XML_SCHEMAP_SRC_SIMPLE_TYPE_3,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012333 NULL, type, NULL,
12334 "Either the attribute 'itemType' or the <simpleType> child "
12335 "must be present on the <list> child ", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012336 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_3);
12337 }
12338
12339
12340 } else if (type->subtypes->type == XML_SCHEMA_TYPE_UNION) {
12341 xmlSchemaTypeLinkPtr member;
12342 xmlSchemaTypePtr ancestor, anySimpleType;
12343
12344 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
12345
12346 /* src-simple-type.4 Circular union type definition is disallowed. That is, if
12347 * the <union> alternative is chosen, there must not be any entries
12348 * in the memberTypes [attribute] at any depth which resolve to the
12349 * component corresponding to the <simpleType>.
12350 */
12351 member = type->memberTypes;
12352 while (member != NULL) {
12353 ancestor = member->type;
12354 while ((ancestor != NULL) && (ancestor->type != XML_SCHEMA_TYPE_BASIC)) {
12355 if (ancestor->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
12356 xmlSchemaTypeFixup(ancestor, ctxt, NULL);
12357 if (ancestor == anySimpleType)
12358 break;
12359 else if (ancestor == type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012360 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012361 XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012362 NULL, type, NULL,
12363 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012364 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
12365 } else if (ancestor->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
12366 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000012367 * TODO, FIXME: Although a list simple type must not have a union ST
Daniel Veillard01fa6152004-06-29 17:04:39 +000012368 * type as item type, which in turn has a list ST as member
12369 * type, we will assume this here as well, since this check
12370 * was not yet performed.
12371 */
12372
12373 }
12374 ancestor = ancestor->baseType;
12375 }
12376 member = member->next;
12377 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012378 }
12379
12380 return (0);
12381}
12382
William M. Brack2f2a6632004-08-20 23:09:47 +000012383#if 0 /* Not yet used code for CT schema validation */
12384static int
12385xmlSchemaCheckCVCSimpleType(xmlSchemaValidCtxtPtr ctxt,
12386 const xmlChar * value,
12387 xmlSchemaTypePtr type,
12388 int fireErrors)
12389{
12390 int ret;
12391 /*
12392 * 3.14.4 Simple Type Definition Validation Rules
12393 * Validation Rule: String Valid
12394 */
12395 /*
12396 * 1 It is schema-valid with respect to that definition as defined
12397 * by Datatype Valid in [XML Schemas: Datatypes].
12398 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012399 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type, value,
12400 fireErrors, 1, 1, 1);
William M. Brack2f2a6632004-08-20 23:09:47 +000012401 return (ret);
12402 /*
12403 * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
12404 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6), then
12405 * the string must be a ·declared entity name·.
12406 */
12407 /*
12408 * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
12409 * given the empty set, as defined in Type Derivation OK (Simple) (§3.14.6),
12410 * then every whitespace-delimited substring of the string must be a ·declared
12411 * entity name·.
12412 */
12413 /*
12414 * 2.3 otherwise no further condition applies.
12415 */
12416
12417 return (0);
12418}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012419#endif
12420
William M. Brack2f2a6632004-08-20 23:09:47 +000012421
12422static int
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012423xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
12424{
12425 if (vctxt->pctxt == NULL) {
12426 vctxt->pctxt =xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
12427 /* vctxt->pctxt = xmlSchemaNewParserCtxt("*"); */
12428 if (vctxt->pctxt == NULL) {
12429 xmlSchemaVErr(vctxt, NULL,
12430 XML_SCHEMAV_INTERNAL,
12431 "Internal error: xmlSchemaCreatePCtxtOnVCtxt, "
12432 "failed to create a temp. parser context.\n",
William M. Brack2f2a6632004-08-20 23:09:47 +000012433 NULL, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012434 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012435 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012436 /* TODO: Pass user data. */
12437 xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error, vctxt->warning, NULL);
12438 }
12439 return (0);
12440}
12441
12442static int
12443xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
12444{
12445 if (ctxt->vctxt == NULL) {
12446 ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
12447 if (ctxt->vctxt == NULL) {
12448 xmlSchemaPErr(ctxt, NULL,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012449 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012450 "Internal error: xmlSchemaCreatePCtxtOnVCtxt, "
12451 "failed to create a temp. validation context.\n",
12452 NULL, NULL);
12453 return (-1);
12454 }
12455 /* TODO: Pass user data. */
12456 xmlSchemaSetValidErrors(ctxt->vctxt, ctxt->error, ctxt->warning, NULL);
12457 }
12458 return (0);
12459}
12460
12461/**
12462 * xmlSchemaCheckCOSValidDefault:
12463 * @ctxt: the schema parser context
12464 * @type: the simple type definition
12465 * @value: the default value
12466 * @node: an optional node (the holder of the value)
12467 *
12468 * Checks the "cos-valid-default" constraints.
12469 *
12470 * Returns 0 if the constraints are satisfied,
12471 * if not, a positive error code and -1 on internal
12472 * errors.
12473 */
12474static int
12475xmlSchemaCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
12476 xmlSchemaValidCtxtPtr vctxt,
12477 xmlSchemaTypePtr type,
12478 const xmlChar *value,
12479 xmlNodePtr node)
12480{
12481 int ret = 0;
12482
12483 /*
12484 * cos-valid-default:
12485 * Schema Component Constraint: Element Default Valid (Immediate)
12486 * For a string to be a valid default with respect to a type
12487 * definition the appropriate case among the following must be true:
12488 */
12489 /*
12490 * NOTE: This has to work without a given node (the holder of the
12491 * value), since it should work on the component, i.e. an underlying
12492 * DOM must not be mandatory.
12493 */
12494 if ((pctxt == NULL) || (vctxt == NULL)) {
12495 xmlSchemaPErr(pctxt, node,
12496 XML_SCHEMAP_INTERNAL,
12497 "Internal error: xmlSchemaCheckCOSValidDefault, "
12498 "bad arguments: the parser and/or validation context is "
12499 "missing.\n",
12500 NULL, NULL);
12501 return (-1);
12502 }
12503 if IS_COMPLEX_TYPE(type) {
William M. Brack2f2a6632004-08-20 23:09:47 +000012504 /*
12505 * Complex type.
12506 *
12507 * 2.1 its {content type} must be a simple type definition or mixed.
12508 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012509 /*
12510 * TODO: Adjust this when the content type will be computed
12511 * correctly.
12512 */
12513 if ((type->contentType != XML_SCHEMA_CONTENT_SIMPLE) &&
12514 (type->contentType != XML_SCHEMA_CONTENT_BASIC) &&
12515 (type->contentType != XML_SCHEMA_CONTENT_MIXED)) {
12516 xmlSchemaPSimpleTypeErr(pctxt,
12517 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
12518 NULL, NULL, node,
12519 type, NULL, NULL,
12520 "If the type of a constraint value is complex, its content "
12521 "type must be mixed or a simple type",
12522 NULL, NULL);
12523 return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
12524 }
12525 if (type->contentType == XML_SCHEMA_CONTENT_MIXED) {
William M. Brack2f2a6632004-08-20 23:09:47 +000012526 /*
12527 * 2.2.2 If the {content type} is mixed, then the {content type}'s
12528 * particle must be ·emptiable· as defined by Particle Emptiable
12529 * (§3.9.6).
12530 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012531
William M. Brack2f2a6632004-08-20 23:09:47 +000012532 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012533 * URGENT TODO: Implement this.
William M. Brack2f2a6632004-08-20 23:09:47 +000012534 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012535 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000012536 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012537 }
12538 /*
12539 * 1 If the type definition is a simple type definition, then the string
12540 * must be ·valid· with respect to that definition as defined by String
12541 * Valid (§3.14.4).
12542 *
12543 * AND
12544 *
12545 * 2.2.1 If the {content type} is a simple type definition, then the
12546 * string must be ·valid· with respect to that simple type definition
12547 * as defined by String Valid (§3.14.4).
12548 */
12549 vctxt->node = node;
12550 vctxt->cur = NULL;
12551 ret = xmlSchemaValidateSimpleTypeValue(vctxt, type, value, 1, 1, 1, 0);
12552 /* ret = xmlSchemaCheckCVCSimpleType(vctxt, elemDecl->value, typeDef, 0); */
12553 if (ret < 0) {
12554 xmlSchemaPErr(pctxt, node,
12555 /* NOTNICE: error code: This function will be used during
12556 * schema construction and xsi:type validation.
12557 */
12558 XML_SCHEMAP_INTERNAL,
12559 "Internal error: xmlSchemaCheckCOSValidDefault, "
12560 "while validating a value constaint value.\n",
12561 NULL, NULL);
12562
12563 }
12564 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +000012565}
12566
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012567#if 0 /* Not yet used code for CT schema validation */
William M. Brack2f2a6632004-08-20 23:09:47 +000012568/**
12569 * xmlSchemaGetSTContentOfCT:
12570 * @ctxt: the schema parser context
12571 * @type: the complex type definition
12572 *
12573 *
12574 * Returns the corresponding simple type for the content of
12575 * the complex type.
12576 */
12577static xmlSchemaTypePtr
12578xmlSchemaGetSTContentOfCT(xmlSchemaParserCtxtPtr ctxt,
12579 xmlSchemaTypePtr type)
12580{
12581 xmlSchemaTypePtr orig = type, anyType;
12582
12583 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
12584 while ((type != NULL) && (type != anyType) &&
12585 (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
12586 if (type->type == XML_SCHEMA_TYPE_SIMPLE)
12587 return(type);
12588 type = type->baseType;
12589 }
12590 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012591 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000012592 NULL, orig, NULL,
12593 "Internal error: xmlSchemaGetSTContentTypeOfCT, "
12594 "no simple type for the content of complex type '%s' could be "
12595 "computed", orig->name);
12596 return (NULL);
12597}
12598
12599
William M. Brack2f2a6632004-08-20 23:09:47 +000012600
William M. Brack2f2a6632004-08-20 23:09:47 +000012601
12602/**
12603 * xmlSchemaCheckCOSCTExtends:
12604 * @ctxt: the schema parser context
12605 * @type: the complex type definition
12606 *
12607 * Schema Component Constraint: Derivation Valid (Extension)
12608 *
12609 * Returns 0 if the constraints are satisfied, a positive
12610 * error code if not and -1 if an internal error occured.
12611 */
12612static int
12613xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
12614 xmlSchemaTypePtr type)
12615{
12616 xmlSchemaTypePtr base;
12617 /*
12618 * 1 If the {base type definition} is a complex type definition,
12619 * then all of the following must be true:
12620 */
12621 base = type->baseType;
12622 if (base == NULL) {
12623 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012624 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000012625 NULL, type, NULL,
12626 "Internal error: xmlSchemaCheckCOSCTExtends, "
12627 "the complex type '%s' has no base type", type->name);
12628 return (-1);
12629 }
12630 if (base->type == XML_SCHEMA_TYPE_COMPLEX) {
12631 /*
12632 * 1.1 The {final} of the {base type definition} must not
12633 * contain extension.
12634 */
12635 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
12636 xmlSchemaPCustomErr(ctxt,
12637 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
12638 NULL, type, NULL,
12639 "The 'final' of the base type definition "
12640 "contains extension", NULL);
12641 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
12642 }
12643 /*
12644 * 1.2 Its {attribute uses} must be a subset of the {attribute uses}
12645 * of the complex type definition itself, that is, for every attribute
12646 * use in the {attribute uses} of the {base type definition}, there
12647 * must be an attribute use in the {attribute uses} of the complex
12648 * type definition itself whose {attribute declaration} has the same
12649 * {name}, {target namespace} and {type definition} as its attribute
12650 * declaration
12651 *
12652 * NOTE: This will be already satisfied by the way the attribute uses
12653 * are extended in xmlSchemaBuildAttributeValidation; thus this check
12654 * is not needed.
12655 */
12656
12657 /*
12658 * 1.3 If it has an {attribute wildcard}, the complex type definition
12659 * must also have one, and the base type definition's {attribute
12660 * wildcard}'s {namespace constraint} must be a subset of the complex
12661 * type definition's {attribute wildcard}'s {namespace constraint},
12662 * as defined by Wildcard Subset (§3.10.6).
12663 *
12664 * This is already checked in xmlSchemaBuildAttributeValidation; thus
12665 * this check is not needed.
12666 */
12667
12668 /*
12669 * 1.4 One of the following must be true:
12670 *
12671 * 1.4.1 The {content type} of the {base type definition} and the
12672 * {content type} of the complex type definition itself must be the same
12673 * simple type definition
12674 */
12675
12676
12677
12678 } else {
12679 /*
12680 * 2 If the {base type definition} is a simple type definition,
12681 * then all of the following must be true:
12682 */
12683 /*
12684 * 2.1 The {content type} must be the same simple type definition.
12685 */
12686 /*
12687 * 2.2 The {final} of the {base type definition} must not contain
12688 * extension
12689 */
12690 }
12691
12692}
12693
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012694static int
12695xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
12696 xmlSchemaTypePtr type)
12697{
12698 xmlSchemaTypePtr base, content;
12699 int OK = 0;
12700
12701 /*
12702 * TODO: Adjust the error codes here, as I used
12703 * XML_SCHEMAP_SRC_CT_1 only yet.
12704 */
12705 /*
12706 * Schema Representation Constraint:
12707 * Complex Type Definition Representation OK
12708 */
12709 base = type->baseType;
12710 if (base == NULL) {
12711 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL, NULL, type, NULL,
12712 "Internal error: xmlSchemaCheckSRCCT, '%s', no base type",
12713 type->name);
12714 return (-1);
12715 }
12716
12717 if (type->subtypes != NULL) {
12718 if (type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
12719 if IS_COMPLEX_TYPE(base) {
12720 /*
12721 * 1 If the <complexContent> alternative is chosen, the type definition
12722 * ·resolved· to by the ·actual value· of the base [attribute]
12723 * must be a complex type definition;
12724 */
12725 xmlSchemaPCustomErr(ctxt,
12726 XML_SCHEMAP_SRC_CT_1,
12727 NULL, type, NULL,
12728 "The base type is not a complex type", NULL);
12729 return (XML_SCHEMAP_SRC_CT_1);
12730 }
12731 } else if (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
12732
12733 if IS_SIMPLE_TYPE(base) {
12734 if (type->flags &
12735 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
12736 /*
12737 * 2.1.3 only if the <extension> alternative is also
12738 * chosen, a simple type definition.
12739 */
12740 /* TODO: Change error code to ..._SRC_CT_2_1_3. */
12741 xmlSchemaPCustomErr(ctxt,
12742 XML_SCHEMAP_SRC_CT_1,
12743 NULL, type, NULL,
12744 "A complex type (simple content) cannot restrict "
12745 "an other simple type",
12746 NULL);
12747 return (XML_SCHEMAP_SRC_CT_1);
12748 }
12749 OK = 1;
12750
12751 } else { /* if IS_SIMPLE_TYPE(base) */
12752 if (base->contentType = XML_SCHEMA_CONTENT_MIXED) {
12753 /*
12754 * 2.1.2 only if the <restriction> alternative is also
12755 * chosen, a complex type definition whose {content type}
12756 * is mixed and a particle emptyable.
12757 */
12758 /*
12759 * FIXME TODO: Check for *empiable particle* is missing.
12760 */
12761 if ((type->flags &
12762 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) == 0) {
12763 xmlSchemaPCustomErr(ctxt,
12764 XML_SCHEMAP_SRC_CT_1,
12765 NULL, type, NULL,
12766 "A complex type (simple content) cannot "
12767 "extend an other complex type which has a "
12768 "content type of: 'mixed' and emptiable particle",
12769 NULL);
12770 return (XML_SCHEMAP_SRC_CT_1);
12771 }
12772 /*
12773 * NOTE: This will be fired as well, if the base type
12774 * is *'anyType'*.
12775 * NOTE: type->subtypes->subtypes will be the
12776 * <restriction> item.
12777 */
12778 if (type->subtypes->subtypes == NULL) {
12779 /* Yes, this is paranoid programming. */
12780 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
12781 NULL, type, NULL,
12782 "Internal error: xmlSchemaCheckSRCCT, "
12783 "'%s', <simpleContent> has no <restriction>",
12784 type->name);
12785 return (-1);
12786 }
12787 /*
12788 * 2.2 If clause 2.1.2 above is satisfied, then there
12789 * must be a <simpleType> among the [children] of
12790 * <restriction>.
12791 */
12792 if (type->subtypes->subtypes->type !=
12793 XML_SCHEMA_TYPE_SIMPLE) {
12794 /* TODO: Change error code to ..._SRC_CT_2_2. */
12795 xmlSchemaPCustomErr(ctxt,
12796 XML_SCHEMAP_SRC_CT_1,
12797 NULL, type, NULL,
12798 "A <simpleType> is expected among the children "
12799 "of <restriction>", NULL);
12800 return (XML_SCHEMAP_SRC_CT_1);
12801 }
12802 OK = 1;
12803 } else { /* if (base->contentType = XML_SCHEMA_CONTENT_MIXED)*/
12804 /*
12805 * 2.1.1 a complex type definition whose {content type} is a
12806 * simple type definition;
12807 */
12808 if (base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) {
12809 xmlSchemaPCustomErr(ctxt,
12810 XML_SCHEMAP_SRC_CT_1,
12811 NULL, type, NULL,
12812 "A complex type (simple content) cannot "
12813 "be derived from the complex type '%s'",
12814 base->name);
12815 return (XML_SCHEMAP_SRC_CT_1);
12816 }
12817 content = base->contentTypeDef;
12818 if (content == NULL) {
12819 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
12820 NULL, type, NULL,
12821 "Internal error: xmlSchemaCheckSRCCT, "
12822 "'%s', base type has no content type",
12823 type->name);
12824 return (-1);
12825 }
12826 if (content->type != XML_SCHEMA_TYPE_SIMPLE) {
12827 xmlSchemaPCustomErr(ctxt,
12828 XML_SCHEMAP_SRC_CT_1,
12829 NULL, type, NULL,
12830 "A complex type (simple content) cannot "
12831 "be derived from the complex type '%s'",
12832 base->name);
12833 return (XML_SCHEMAP_SRC_CT_1);
12834 }
12835 }
12836 }
12837 }
12838 }
12839 /*
12840 * TODO: 3 The corresponding complex type definition component must
12841 * satisfy the conditions set out in Constraints on Complex Type
12842 * Definition Schema Components (§3.4.6);
12843 *
12844 * TODO: 4 If clause 2.2.1 or clause 2.2.2 in the correspondence specification
12845 * above for {attribute wildcard} is satisfied, the intensional
12846 * intersection must be expressible, as defined in Attribute Wildcard
12847 * Intersection (§3.10.6).
12848 */
12849
12850}
William M. Brack2f2a6632004-08-20 23:09:47 +000012851#endif
12852
Daniel Veillard01fa6152004-06-29 17:04:39 +000012853/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012854 * xmlSchemaGroupDefFixup:
12855 * @typeDecl: the schema model group definition
12856 * @ctxt: the schema parser context
12857 *
12858 * Fixes model group definitions.
12859 */
12860static void
12861xmlSchemaGroupDefFixup(xmlSchemaTypePtr group,
12862 xmlSchemaParserCtxtPtr ctxt,
12863 const xmlChar * name ATTRIBUTE_UNUSED)
12864{
12865 group->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
12866 if ((group->ref != NULL) && (group->subtypes == NULL)) {
12867 xmlSchemaTypePtr groupDef;
12868 /*
12869 * Resolve the reference.
12870 */
12871 groupDef = xmlSchemaGetGroup(ctxt->schema, group->ref,
12872 group->refNs);
12873 if (groupDef == NULL) {
12874 xmlSchemaPResCompAttrErr(ctxt,
12875 XML_SCHEMAP_SRC_RESOLVE,
12876 NULL, group, NULL,
12877 "ref", group->ref, group->refNs,
12878 XML_SCHEMA_TYPE_GROUP, NULL);
12879 return;
12880 }
12881 group->subtypes = groupDef;
12882 }
12883}
12884
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012885#if 0 /* Enable when the content type will be computed. */
12886static int
12887xmlSchemaComputeContentType(xmlSchemaParserCtxtPtr ctxt,
12888 xmlSchemaTypePtr type)
12889{
12890 xmlSchemaTypePtr base, res = NULL;
12891
12892 base = type->baseType;
12893 if (base == NULL) {
12894 xmlSchemaPCustomErr(ctxt,
12895 XML_SCHEMAP_INTERNAL,
12896 NULL, type, NULL,
12897 "Internal error: xmlSchemaGetContentType, "
12898 "the complex type '%s' has no base type", type->name);
12899 return (-1);
12900 }
12901 if (IS_ANYTYPE(base) || (type->subtypes->type ==
12902 XML_SCHEMA_TYPE_COMPLEX_CONTENT)) {
12903 xmlSchemaTypePtr start;
12904 /*
12905 * Effective 'mixed'.
12906 */
12907 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
12908 type->contentType = XML_SCHEMA_CONTENT_MIXED;
12909 /*
12910 * Effective content.
12911 */
12912 if (IS_ANYTYPE(base))
12913 start = type;
12914 else
12915 start = type->subtypes;
12916
12917 } else { /* if XML_SCHEMA_TYPE_COMPLEX_CONTENT */
12918 xmlSchemaTypePtr baseContentItem;
12919
12920 /*
12921 * Complex type with simple content.
12922 */
12923 if IS_COMPLEX_TYPE(base) {
12924 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
12925 /*
12926 * Summary: a complex type (simple content) can *restrict*
12927 * a complex type with the following content type:
12928 * 1. 'mixed' and an emptiable particle
12929 * 2. simple type
12930 */
12931 if (base->contentType == XML_SCHEMA_CONTENT_MIXED) {
12932 /*
12933 * 2 if the {content type} of the base type is mixed and a
12934 * particle which is ·emptiable·,
12935 * [...]
12936 * then starting from the simple type definition
12937 * corresponding to the <simpleType> among the [children]
12938 * of <restriction> (**which must be present**)
12939 *
12940 * FIXME TODO: Handle "emptiable particle".
12941 */
12942 res = type->subtypes->subtypes;
12943 if (res == NULL) {
12944 xmlSchemaPCustomErr(ctxt,
12945 XML_SCHEMAP_INTERNAL,
12946 NULL, type, NULL,
12947 "Internal error: xmlSchemaGetContentType, "
12948 "CT '%s' (restricting): <simpleContent> has no "
12949 "<restriction>",
12950 type->name);
12951 return (-1);
12952 }
12953
12954 res->subtypes;
12955 if (res == NULL) {
12956 xmlSchemaPCustomErr(ctxt,
12957 XML_SCHEMAP_INTERNAL,
12958 NULL, type, NULL,
12959 "Internal error: xmlSchemaGetContentType, "
12960 "CT '%s' (restricting): <restriction> has no "
12961 "mandatory <simpleType>",
12962 type->name);
12963 return (-1);
12964 }
12965 } else {
12966 baseContentItem = base->contentTypeDef;
12967 if (baseContentItem == NULL) {
12968 xmlSchemaPCustomErr(ctxt,
12969 XML_SCHEMAP_INTERNAL,
12970 NULL, type, NULL,
12971 "Internal error: xmlSchemaGetContentType, "
12972 "CT '%s' (restricting), the base type has no "
12973 "content type", type->name);
12974 return (-1);
12975 }
12976 if IS_SIMPLE_TYPE(baseContentItem) {
12977 /*
12978 * 1 If the base type is a complex type whose own
12979 * {content type} is a simple type and the <restriction>
12980 * alternative is chosen
12981 */
12982 /* type->subtypes->subtypes will be the restriction item.*/
12983 res = type->subtypes->subtypes;
12984 if (res == NULL) {
12985 xmlSchemaPCustomErr(ctxt,
12986 XML_SCHEMAP_INTERNAL,
12987 NULL, type, NULL,
12988 "Internal error: xmlSchemaGetContentType, "
12989 "CT '%s' (restricting): <simpleType> has no "
12990 "<restriction>", type->name);
12991 return (-1);
12992 }
12993 /*
12994 * 1.1 the simple type definition corresponding to the
12995 * <simpleType> among the [children] of <restriction>if
12996 * there is one;
12997 */
12998 res = res->subtypes;
12999 if (res == NULL) {
13000 /*
13001 * 1.2 otherwise the {content type}
13002 * of the base type .
13003 */
13004 res = baseContentItem;
13005 }
13006 }
13007 }
13008 /*
13009 * SPECIAL TODO: If *restricting* the spec wants us to
13010 * create an *additional* simple type which restricts the
13011 * located simple type; we won't do this yet, and look how
13012 * far we get with it.
13013 */
13014 } else { /* if XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION */
13015 /*
13016 * Summary: a complex type (simple content) can *extend*
13017 * only a complex base with a simple type as content.
13018 */
13019 /*
13020 * 3 If the type definition ·resolved· to by the ·actual
13021 * value· of the base [attribute] is a complex type
13022 * definition (whose own {content type} *must be* a simple
13023 * type definition, see below) and the *<extension>*
13024 * alternative is chosen, then the {content type} of that
13025 * complex type definition;
13026 */
13027 res = base->contentTypeDef;
13028 if (res == NULL) {
13029 xmlSchemaPCustomErr(ctxt,
13030 XML_SCHEMAP_INTERNAL,
13031 NULL, type, NULL,
13032 "Internal error: xmlSchemaGetContentType, "
13033 "CT '%s' (extending), the base type has no content "
13034 "type", type->name);
13035 return (-1);
13036 }
13037 if (! IS_SIMPLE_TYPE(res)) {
13038 xmlSchemaPCustomErr(ctxt,
13039 XML_SCHEMAP_INTERNAL,
13040 NULL, type, NULL,
13041 "Internal error: xmlSchemaGetContentType, "
13042 "CT '%s' (extending), the content type of the "
13043 "base is not a simple type", type->name);
13044 return (-1);
13045 }
13046 }
13047 } else /* if IS_COMPLEX_TYPE(base) */
13048 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
13049 /*
13050 * 4 otherwise (the type definition ·resolved· to by the
13051 * ·actual value· of the base [attribute] is a simple type
13052 * definition and the <extension> alternative is chosen),
13053 * then that simple type definition.
13054 */
13055 res = base;
13056 }
13057 type->contentTypeDef = res;
13058 if (res == NULL) {
13059 xmlSchemaPCustomErr(ctxt,
13060 XML_SCHEMAP_INTERNAL,
13061 NULL, type, NULL,
13062 "Internal error: xmlSchemaGetContentType, "
13063 "'%s', the content type could not be determined",
13064 type->name);
13065 return (-1);
13066 }
13067
13068 }
13069
13070}
13071#endif
13072
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013073/**
Daniel Veillard4255d502002-04-16 15:50:10 +000013074 * xmlSchemaTypeFixup:
13075 * @typeDecl: the schema type definition
13076 * @ctxt: the schema parser context
13077 *
13078 * Fixes the content model of the type.
13079 */
13080static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013081xmlSchemaTypeFixup(xmlSchemaTypePtr item,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013082 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000013083{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013084 xmlSchemaTypePtr ctxtType;
13085
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013086 if (item == NULL)
Daniel Veillard82bbbd42003-05-11 20:16:09 +000013087 return;
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013088 /*
13089 * Do not allow the following types to be typefixed, prior to
13090 * the corresponding simple/complex types.
13091 */
13092 if (ctxt->ctxtType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013093 switch (item->type) {
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013094 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
13095 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
13096 case XML_SCHEMA_TYPE_UNION:
13097 case XML_SCHEMA_TYPE_RESTRICTION:
13098 case XML_SCHEMA_TYPE_EXTENSION:
13099 return;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013100 default:
13101 break;
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013102 }
13103 }
Daniel Veillard4255d502002-04-16 15:50:10 +000013104 if (name == NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013105 name = item->name;
13106 if (item->contentType == XML_SCHEMA_CONTENT_UNKNOWN) {
13107 switch (item->type) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013108 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013109 if (item->subtypes != NULL) {
13110 if (item->subtypes->contentType ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013111 XML_SCHEMA_CONTENT_UNKNOWN) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013112 xmlSchemaTypeFixup(item->subtypes, ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013113 NULL);
13114 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013115 item->contentType =
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013116 XML_SCHEMA_CONTENT_SIMPLE;
13117 /* item->subtypes->contentType; */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013118 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013119 break;
13120 }
13121 case XML_SCHEMA_TYPE_RESTRICTION:{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013122 xmlSchemaTypePtr base = NULL;
13123
13124 ctxt->ctxtType->flags |=
13125 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013126 if (item->baseType != NULL)
13127 base = item->baseType;
13128 else if (item->base != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013129 base =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013130 xmlSchemaGetType(ctxt->schema, item->base,
13131 item->baseNs);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013132 if (base == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013133 xmlSchemaPResCompAttrErr(ctxt,
13134 XML_SCHEMAP_SRC_RESOLVE,
William M. Brack2f2a6632004-08-20 23:09:47 +000013135 NULL, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013136 (xmlNodePtr) xmlSchemaGetPropNode(item->node, "base"),
13137 "base", item->base, item->baseNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013138 XML_SCHEMA_TYPE_BASIC, "type definition");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013139 } else if (base->contentType ==
Daniel Veillard3646d642004-06-02 19:19:14 +000013140 XML_SCHEMA_CONTENT_UNKNOWN) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013141 xmlSchemaTypeFixup(base, ctxt, NULL);
13142 }
William M. Brack2f2a6632004-08-20 23:09:47 +000013143 }
13144 ctxt->ctxtType->baseType = base;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013145 if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX) {
13146 /*
13147 * ComplexType restriction.
William M. Brack2f2a6632004-08-20 23:09:47 +000013148 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013149 /*
13150 * Content type.
13151 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013152 if (item->subtypes == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013153 /* 1.1.1 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013154 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
13155 else if ((item->subtypes->subtypes == NULL) &&
13156 ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013157 XML_SCHEMA_TYPE_ALL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013158 || (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013159 XML_SCHEMA_TYPE_SEQUENCE)))
13160 /* 1.1.2 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013161 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
13162 else if ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013163 XML_SCHEMA_TYPE_CHOICE)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013164 && (item->subtypes->subtypes == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +000013165 /* 1.1.3 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013166 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013167 else {
13168 /* 1.2 and 2.X are applied at the other layer */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013169 item->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000013170 XML_SCHEMA_CONTENT_ELEMENTS;
13171 }
13172 } else {
13173 /*
13174 * SimpleType restriction.
13175 */
William M. Brack2f2a6632004-08-20 23:09:47 +000013176 /* TODO: Nothing? */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013177 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013178 break;
13179 }
13180 case XML_SCHEMA_TYPE_EXTENSION:{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013181 xmlSchemaTypePtr base = NULL;
13182 xmlSchemaContentType explicitContentType;
13183
13184 /*
13185 * An extension does exist on a complexType only.
13186 */
13187 ctxt->ctxtType->flags |=
13188 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013189 if (item->recurse) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013190 /* TODO: The word "recursive" should be changed to "circular" here. */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013191 xmlSchemaPCustomErr(ctxt,
13192 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013193 NULL, item, item->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013194 "This item is circular", NULL);
Daniel Veillard2582a332004-04-18 19:49:46 +000013195 return;
13196 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013197 if (item->base != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013198 base =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013199 xmlSchemaGetType(ctxt->schema, item->base,
13200 item->baseNs);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013201 if (base == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013202 xmlSchemaPResCompAttrErr(ctxt,
13203 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013204 NULL, item, item->node,
13205 "base", item->base, item->baseNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013206 XML_SCHEMA_TYPE_BASIC, "type definition");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013207 } else if (base->contentType ==
13208 XML_SCHEMA_CONTENT_UNKNOWN) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013209 item->recurse = 1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013210 xmlSchemaTypeFixup(base, ctxt, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013211 item->recurse = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013212 }
13213 /*
13214 * The type definition ·resolved· to by the ·actual
13215 * value· of the base [attribute]
13216 */
13217 ctxt->ctxtType->baseType = base;
13218 /*
13219 * TODO: This one is still needed for computation of
13220 * the content model by xmlSchemaBuildAContentModel.
13221 * Try to get rid of it.
13222 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013223 item->baseType = base;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013224 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013225 if ((item->subtypes != NULL) &&
13226 (item->subtypes->contentType == XML_SCHEMA_CONTENT_UNKNOWN))
13227 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013228
13229 explicitContentType = XML_SCHEMA_CONTENT_ELEMENTS;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013230 if (item->subtypes == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013231 /* 1.1.1 */
13232 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013233 else if ((item->subtypes->subtypes == NULL) &&
13234 ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013235 XML_SCHEMA_TYPE_ALL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013236 || (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013237 XML_SCHEMA_TYPE_SEQUENCE)))
13238 /* 1.1.2 */
13239 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013240 else if ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013241 XML_SCHEMA_TYPE_CHOICE)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013242 && (item->subtypes->subtypes == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +000013243 /* 1.1.3 */
13244 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
13245 if (base != NULL) {
13246 /* It will be reported later, if the base is missing. */
13247 if (explicitContentType == XML_SCHEMA_CONTENT_EMPTY) {
13248 /* 2.1 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013249 item->contentType = base->contentType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013250 } else if (base->contentType ==
13251 XML_SCHEMA_CONTENT_EMPTY) {
13252 /* 2.2 imbitable ! */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013253 item->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000013254 XML_SCHEMA_CONTENT_ELEMENTS;
13255 } else {
13256 /* 2.3 imbitable pareil ! */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013257 item->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000013258 XML_SCHEMA_CONTENT_ELEMENTS;
13259 }
13260 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013261 break;
13262 }
13263 case XML_SCHEMA_TYPE_COMPLEX:{
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013264 ctxtType = ctxt->ctxtType;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013265 ctxt->ctxtType = item;
13266 /*
13267 * Start with an empty content-type type.
13268 */
13269 if (item->subtypes == NULL)
13270 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
13271
13272 if ((item->subtypes == NULL) ||
13273 ((item->subtypes->type !=
Daniel Veillard01fa6152004-06-29 17:04:39 +000013274 XML_SCHEMA_TYPE_SIMPLE_CONTENT) &&
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013275 (item->subtypes->type !=
Daniel Veillard01fa6152004-06-29 17:04:39 +000013276 XML_SCHEMA_TYPE_COMPLEX_CONTENT))) {
13277 /*
13278 * This case is understood as shorthand for complex
13279 * content restricting the ur-type definition, and
13280 * the details of the mappings should be modified as
13281 * necessary.
13282 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013283 item->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
13284 item->flags |=
Daniel Veillard01fa6152004-06-29 17:04:39 +000013285 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013286 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013287 * Assume that we inherit the content-type type
13288 * from 'anyType', which is 'mixed' and a particle
13289 * emptiable.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013290 */
13291 item->contentType = item->baseType->contentType;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013292 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013293 /*
13294 * Fixup the sub components.
13295 */
13296 if ((item->subtypes != NULL) &&
13297 (item->subtypes->contentType ==
13298 XML_SCHEMA_CONTENT_UNKNOWN)) {
13299 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013300 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013301 if (item->flags & XML_SCHEMAS_TYPE_MIXED) {
13302 item->contentType = XML_SCHEMA_CONTENT_MIXED;
13303 } else if (item->subtypes != NULL) {
13304 /*
13305 * Use the content-type type of the model groups
13306 * defined, if 'mixed' is not set. If 'mixed' is set
13307 * it will expand the content-type by allowing character
13308 * content to appear.
13309 */
13310 item->contentType =
13311 item->subtypes->contentType;
13312 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013313
13314 /*
13315 * Some optimization for validation:
13316 * If there are no facets beside the "whitespace" facet,
13317 * then a value needs not to checked against against a
13318 * facet, thus no computed value is needed.
13319 * TODO URGENT: This is just a workaround, we need to
13320 * introduce the correct usage of contentType to store the
13321 * facets in!
13322 */
Daniel Veillardd3210bc2005-01-28 17:56:39 +000013323 if ((item->baseType != NULL) &&
13324 (item->baseType->flags &
13325 XML_SCHEMAS_TYPE_FACETSNEEDVALUE))
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013326 item->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
13327 else {
13328 xmlSchemaFacetLinkPtr cur;
13329
13330 for (cur = item->facetSet; cur != NULL;
13331 cur = cur->next) {
13332 if (cur->facet->type != XML_SCHEMA_FACET_WHITESPACE) {
13333 item->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
13334 break;
13335 }
13336 }
13337 }
13338
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013339 xmlSchemaBuildAttributeValidation(ctxt, item);
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000013340 xmlSchemaCheckDefaults(item, ctxt, item->name);
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013341 ctxt->ctxtType = ctxtType;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013342 break;
13343 }
13344 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013345 if (item->subtypes == NULL) {
13346 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
13347 if (item->flags & XML_SCHEMAS_TYPE_MIXED)
13348 item->contentType =
Daniel Veillard1aefc862004-03-04 11:40:48 +000013349 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013350 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013351 if (item->flags & XML_SCHEMAS_TYPE_MIXED) {
13352 item->contentType =
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013353 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillard3646d642004-06-02 19:19:14 +000013354 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013355 xmlSchemaTypeFixup(item->subtypes, ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013356 NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013357 if (item->subtypes != NULL)
13358 item->contentType =
13359 item->subtypes->contentType;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013360 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013361 /*
13362 * Removed due to implementation of the build of attribute uses.
13363 */
13364 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013365 if (item->attributes == NULL)
13366 item->attributes =
13367 item->subtypes->attributes;
Daniel Veillard3646d642004-06-02 19:19:14 +000013368 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013369 }
13370 break;
13371 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013372 case XML_SCHEMA_TYPE_SIMPLE:
13373 /*
13374 * Simple Type Definition Schema Component
13375 *
13376 */
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013377 ctxtType = ctxt->ctxtType;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013378 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
13379 if (item->subtypes->contentType ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013380 XML_SCHEMA_CONTENT_UNKNOWN) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013381 ctxt->ctxtType = item;
13382 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013383 }
13384 /* Fixup base type */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013385 if ((item->baseType != NULL) &&
13386 (item->baseType->contentType ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013387 XML_SCHEMA_CONTENT_UNKNOWN)) {
13388 /* OPTIMIZE: Actually this one will never by hit, since
13389 * the base type is already type-fixed in <restriction>.
13390 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013391 ctxt->ctxtType = item;
13392 xmlSchemaTypeFixup(item->baseType, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013393 }
13394 /* Base type:
13395 * 2 If the <list> or <union> alternative is chosen,
13396 * then the ·simple ur-type definition·.
13397 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013398 if (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013399 XML_SCHEMA_TYPE_LIST) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013400 item->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
13401 item->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
13402 } else if (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013403 XML_SCHEMA_TYPE_UNION) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013404 item->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
13405 item->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
13406 } else if (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013407 XML_SCHEMA_TYPE_RESTRICTION) {
13408 xmlSchemaFacetLinkPtr facet, cur, last = NULL;
13409
13410 /*
13411 * Variety
13412 * If the <restriction> alternative is chosen, then the
13413 * {variety} of the {base type definition}.
13414 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013415 if (item->baseType != NULL) {
13416 if (item->baseType->flags &
Daniel Veillard01fa6152004-06-29 17:04:39 +000013417 XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013418 item->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
13419 else if (item->baseType->flags &
Daniel Veillard01fa6152004-06-29 17:04:39 +000013420 XML_SCHEMAS_TYPE_VARIETY_LIST)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013421 item->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
13422 else if (item->baseType->flags &
Daniel Veillard01fa6152004-06-29 17:04:39 +000013423 XML_SCHEMAS_TYPE_VARIETY_UNION)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013424 item->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013425 /*
13426 * Schema Component Constraint: Simple Type Restriction
13427 * (Facets)
13428 * NOTE: Satisfaction of 1 and 2 arise from the fixup
13429 * applied beforehand.
13430 *
13431 * 3 The {facets} of R are the union of S and the {facets}
13432 * of B, eliminating duplicates. To eliminate duplicates,
13433 * when a facet of the same kind occurs in both S and the
13434 * {facets} of B, the one in the {facets} of B is not
13435 * included, with the exception of enumeration and pattern
13436 * facets, for which multiple occurrences with distinct values
13437 * are allowed.
13438 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013439 if (item->baseType->facetSet != NULL) {
13440 last = item->facetSet;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013441 if (last != NULL)
13442 while (last->next != NULL)
13443 last = last->next;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013444 cur = item->baseType->facetSet;
13445 for (; cur != NULL; cur = cur->next) {
13446 /*
13447 * Base patterns won't be add here:
13448 * they are ORed in a type and
13449 * ANDed in derived types. This will
13450 * happed at validation level by
13451 * walking the base axis of the type.
13452 */
13453 if (cur->facet->type ==
13454 XML_SCHEMA_FACET_PATTERN)
13455 continue;
13456 facet = NULL;
13457 if ((item->facetSet != NULL) &&
13458 /* REMOVED: a check for
13459 * XML_SCHEMA_FACET_PATTERN was already
13460 * performed above.
13461
13462 * (cur->facet->type !=
13463 * XML_SCHEMA_FACET_PATTERN) &&
Daniel Veillard01fa6152004-06-29 17:04:39 +000013464 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013465 (cur->facet->type !=
13466 XML_SCHEMA_FACET_ENUMERATION)) {
13467 facet = item->facetSet;
13468 do {
13469 if (cur->facet->type ==
13470 facet->facet->type)
13471 break;
13472 facet = facet->next;
13473 } while (facet != NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013474 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013475 if (facet == NULL) {
13476 facet = (xmlSchemaFacetLinkPtr)
13477 xmlMalloc(sizeof(xmlSchemaFacetLink));
13478 if (facet == NULL) {
13479 xmlSchemaPErrMemory(ctxt,
13480 "fixing simpleType", NULL);
13481 return;
13482 }
13483 /*
13484 * The facets are not copied but referenced
13485 * via the facet link.
13486 */
13487 facet->facet = cur->facet;
13488 facet->next = NULL;
13489 if (last == NULL)
13490 item->facetSet = facet;
13491 else
13492 last->next = facet;
13493 last = facet;
13494 }
13495 }
13496 }
13497 /*
13498 * Some optimization for validation:
13499 * If there are no facets beside the "whitespace" facet,
13500 * then a value needs not to checked against against a
13501 * facet, thus no computed value is needed.
13502 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000013503 if (item->baseType->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013504 item->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
13505 else {
13506 for (cur = item->facetSet; cur != NULL;
13507 cur = cur->next) {
13508 if (cur->facet->type != XML_SCHEMA_FACET_WHITESPACE) {
13509 item->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
13510 break;
13511 }
13512 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013513 }
13514 }
13515 }
13516 /*
13517 * Check constraints.
13518 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013519 xmlSchemaCheckSRCSimpleType(ctxt, item);
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000013520 xmlSchemaCheckDefaults(item, ctxt, item->name);
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013521 ctxt->ctxtType = ctxtType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013522 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013523 case XML_SCHEMA_TYPE_SEQUENCE:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013524 case XML_SCHEMA_TYPE_ALL:
13525 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013526 item->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013527 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013528 case XML_SCHEMA_TYPE_GROUP:
13529 /*
13530 * TODO: Handling was moved to xmlSchemaGroupDefFixup.
13531 */
13532 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013533 case XML_SCHEMA_TYPE_LIST:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013534 xmlSchemaParseListRefFixup(item, ctxt);
13535 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013536 break;
13537 case XML_SCHEMA_TYPE_UNION:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013538 xmlSchemaParseUnionRefCheck(item, ctxt);
13539 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013540 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013541 case XML_SCHEMA_TYPE_BASIC:
13542 case XML_SCHEMA_TYPE_ANY:
13543 case XML_SCHEMA_TYPE_FACET:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013544 case XML_SCHEMA_TYPE_UR:
13545 case XML_SCHEMA_TYPE_ELEMENT:
13546 case XML_SCHEMA_TYPE_ATTRIBUTE:
13547 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
William M. Brack29aa7722004-05-12 00:27:56 +000013548 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013549 case XML_SCHEMA_TYPE_NOTATION:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013550 case XML_SCHEMA_FACET_MININCLUSIVE:
13551 case XML_SCHEMA_FACET_MINEXCLUSIVE:
13552 case XML_SCHEMA_FACET_MAXINCLUSIVE:
13553 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
13554 case XML_SCHEMA_FACET_TOTALDIGITS:
13555 case XML_SCHEMA_FACET_FRACTIONDIGITS:
13556 case XML_SCHEMA_FACET_PATTERN:
13557 case XML_SCHEMA_FACET_ENUMERATION:
13558 case XML_SCHEMA_FACET_WHITESPACE:
13559 case XML_SCHEMA_FACET_LENGTH:
13560 case XML_SCHEMA_FACET_MAXLENGTH:
13561 case XML_SCHEMA_FACET_MINLENGTH:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013562 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
13563 if (item->subtypes != NULL)
13564 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013565 break;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000013566 case XML_SCHEMA_TYPE_IDC_UNIQUE:
13567 case XML_SCHEMA_TYPE_IDC_KEY:
13568 case XML_SCHEMA_TYPE_IDC_KEYREF:
13569 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013570 }
13571 }
Daniel Veillard8651f532002-04-17 09:06:27 +000013572#ifdef DEBUG_TYPE
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013573 if (item->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013574 xmlGenericError(xmlGenericErrorContext,
13575 "Type of %s : %s:%d :", name,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013576 item->node->doc->URL,
13577 xmlGetLineNo(item->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +000013578 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013579 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000013580 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013581 switch (item->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013582 case XML_SCHEMA_CONTENT_SIMPLE:
13583 xmlGenericError(xmlGenericErrorContext, "simple\n");
13584 break;
13585 case XML_SCHEMA_CONTENT_ELEMENTS:
13586 xmlGenericError(xmlGenericErrorContext, "elements\n");
13587 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000013588 case XML_SCHEMA_CONTENT_UNKNOWN:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013589 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
13590 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000013591 case XML_SCHEMA_CONTENT_EMPTY:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013592 xmlGenericError(xmlGenericErrorContext, "empty\n");
13593 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000013594 case XML_SCHEMA_CONTENT_MIXED:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013595 xmlGenericError(xmlGenericErrorContext, "mixed\n");
13596 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013597 /* Removed, since not used. */
13598 /*
Daniel Veillard8651f532002-04-17 09:06:27 +000013599 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013600 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
13601 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013602 */
Daniel Veillard8651f532002-04-17 09:06:27 +000013603 case XML_SCHEMA_CONTENT_BASIC:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013604 xmlGenericError(xmlGenericErrorContext, "basic\n");
13605 break;
13606 default:
13607 xmlGenericError(xmlGenericErrorContext,
13608 "not registered !!!\n");
13609 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000013610 }
13611#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000013612}
13613
13614/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000013615 * xmlSchemaCheckFacet:
13616 * @facet: the facet
13617 * @typeDecl: the schema type definition
13618 * @ctxt: the schema parser context or NULL
13619 * @name: name of the type
13620 *
13621 * Checks the default values types, especially for facets
13622 *
13623 * Returns 0 if okay or -1 in cae of error
13624 */
13625int
13626xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013627 xmlSchemaTypePtr typeDecl,
13628 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000013629{
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +000013630 xmlSchemaTypePtr nonNegativeIntegerType = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013631 int ret = 0, reuseValCtxt = 0;
13632
Daniel Veillardce682bc2004-11-05 17:22:25 +000013633 if ((facet == NULL) || (typeDecl == NULL))
13634 return(-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013635 /*
13636 * TODO: will the parser context be given if used from
13637 * the relaxNG module?
13638 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000013639
13640 if (nonNegativeIntegerType == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013641 nonNegativeIntegerType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000013642 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000013643 }
13644 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013645 case XML_SCHEMA_FACET_MININCLUSIVE:
13646 case XML_SCHEMA_FACET_MINEXCLUSIVE:
13647 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013648 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
13649 case XML_SCHEMA_FACET_ENUMERATION: {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013650 /*
13651 * Okay we need to validate the value
13652 * at that point.
13653 */
13654 xmlSchemaValidCtxtPtr vctxt;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013655 xmlSchemaTypePtr base;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013656
13657 /* 4.3.5.5 Constraints on enumeration Schema Components
13658 * Schema Component Constraint: enumeration valid restriction
13659 * It is an ·error· if any member of {value} is not in the
13660 * ·value space· of {base type definition}.
13661 *
13662 * minInclusive, maxInclusive, minExclusive, maxExclusive:
13663 * The value ·must· be in the
13664 * ·value space· of the ·base type·.
13665 */
13666 /*
13667 * This function is intended to deliver a compiled value
13668 * on the facet. In XML Schemas the type holding a facet,
13669 * cannot be a built-in type. Thus to ensure that other API
13670 * calls (relaxng) do work, if the given type is a built-in
13671 * type, we will assume that the given built-in type *is
13672 * already* the base type.
13673 */
13674 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
13675 base = typeDecl->baseType;
13676 if (base == NULL) {
13677 xmlSchemaPErr(ctxt, typeDecl->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013678 XML_SCHEMAP_INTERNAL,
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013679 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013680 "the type '%s' has no base type.\n",
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013681 typeDecl->name, NULL);
13682 return (-1);
13683 }
13684 } else
13685 base = typeDecl;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013686 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013687 * This avoids perseverative creation of the
13688 * validation context if a parser context is
13689 * used.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013690 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013691 if (ctxt != NULL) {
13692 reuseValCtxt = 1;
13693 if (ctxt->vctxt == NULL) {
13694 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
13695 return (-1);
13696 }
13697 vctxt = ctxt->vctxt;
13698 } else {
13699 vctxt = xmlSchemaNewValidCtxt(NULL);
13700 if (vctxt == NULL) {
13701 xmlSchemaPErr(ctxt, typeDecl->node,
13702 XML_SCHEMAP_INTERNAL,
13703 "Internal error: xmlSchemaCheckFacet, "
13704 "creating a new validation context.\n",
13705 NULL, NULL);
13706 return (-1);
13707 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013708 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013709
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013710 vctxt->node = facet->node;
13711 vctxt->cur = NULL;
13712 /*
13713 * NOTE: This call does not check the content nodes,
13714 * since they are not available:
13715 * facet->node is just the node holding the facet
13716 * definition, *not* the attribute holding the *value*
13717 * of the facet.
13718 */
13719 ret = xmlSchemaValidateSimpleTypeValue(vctxt, base,
13720 facet->value, 0, 1, 1, 0);
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013721 facet->val = vctxt->value;
13722 vctxt->value = NULL;
13723 if (ret > 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013724 /* error code */
13725 if (ctxt != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013726 xmlSchemaPErrExt(ctxt, facet->node,
13727 XML_SCHEMAP_INVALID_FACET,
13728 NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013729 "Type definition '%s': The value '%s' of the "
13730 "facet '%s' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013731 name, facet->value,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013732 BAD_CAST xmlSchemaFacetTypeToString(facet->type),
Daniel Veillard01fa6152004-06-29 17:04:39 +000013733 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013734 }
13735 ret = -1;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013736 } else if (ret < 0) {
13737 xmlSchemaPErrExt(ctxt, facet->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013738 XML_SCHEMAP_INTERNAL,
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013739 NULL, NULL, NULL,
13740 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013741 "failed to validate the value '%s' name of the "
13742 "facet '%s' against the base type '%s'.\n",
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013743 facet->value,
13744 BAD_CAST xmlSchemaFacetTypeToString(facet->type),
13745 base->name, NULL, NULL);
13746 ret = -1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013747 }
13748 if (reuseValCtxt == 0)
13749 xmlSchemaFreeValidCtxt(vctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013750 break;
13751 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013752 case XML_SCHEMA_FACET_PATTERN:
13753 facet->regexp = xmlRegexpCompile(facet->value);
13754 if (facet->regexp == NULL) {
13755 xmlSchemaPErr(ctxt, typeDecl->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013756 XML_SCHEMAP_REGEXP_INVALID,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013757 "Type definition '%s': The value '%s' of the "
13758 "facet 'pattern' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013759 name, facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013760 ret = -1;
13761 }
13762 break;
13763 case XML_SCHEMA_FACET_TOTALDIGITS:
13764 case XML_SCHEMA_FACET_FRACTIONDIGITS:
13765 case XML_SCHEMA_FACET_LENGTH:
13766 case XML_SCHEMA_FACET_MAXLENGTH:
13767 case XML_SCHEMA_FACET_MINLENGTH:{
13768 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000013769
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013770 tmp =
13771 xmlSchemaValidatePredefinedType(nonNegativeIntegerType,
13772 facet->value,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +000013773 &(facet->val));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013774 if (tmp != 0) {
13775 /* error code */
13776 if (ctxt != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013777 xmlSchemaPErrExt(ctxt, facet->node,
13778 XML_SCHEMAP_INVALID_FACET_VALUE,
13779 NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013780 "Type definition '%s': The value '%s' of the "
13781 "facet '%s' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013782 name, facet->value,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013783 BAD_CAST xmlSchemaFacetTypeToString(facet->type),
Daniel Veillard01fa6152004-06-29 17:04:39 +000013784 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013785 }
13786 ret = -1;
13787 }
13788 break;
13789 }
13790 case XML_SCHEMA_FACET_WHITESPACE:{
13791 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
13792 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
13793 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
13794 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
13795 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
13796 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
13797 } else {
13798 if (ctxt != NULL) {
13799 xmlSchemaPErr(ctxt, facet->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013800 XML_SCHEMAP_INVALID_WHITE_SPACE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013801 "Type definition '%s': The value '%s' of the "
13802 "facet 'whiteSpace' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013803 name, facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013804 }
13805 ret = -1;
13806 }
13807 }
13808 default:
13809 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000013810 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013811 return (ret);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000013812}
13813
13814/**
Daniel Veillard4255d502002-04-16 15:50:10 +000013815 * xmlSchemaCheckDefaults:
13816 * @typeDecl: the schema type definition
13817 * @ctxt: the schema parser context
13818 *
13819 * Checks the default values types, especially for facets
13820 */
13821static void
13822xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013823 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000013824{
Daniel Veillard4255d502002-04-16 15:50:10 +000013825 if (name == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013826 name = typeDecl->name;
13827 /*
13828 * NOTE: It is intended to use the facets list, instead
13829 * of facetSet.
13830 */
13831 if (typeDecl->facets != NULL) {
13832 xmlSchemaFacetPtr facet = typeDecl->facets;
13833
13834 while (facet != NULL) {
13835 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
13836 facet = facet->next;
13837 }
13838 }
Daniel Veillard4255d502002-04-16 15:50:10 +000013839}
13840
13841/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013842 * xmlSchemaGetCircModelGrDefRef:
13843 * @ctxtGr: the searched model group
13844 * @list: the list of model groups to be processed
13845 *
13846 * This one is intended to be used by
13847 * xmlSchemaCheckGroupDefCircular only.
13848 *
13849 * Returns the circular model group definition reference, otherwise NULL.
13850 */
13851static xmlSchemaTypePtr
13852xmlSchemaGetCircModelGrDefRef(xmlSchemaTypePtr ctxtGrDef,
13853 xmlSchemaTypePtr gr)
13854{
13855 xmlSchemaTypePtr circ = NULL;
13856 int marked;
13857 /*
13858 * We will search for an model group reference which
13859 * references the context model group definition.
13860 */
13861 while (gr != NULL) {
13862 if (((gr->type == XML_SCHEMA_TYPE_GROUP) ||
13863 (gr->type == XML_SCHEMA_TYPE_ALL) ||
13864 (gr->type == XML_SCHEMA_TYPE_SEQUENCE) ||
13865 (gr->type == XML_SCHEMA_TYPE_CHOICE)) &&
13866 (gr->subtypes != NULL)) {
13867 marked = 0;
13868 if ((gr->type == XML_SCHEMA_TYPE_GROUP) &&
13869 (gr->ref != NULL)) {
13870 if (gr->subtypes == ctxtGrDef)
13871 return (gr);
13872 else if (gr->subtypes->flags &
13873 XML_SCHEMAS_TYPE_MARKED) {
13874 gr = gr->next;
13875 continue;
13876 } else {
13877 /*
13878 * Mark to avoid infinite recursion on
13879 * circular references not yet examined.
13880 */
13881 gr->subtypes->flags |= XML_SCHEMAS_TYPE_MARKED;
13882 marked = 1;
13883 }
13884 if (gr->subtypes->subtypes != NULL)
13885 circ = xmlSchemaGetCircModelGrDefRef(ctxtGrDef,
13886 gr->subtypes->subtypes);
13887 /*
13888 * Unmark the visited model group definition.
13889 */
13890 if (marked)
13891 gr->subtypes->flags ^= XML_SCHEMAS_TYPE_MARKED;
13892 if (circ != NULL)
13893 return (circ);
13894 } else {
13895 circ = xmlSchemaGetCircModelGrDefRef(ctxtGrDef,
13896 (xmlSchemaTypePtr) gr->subtypes);
13897 if (circ != NULL)
13898 return (circ);
13899 }
13900
13901 }
13902 gr = gr->next;
13903 }
13904 return (NULL);
13905}
13906
13907/**
13908 * xmlSchemaCheckGroupDefCircular:
13909 * attrGr: the model group definition
13910 * @ctxt: the parser context
13911 * @name: the name
13912 *
13913 * Checks for circular references to model group definitions.
13914 */
13915static void
13916xmlSchemaCheckGroupDefCircular(xmlSchemaTypePtr modelGrDef,
13917 xmlSchemaParserCtxtPtr ctxt,
13918 const xmlChar * name ATTRIBUTE_UNUSED)
13919{
13920 /*
13921 * Schema Component Constraint: Model Group Correct
13922 * 2 Circular groups are disallowed. That is, within the {particles}
13923 * of a group there must not be at any depth a particle whose {term}
13924 * is the group itself.
13925 */
13926 /*
13927 * NOTE: "gr->subtypes" holds the referenced group.
13928 */
13929 if ((modelGrDef->type != XML_SCHEMA_TYPE_GROUP) ||
13930 ((modelGrDef->flags & XML_SCHEMAS_TYPE_GLOBAL) == 0) ||
13931 (modelGrDef->subtypes == NULL))
13932 return;
13933 else {
13934 xmlSchemaTypePtr circ;
13935
13936 circ = xmlSchemaGetCircModelGrDefRef(modelGrDef, modelGrDef->subtypes);
13937 if (circ != NULL) {
13938 /*
13939 * TODO: Report the referenced attr group as QName.
13940 */
13941 xmlSchemaPCustomErr(ctxt,
13942 XML_SCHEMAP_MG_PROPS_CORRECT_2,
13943 NULL, NULL, circ->node,
13944 "Circular reference to the model group definition '%s' "
13945 "defined", modelGrDef->name);
13946 /*
13947 * NOTE: We will cut the reference to avoid further
13948 * confusion of the processor.
13949 * TODO: SPEC: Does the spec define how to process here?
13950 */
13951 circ->subtypes = NULL;
13952 }
13953 }
13954}
13955
13956
13957/**
13958 * xmlSchemaGetCircAttrGrRef:
13959 * @ctxtGr: the searched attribute group
13960 * @attr: the current attribute list to be processed
13961 *
13962 * This one is intended to be used by
13963 * xmlSchemaCheckSRCAttributeGroupCircular only.
13964 *
13965 * Returns the circular attribute grou reference, otherwise NULL.
13966 */
13967static xmlSchemaAttributeGroupPtr
13968xmlSchemaGetCircAttrGrRef(xmlSchemaAttributeGroupPtr ctxtGr,
13969 xmlSchemaAttributePtr attr)
13970{
13971 xmlSchemaAttributeGroupPtr circ = NULL, gr;
13972 int marked;
13973 /*
13974 * We will search for an attribute group reference which
13975 * references the context attribute group.
13976 */
13977 while (attr != NULL) {
13978 marked = 0;
13979 if (attr->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
13980 gr = (xmlSchemaAttributeGroupPtr) attr;
13981 if (gr->refItem != NULL) {
13982 if (gr->refItem == ctxtGr)
13983 return (gr);
13984 else if (gr->refItem->flags &
13985 XML_SCHEMAS_ATTRGROUP_MARKED) {
13986 attr = attr->next;
13987 continue;
13988 } else {
13989 /*
13990 * Mark as visited to avoid infinite recursion on
13991 * circular references not yet examined.
13992 */
13993 gr->refItem->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
13994 marked = 1;
13995 }
13996 }
13997 if (gr->attributes != NULL)
13998 circ = xmlSchemaGetCircAttrGrRef(ctxtGr, gr->attributes);
13999 /*
14000 * Unmark the visited group's attributes.
14001 */
14002 if (marked)
14003 gr->refItem->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
14004 if (circ != NULL)
14005 return (circ);
14006 }
14007 attr = attr->next;
14008 }
14009 return (NULL);
14010}
14011
14012/**
14013 * xmlSchemaCheckSRCAttributeGroupCircular:
14014 * attrGr: the attribute group definition
14015 * @ctxt: the parser context
14016 * @name: the name
14017 *
14018 * Checks for circular references of attribute groups.
14019 */
14020static void
14021xmlSchemaCheckAttributeGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
14022 xmlSchemaParserCtxtPtr ctxt,
14023 const xmlChar * name ATTRIBUTE_UNUSED)
14024{
14025 /*
14026 * Schema Representation Constraint:
14027 * Attribute Group Definition Representation OK
14028 * 3 Circular group reference is disallowed outside <redefine>.
14029 * That is, unless this element information item's parent is
14030 * <redefine>, then among the [children], if any, there must
14031 * not be an <attributeGroup> with ref [attribute] which resolves
14032 * to the component corresponding to this <attributeGroup>. Indirect
14033 * circularity is also ruled out. That is, when QName resolution
14034 * (Schema Document) (§3.15.3) is applied to a ·QName· arising from
14035 * any <attributeGroup>s with a ref [attribute] among the [children],
14036 * it must not be the case that a ·QName· is encountered at any depth
14037 * which resolves to the component corresponding to this <attributeGroup>.
14038 */
14039 /*
14040 * Only global components can be referenced.
14041 */
14042 if (((attrGr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) == 0) ||
14043 (attrGr->attributes == NULL))
14044 return;
14045 else {
14046 xmlSchemaAttributeGroupPtr circ;
14047
14048 circ = xmlSchemaGetCircAttrGrRef(attrGr, attrGr->attributes);
14049 if (circ != NULL) {
14050 /*
14051 * TODO: Report the referenced attr group as QName.
14052 */
14053 xmlSchemaPCustomErr(ctxt,
14054 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
14055 NULL, NULL, circ->node,
14056 "Circular reference to the attribute group '%s' "
14057 "defined", attrGr->name);
14058 /*
14059 * NOTE: We will cut the reference to avoid further
14060 * confusion of the processor.
14061 * BADSPEC: The spec should define how to process in this case.
14062 */
14063 circ->attributes = NULL;
14064 circ->refItem = NULL;
14065 }
14066 }
14067}
14068
14069/**
Daniel Veillard13e04c62002-04-23 17:51:29 +000014070 * xmlSchemaAttrGrpFixup:
14071 * @attrgrpDecl: the schema attribute definition
14072 * @ctxt: the schema parser context
14073 * @name: the attribute name
14074 *
14075 * Fixes finish doing the computations on the attributes definitions
14076 */
14077static void
Daniel Veillard3646d642004-06-02 19:19:14 +000014078xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014079 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +000014080{
14081 if (name == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000014082 name = attrgrp->name;
14083 if (attrgrp->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014084 return;
Daniel Veillard3646d642004-06-02 19:19:14 +000014085 if (attrgrp->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014086 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +000014087
Daniel Veillardc0826a72004-08-10 14:17:33 +000014088 ref = xmlSchemaGetAttributeGroup(ctxt->schema, attrgrp->ref,
14089 attrgrp->refNs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014090 if (ref == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014091 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014092 XML_SCHEMAP_SRC_RESOLVE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014093 NULL, (xmlSchemaTypePtr) attrgrp, attrgrp->node,
14094 "ref", attrgrp->ref, attrgrp->refNs,
14095 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014096 return;
14097 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014098 attrgrp->refItem = ref;
14099 /*
14100 * Check for self reference!
14101 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014102 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000014103 attrgrp->attributes = ref->attributes;
14104 attrgrp->attributeWildcard = ref->attributeWildcard;
14105 }
Daniel Veillard13e04c62002-04-23 17:51:29 +000014106}
14107
14108/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014109 * xmlSchemaAttrCheckValConstr:
14110 * @item: an schema attribute declaration/use
14111 * @ctxt: a schema parser context
14112 * @name: the name of the attribute
14113 *
14114 * Validates the value constraints of an attribute declaration/use.
Daniel Veillard4255d502002-04-16 15:50:10 +000014115 *
14116 * Fixes finish doing the computations on the attributes definitions
14117 */
14118static void
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014119xmlSchemaCheckAttrValConstr(xmlSchemaAttributePtr item,
14120 xmlSchemaParserCtxtPtr ctxt,
14121 const xmlChar * name ATTRIBUTE_UNUSED)
14122{
14123
14124 /*
14125 * a-props-correct
14126 * Schema Component Constraint: Attribute Declaration Properties Correct
14127 *
14128 * 2 if there is a {value constraint}, the canonical lexical
14129 * representation of its value must be ·valid· with respect
14130 * to the {type definition} as defined in String Valid (§3.14.4).
14131 */
14132
14133 if (item->defValue != NULL) {
14134 int ret;
14135 xmlNodePtr node;
14136 xmlSchemaTypePtr type;
14137
14138 if (item->subtypes == NULL) {
14139 xmlSchemaPErr(ctxt, item->node,
14140 XML_SCHEMAP_INTERNAL,
14141 "Internal error: xmlSchemaCheckAttrValConstr, "
14142 "type is missing... skipping validation of "
14143 "value constraint", NULL, NULL);
14144 return;
14145 }
14146
14147 /*
14148 * TODO: Try to avoid creating a new context.
14149 * TODO: This all is not very performant.
14150 */
14151 type = item->subtypes;
14152 /*
14153 * Ensure there's validation context.
14154 */
14155 if (ctxt->vctxt == NULL) {
14156 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1) {
14157 xmlSchemaPErr(ctxt, item->node,
14158 XML_SCHEMAP_INTERNAL,
14159 "Internal error: xmlSchemaCheckAttrValConstr, "
14160 "creating a new validation context.\n",
14161 NULL, NULL);
14162 return;
14163 }
14164 }
14165
14166 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
14167 node = (xmlNodePtr) xmlHasProp(item->node, BAD_CAST "fixed");
14168 else
14169 node = (xmlNodePtr) xmlHasProp(item->node, BAD_CAST "default");
14170 ctxt->vctxt->node = node;
14171 ctxt->vctxt->cur = NULL;
14172 /*
14173 * NOTE: This call does not check the content nodes,
14174 * since they are not available:
14175 * facet->node is just the node holding the facet
14176 * definition, *not* the attribute holding the *value*
14177 * of the facet.
14178 */
14179 ret = xmlSchemaValidateSimpleTypeValue(ctxt->vctxt, type,
14180 item->defValue, 0, 1, 1, 0);
14181 if (ret == 0) {
14182 /*
14183 * Store the computed value.
14184 */
14185 item->defVal = ctxt->vctxt->value;
14186 ctxt->vctxt->value = NULL;
14187 } else if (ret > 0) {
14188 if (ctxt != NULL) {
14189 xmlSchemaPSimpleTypeErr(ctxt,
14190 XML_SCHEMAP_A_PROPS_CORRECT_2,
14191 NULL, NULL, node,
14192 type, NULL, item->defValue,
14193 NULL, NULL, NULL);
14194 }
14195 } else if (ret < 0) {
14196 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
14197 NULL, NULL, node,
14198 "Internal error: xmlSchemaAttrCheckValConstr, "
14199 "failed to validate the value constraint of the "
14200 "attribute decl/use against the type '%s'",
14201 type->name);
14202 }
14203 }
14204}
14205
14206#if 0 /* Not used yet. */
14207static int
14208xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
14209 xmlSchemaElementPtr edecl)
14210{
14211 /*
14212 * TODO: 1 The values of the properties of an element declaration must be as
14213 * described in the property tableau in The Element Declaration Schema
14214 * Component (§3.3.1), modulo the impact of Missing Sub-components (§5.3).
14215 */
14216 /*
14217 * 2 If there is a {value constraint}, the canonical lexical
14218 * representation of its value must be ·valid· with respect to the {type
14219 * definition} as defined in Element Default Valid (Immediate) (§3.3.6).
14220 *
14221 * NOTE: This is done in xmlSchemaCheckElemValConstr.
14222 */
14223 /*
14224 * 3 If there is a non-·absent· {substitution group affiliation},
14225 * then {scope} must be global.
14226 *
14227 * NOTE: This is done in xmlSchemaParseElement.
14228 * TODO: Move it to this layer here.
14229 */
14230 /*
14231 * TODO: 4 If there is a {substitution group affiliation}, the {type definition}
14232 * of the element declaration must be validly derived from the {type
14233 * definition} of the {substitution group affiliation}, given the value
14234 * of the {substitution group exclusions} of the {substitution group
14235 * affiliation}, as defined in Type Derivation OK (Complex) (§3.4.6)
14236 * (if the {type definition} is complex) or as defined in
14237 * Type Derivation OK (Simple) (§3.14.6) (if the {type definition} is
14238 * simple).
14239 */
14240 /*
14241 * TODO: 5 If the {type definition} or {type definition}'s {content type}
14242 * is or is derived from ID then there must not be a {value constraint}.
14243 * Note: The use of ID as a type definition for elements goes beyond
14244 * XML 1.0, and should be avoided if backwards compatibility is desired
14245 */
14246 /*
14247 * TODO: 6 Circular substitution groups are disallowed. That is, it must not
14248 * be possible to return to an element declaration by repeatedly following
14249 * the {substitution group affiliation} property.
14250 */
14251}
14252#endif
14253
14254/**
14255 * xmlSchemaCheckElemValConstr:
14256 * @item: an schema element declaration/particle
14257 * @ctxt: a schema parser context
14258 * @name: the name of the attribute
14259 *
14260 * Validates the value constraints of an element declaration.
14261 *
14262 * Fixes finish doing the computations on the element declarations.
14263 */
14264static void
14265xmlSchemaCheckElemValConstr(xmlSchemaElementPtr decl,
14266 xmlSchemaParserCtxtPtr ctxt,
14267 const xmlChar * name ATTRIBUTE_UNUSED)
14268{
14269 if (decl->value != NULL) {
14270 int ret;
14271 xmlNodePtr node = NULL;
14272 xmlSchemaTypePtr type;
14273
14274 /*
14275 * 2 If there is a {value constraint}, the canonical lexical
14276 * representation of its value must be ·valid· with respect to the {type
14277 * definition} as defined in Element Default Valid (Immediate) (§3.3.6).
14278 */
14279 if (decl->subtypes == NULL) {
14280 xmlSchemaPErr(ctxt, decl->node,
14281 XML_SCHEMAP_INTERNAL,
14282 "Internal error: xmlSchemaCheckElemValConstr, "
14283 "type is missing... skipping validation of "
14284 "the value constraint", NULL, NULL);
14285 return;
14286 }
14287 /*
14288 * Ensure there's a validation context.
14289 */
14290 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
14291 return;
14292
14293 type = decl->subtypes;
14294
14295 if (decl->node != NULL) {
14296 if (decl->flags & XML_SCHEMAS_ELEM_FIXED)
14297 node = (xmlNodePtr) xmlHasProp(decl->node, BAD_CAST "fixed");
14298 else
14299 node = (xmlNodePtr) xmlHasProp(decl->node, BAD_CAST "default");
14300 }
14301 ctxt->vctxt->node = node;
14302 ctxt->vctxt->cur = NULL;
14303 ret = xmlSchemaCheckCOSValidDefault(ctxt, ctxt->vctxt, type, decl->value,
14304 node);
14305 if (ret == 0) {
14306 /*
14307 * Consume the computed value.
14308 */
14309 decl->defVal = ctxt->vctxt->value;
14310 ctxt->vctxt->value = NULL;
14311 } else if (ret < 0) {
14312 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
14313 NULL, NULL, node,
14314 "Internal error: xmlSchemaElemCheckValConstr, "
14315 "failed to validate the value constraint of the "
14316 "element declaration '%s'",
14317 decl->name);
14318 }
14319 }
14320}
14321
14322/**
14323 * xmlSchemaAttrFixup:
14324 * @item: an schema attribute declaration/use.
14325 * @ctxt: a schema parser context
14326 * @name: the name of the attribute
14327 *
14328 * Fixes finish doing the computations on attribute declarations/uses.
14329 */
14330static void
14331xmlSchemaAttrFixup(xmlSchemaAttributePtr item,
14332 xmlSchemaParserCtxtPtr ctxt,
14333 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000014334{
Daniel Veillardc0826a72004-08-10 14:17:33 +000014335 /*
14336 * TODO: If including this is done twice (!) for every attribute.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014337 * -> Hmm, check if this is still done.
Daniel Veillardc0826a72004-08-10 14:17:33 +000014338 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014339 /*
14340 * The simple type definition corresponding to the <simpleType> element
14341 * information item in the [children], if present, otherwise the simple
14342 * type definition ·resolved· to by the ·actual value· of the type
14343 * [attribute], if present, otherwise the ·simple ur-type definition·.
14344 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014345 if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
Daniel Veillardc0826a72004-08-10 14:17:33 +000014346 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014347 item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
14348 if (item->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014349 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014350 if (item->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014351 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000014352
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014353 type = xmlSchemaGetType(ctxt->schema, item->typeName,
14354 item->typeNs);
14355 if ((type == NULL) || (! IS_SIMPLE_TYPE(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014356 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014357 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014358 NULL, (xmlSchemaTypePtr) item, item->node,
14359 "type", item->typeName, item->typeNs,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014360 XML_SCHEMA_TYPE_SIMPLE, NULL);
14361 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014362 item->subtypes = type;
14363
14364 } else if (item->ref != NULL) {
14365 xmlSchemaAttributePtr decl;
Daniel Veillard4255d502002-04-16 15:50:10 +000014366
Daniel Veillardc0826a72004-08-10 14:17:33 +000014367 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014368 * We have an attribute use here; assign the referenced
14369 * attribute declaration.
14370 */
14371 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000014372 * TODO: Evaluate, what errors could occur if the declaration is not
14373 * found. It might be possible that the "typefixup" might crash if
14374 * no ref declaration was found.
14375 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014376 decl = xmlSchemaGetAttribute(ctxt->schema, item->ref, item->refNs);
14377 if (decl == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014378 xmlSchemaPResCompAttrErr(ctxt,
14379 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014380 NULL, (xmlSchemaTypePtr) item, item->node,
14381 "ref", item->ref, item->refNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014382 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014383 return;
14384 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014385 item->refDecl = decl;
14386 xmlSchemaAttrFixup(decl, ctxt, NULL);
14387
14388 item->subtypes = decl->subtypes;
14389 /*
14390 * Attribute Use Correct
14391 * au-props-correct.2: If the {attribute declaration} has a fixed
14392 * {value constraint}, then if the attribute use itself has a
14393 * {value constraint}, it must also be fixed and its value must match
14394 * that of the {attribute declaration}'s {value constraint}.
14395 */
14396 if ((decl->flags & XML_SCHEMAS_ATTR_FIXED) &&
14397 (item->defValue != NULL)) {
14398 if (((item->flags & XML_SCHEMAS_ATTR_FIXED) == 0) ||
14399 (!xmlStrEqual(item->defValue, decl->defValue))) {
14400 xmlSchemaPCustomErr(ctxt,
14401 XML_SCHEMAP_AU_PROPS_CORRECT_2,
14402 NULL, NULL, item->node,
14403 "The value constraint must be fixed "
14404 "and match the referenced attribute "
14405 "declarations's value constraint '%s'",
14406 decl->defValue);
14407 }
14408 /*
14409 * FUTURE: One should change the values of the attr. use
14410 * if ever validation should be attempted even if the
14411 * schema itself was not fully valid.
14412 */
14413 }
Daniel Veillard3646d642004-06-02 19:19:14 +000014414 } else {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014415 item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
14416 }
Daniel Veillard4255d502002-04-16 15:50:10 +000014417}
14418
14419/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000014420 * xmlSchemaResolveIDCKeyRef:
14421 * @idc: the identity-constraint definition
14422 * @ctxt: the schema parser context
14423 * @name: the attribute name
14424 *
14425 * Resolve keyRef references to key/unique IDCs.
14426 */
14427static void
14428xmlSchemaResolveIDCKeyRef(xmlSchemaIDCPtr idc,
14429 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000014430 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000014431{
14432 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
14433 return;
14434 if (idc->ref->name != NULL) {
14435 idc->ref->item = (xmlSchemaBasicItemPtr) xmlHashLookup2(
14436 ctxt->schema->idcDef,
14437 idc->ref->name,
14438 idc->ref->targetNamespace);
14439 if (idc->ref->item == NULL) {
14440 /*
14441 * TODO: It is actually not an error to fail to resolve.
14442 */
14443 xmlSchemaPResCompAttrErr(ctxt,
14444 XML_SCHEMAP_SRC_RESOLVE,
14445 NULL, (xmlSchemaTypePtr) idc, idc->node,
14446 "refer", idc->ref->name,
14447 idc->ref->targetNamespace,
14448 XML_SCHEMA_TYPE_IDC_KEYREF, NULL);
14449 return;
14450 }
14451 }
14452}
14453
14454/**
Daniel Veillard4255d502002-04-16 15:50:10 +000014455 * xmlSchemaParse:
14456 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000014457 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000014458 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +000014459 * XML Shema struture which can be used to validate instances.
14460 * *WARNING* this interface is highly subject to change
14461 *
14462 * Returns the internal XML Schema structure built from the resource or
14463 * NULL in case of error
14464 */
14465xmlSchemaPtr
14466xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
14467{
14468 xmlSchemaPtr ret = NULL;
14469 xmlDocPtr doc;
Daniel Veillardbd2904b2003-11-25 15:38:59 +000014470 xmlNodePtr root;
Daniel Veillarddda22c12004-01-24 08:31:30 +000014471 int preserve = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000014472
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014473 /*
14474 * This one is used if the schema to be parsed was specified via
14475 * the API; i.e. not automatically by the validated instance document.
14476 */
14477
Daniel Veillard4255d502002-04-16 15:50:10 +000014478 xmlSchemaInitTypes();
14479
Daniel Veillard6045c902002-10-09 21:13:59 +000014480 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +000014481 return (NULL);
14482
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000014483 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000014484 ctxt->counter = 0;
14485 ctxt->container = NULL;
14486
14487 /*
14488 * First step is to parse the input document into an DOM/Infoset
14489 */
Daniel Veillard6045c902002-10-09 21:13:59 +000014490 if (ctxt->URL != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000014491 doc = xmlReadFile((const char *) ctxt->URL, NULL,
14492 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014493 if (doc == NULL) {
14494 xmlSchemaPErr(ctxt, NULL,
14495 XML_SCHEMAP_FAILED_LOAD,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014496 "xmlSchemaParse: could not load '%s'.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014497 ctxt->URL, NULL);
14498 return (NULL);
14499 }
Daniel Veillard6045c902002-10-09 21:13:59 +000014500 } else if (ctxt->buffer != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000014501 doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
14502 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014503 if (doc == NULL) {
14504 xmlSchemaPErr(ctxt, NULL,
14505 XML_SCHEMAP_FAILED_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014506 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014507 NULL, NULL);
14508 return (NULL);
14509 }
14510 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard65765282004-01-08 16:59:30 +000014511 ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
Daniel Veillard9d751502003-10-29 13:21:47 +000014512 } else if (ctxt->doc != NULL) {
14513 doc = ctxt->doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000014514 preserve = 1;
Daniel Veillard6045c902002-10-09 21:13:59 +000014515 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014516 xmlSchemaPErr(ctxt, NULL,
14517 XML_SCHEMAP_NOTHING_TO_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014518 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014519 NULL, NULL);
14520 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000014521 }
14522
14523 /*
14524 * Then extract the root and Schema parse it
14525 */
14526 root = xmlDocGetRootElement(doc);
14527 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014528 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
14529 XML_SCHEMAP_NOROOT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014530 "The schema has no document element.\n", NULL, NULL);
Daniel Veillarddda22c12004-01-24 08:31:30 +000014531 if (!preserve) {
14532 xmlFreeDoc(doc);
14533 }
Daniel Veillard4255d502002-04-16 15:50:10 +000014534 return (NULL);
14535 }
14536
14537 /*
14538 * Remove all the blank text nodes
14539 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +000014540 xmlSchemaCleanupDoc(ctxt, root);
Daniel Veillard4255d502002-04-16 15:50:10 +000014541
14542 /*
14543 * Then do the parsing for good
14544 */
14545 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillard1d913862003-11-21 00:28:39 +000014546 if (ret == NULL) {
Daniel Veillarddda22c12004-01-24 08:31:30 +000014547 if (!preserve) {
14548 xmlFreeDoc(doc);
14549 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014550 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +000014551 }
Daniel Veillard4255d502002-04-16 15:50:10 +000014552 ret->doc = doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000014553 ret->preserve = preserve;
Daniel Veillard4255d502002-04-16 15:50:10 +000014554 ctxt->schema = ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014555 ctxt->ctxtType = NULL;
14556 ctxt->parentItem = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000014557 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +000014558 * Then fixup all attributes declarations
14559 */
14560 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
14561
14562 /*
14563 * Then fixup all attributes group declarations
14564 */
14565 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
14566 ctxt);
14567
14568 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000014569 * Resolve identity-constraint keyRefs.
14570 */
14571 xmlHashScan(ret->idcDef, (xmlHashScanner) xmlSchemaResolveIDCKeyRef, ctxt);
14572
14573 /*
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014574 * Check attribute groups for circular references.
14575 */
14576 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner)
14577 xmlSchemaCheckAttributeGroupCircular, ctxt);
14578
14579 /*
14580 * Then fixup all model group definitions.
14581 */
14582 xmlHashScan(ret->groupDecl, (xmlHashScanner) xmlSchemaGroupDefFixup, ctxt);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014583
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014584 /*
Daniel Veillard4255d502002-04-16 15:50:10 +000014585 * Then fixup all types properties
Daniel Veillardc0826a72004-08-10 14:17:33 +000014586 */
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014587 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014588
14589 /*
14590 * Then fix references of element declaration; apply constraints.
14591 */
14592 xmlHashScanFull(ret->elemDecl,
14593 (xmlHashScannerFull) xmlSchemaRefFixupCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000014594
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014595 /*
14596 * Check model groups defnitions for circular references.
14597 */
14598 xmlHashScan(ret->groupDecl, (xmlHashScanner)
14599 xmlSchemaCheckGroupDefCircular, ctxt);
14600
Daniel Veillard4255d502002-04-16 15:50:10 +000014601 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014602 * Then build the content model for all complex types
Daniel Veillard4255d502002-04-16 15:50:10 +000014603 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014604 xmlHashScan(ret->typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014605 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000014606
14607 /*
14608 * Then check the defaults part of the type like facets values
14609 */
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000014610 /* OLD: xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaCheckDefaults, ctxt); */
Daniel Veillard4255d502002-04-16 15:50:10 +000014611
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014612 /*
14613 * Validate the value constraint of attribute declarations/uses.
14614 */
14615 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaCheckAttrValConstr, ctxt);
14616
14617 /*
14618 * Validate the value constraint of element declarations.
14619 */
14620 xmlHashScan(ret->elemDecl, (xmlHashScanner) xmlSchemaCheckElemValConstr, ctxt);
14621
Daniel Veillardc0826a72004-08-10 14:17:33 +000014622
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000014623 if (ctxt->nberrors != 0) {
14624 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014625 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000014626 }
Daniel Veillard4255d502002-04-16 15:50:10 +000014627 return (ret);
14628}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014629
Daniel Veillard4255d502002-04-16 15:50:10 +000014630/**
Daniel Veillard01c13b52002-12-10 15:19:08 +000014631 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +000014632 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +000014633 * @err: the error callback
14634 * @warn: the warning callback
14635 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +000014636 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000014637 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000014638 */
14639void
14640xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014641 xmlSchemaValidityErrorFunc err,
14642 xmlSchemaValidityWarningFunc warn, void *ctx)
14643{
Daniel Veillard4255d502002-04-16 15:50:10 +000014644 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014645 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000014646 ctxt->error = err;
14647 ctxt->warning = warn;
14648 ctxt->userData = ctx;
14649}
14650
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014651/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000014652 * xmlSchemaGetParserErrors:
14653 * @ctxt: a XMl-Schema parser context
14654 * @err: the error callback result
14655 * @warn: the warning callback result
14656 * @ctx: contextual data for the callbacks result
14657 *
14658 * Get the callback information used to handle errors for a parser context
14659 *
14660 * Returns -1 in case of failure, 0 otherwise
14661 */
14662int
14663xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
14664 xmlSchemaValidityErrorFunc * err,
14665 xmlSchemaValidityWarningFunc * warn, void **ctx)
14666{
14667 if (ctxt == NULL)
14668 return(-1);
14669 if (err != NULL)
14670 *err = ctxt->error;
14671 if (warn != NULL)
14672 *warn = ctxt->warning;
14673 if (ctx != NULL)
14674 *ctx = ctxt->userData;
14675 return(0);
14676}
14677
14678/**
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014679 * xmlSchemaFacetTypeToString:
14680 * @type: the facet type
14681 *
14682 * Convert the xmlSchemaTypeType to a char string.
14683 *
14684 * Returns the char string representation of the facet type if the
14685 * type is a facet and an "Internal Error" string otherwise.
14686 */
14687static const char *
14688xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
14689{
14690 switch (type) {
14691 case XML_SCHEMA_FACET_PATTERN:
14692 return ("pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014693 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014694 return ("maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014695 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014696 return ("maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014697 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014698 return ("minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014699 case XML_SCHEMA_FACET_MININCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014700 return ("minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014701 case XML_SCHEMA_FACET_WHITESPACE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014702 return ("whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014703 case XML_SCHEMA_FACET_ENUMERATION:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014704 return ("enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014705 case XML_SCHEMA_FACET_LENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014706 return ("length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014707 case XML_SCHEMA_FACET_MAXLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014708 return ("maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014709 case XML_SCHEMA_FACET_MINLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014710 return ("minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014711 case XML_SCHEMA_FACET_TOTALDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014712 return ("totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014713 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014714 return ("fractionDigits");
14715 default:
14716 break;
14717 }
14718 return ("Internal Error");
14719}
14720
Daniel Veillardc0826a72004-08-10 14:17:33 +000014721
Daniel Veillardc0826a72004-08-10 14:17:33 +000014722
14723static int
14724xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
14725{
14726 xmlSchemaTypePtr anc;
14727
14728 /*
14729 * The normalization type can be changed only for types which are derived
14730 * from xsd:string.
14731 */
14732 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000014733 if (type->builtInType == XML_SCHEMAS_STRING)
Daniel Veillardc0826a72004-08-10 14:17:33 +000014734 return(XML_SCHEMAS_VAL_WTSP_PRESERVE);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000014735 else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
14736 return(XML_SCHEMAS_VAL_WTSP_REPLACE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014737 else {
14738 /*
14739 * For all ·atomic· datatypes other than string (and types ·derived·
14740 * by ·restriction· from it) the value of whiteSpace is fixed to
14741 * collapse
14742 */
14743 return(XML_SCHEMAS_VAL_WTSP_COLLAPSE);
14744 }
14745 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
14746 /*
14747 * For list types the facet "whiteSpace" is fixed to "collapse".
14748 */
14749 return (XML_SCHEMAS_VAL_WTSP_COLLAPSE);
14750 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
14751 return (-1);
14752 } else if (type->facetSet != NULL) {
14753 xmlSchemaTypePtr anyST;
14754 xmlSchemaFacetLinkPtr lin;
14755
14756 /*
14757 * Atomic types.
14758 */
14759 anyST = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
14760 anc = type->baseType;
14761 do {
14762 /*
14763 * For all ·atomic· datatypes other than string (and types ·derived·
14764 * by ·restriction· from it) the value of whiteSpace is fixed to
14765 * collapse
14766 */
14767 if ((anc->type == XML_SCHEMA_TYPE_BASIC) &&
14768 (anc->builtInType == XML_SCHEMAS_STRING)) {
14769
14770 lin = type->facetSet;
14771 do {
14772 if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
14773 if (lin->facet->whitespace ==
14774 XML_SCHEMAS_FACET_COLLAPSE) {
14775 return(XML_SCHEMAS_VAL_WTSP_COLLAPSE);
14776 } else if (lin->facet->whitespace ==
14777 XML_SCHEMAS_FACET_REPLACE) {
14778 return(XML_SCHEMAS_VAL_WTSP_REPLACE);
14779 } else
14780 return(XML_SCHEMAS_VAL_WTSP_PRESERVE);
14781 break;
14782 }
14783 lin = lin->next;
14784 } while (lin != NULL);
14785 break;
14786 }
14787 anc = anc->baseType;
14788 } while (anc != anyST);
14789 return (XML_SCHEMAS_VAL_WTSP_COLLAPSE);
14790 }
14791 return (-1);
14792}
14793
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014794/**
Daniel Veillard377e1a92004-04-16 16:30:05 +000014795 * xmlSchemaValidateFacetsInternal:
14796 * @ctxt: a schema validation context
Daniel Veillardc0826a72004-08-10 14:17:33 +000014797 * @type: the type holding the facets
Daniel Veillard377e1a92004-04-16 16:30:05 +000014798 * @facets: the list of facets to check
14799 * @value: the lexical repr of the value to validate
14800 * @val: the precomputed value
William M. Bracke7091952004-05-11 15:09:58 +000014801 * @fireErrors: if 0, only internal errors will be fired;
14802 * otherwise all errors will be fired.
Daniel Veillard377e1a92004-04-16 16:30:05 +000014803 *
14804 * Check a value against all facet conditions
14805 *
14806 * Returns 0 if the element is schemas valid, a positive error code
14807 * number otherwise and -1 in case of internal or API error.
14808 */
14809static int
14810xmlSchemaValidateFacetsInternal(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014811 xmlSchemaTypePtr type,
14812 const xmlChar * value,
14813 unsigned long length,
14814 int fireErrors)
Daniel Veillard377e1a92004-04-16 16:30:05 +000014815{
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014816 int ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014817 xmlNodePtr node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014818 xmlSchemaTypePtr biType; /* The build-in type. */
14819 xmlSchemaTypePtr tmpType;
14820 xmlSchemaFacetLinkPtr facetLink;
Daniel Veillardc7e3cc42004-09-28 12:33:52 +000014821 int retFacet;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014822 xmlSchemaFacetPtr facet;
14823 unsigned long len = 0;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014824
Daniel Veillardc0826a72004-08-10 14:17:33 +000014825#ifdef DEBUG_UNION_VALIDATION
14826 printf("Facets of type: '%s'\n", (const char *) type->name);
14827 printf(" fireErrors: %d\n", fireErrors);
14828#endif
14829
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014830 node = ctxt->node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014831 /*
14832 * NOTE: Do not jump away, if the facetSet of the given type is
14833 * empty: until now, "pattern" facets of the *base types* need to
14834 * be checked as well.
14835 */
14836 biType = type->baseType;
14837 while ((biType != NULL) && (biType->type != XML_SCHEMA_TYPE_BASIC))
14838 biType = biType->baseType;
14839 if (biType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014840 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014841 "Internal error: xmlSchemaValidateFacetsInternal, "
14842 "the base type axis of the given type '%s' does not resolve to "
14843 "a built-in type.\n",
14844 type->name, NULL);
14845 return (-1);
14846 }
14847
14848 if (type->facetSet != NULL) {
14849 facetLink = type->facetSet;
14850 while (facetLink != NULL) {
14851 facet = facetLink->facet;
14852 /*
14853 * Skip the pattern "whiteSpace": it is used to
14854 * format the character content beforehand.
14855 */
14856 switch (facet->type) {
14857 case XML_SCHEMA_FACET_WHITESPACE:
14858 case XML_SCHEMA_FACET_PATTERN:
14859 case XML_SCHEMA_FACET_ENUMERATION:
14860 break;
14861 case XML_SCHEMA_FACET_LENGTH:
14862 case XML_SCHEMA_FACET_MINLENGTH:
14863 case XML_SCHEMA_FACET_MAXLENGTH:
14864 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
14865 ret = xmlSchemaValidateListSimpleTypeFacet(facet,
14866 value, length, 0);
14867 len = length;
14868 } else
14869 ret = xmlSchemaValidateLengthFacet(biType, facet,
14870 value, ctxt->value, &len);
14871 break;
14872 default:
14873 ret = xmlSchemaValidateFacet(biType, facet, value,
14874 ctxt->value);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014875 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000014876 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014877 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014878 "Internal error: xmlSchemaValidateFacetsInternal, "
14879 "validating facet of type '%s'.\n",
14880 type->name, NULL);
14881 break;
14882 } else if ((ret > 0) && (fireErrors)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014883 xmlSchemaVFacetErr(ctxt, ret, node, value, len,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014884 type, facet, NULL, NULL, NULL, NULL);
14885 }
14886
14887 facetLink = facetLink->next;
14888 }
14889 if (ret >= 0) {
14890 /*
14891 * Process enumerations.
14892 */
14893 retFacet = 0;
14894 facetLink = type->facetSet;
14895 while (facetLink != NULL) {
14896 if (facetLink->facet->type == XML_SCHEMA_FACET_ENUMERATION) {
14897 retFacet = xmlSchemaValidateFacet(biType, facetLink->facet,
14898 value, ctxt->value);
14899 if (retFacet <= 0)
14900 break;
14901 }
14902 facetLink = facetLink->next;
14903 }
14904 if (retFacet > 0) {
14905 ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
14906 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014907 xmlSchemaVFacetErr(ctxt, ret, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014908 value, 0, type, NULL, NULL, NULL, NULL, NULL);
14909 } else if (retFacet < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014910 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014911 "Internal error: xmlSchemaValidateFacetsInternal, "
14912 "validating facet of type '%s'.\n",
14913 BAD_CAST "enumeration", NULL);
14914 ret = -1;
14915 }
14916 }
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014917 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000014918 if (ret >= 0) {
14919 /*
14920 * Process patters. Pattern facets are ORed at type level
14921 * and ANDed if derived. Walk the base type axis.
14922 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000014923 tmpType = type;
14924 facet = NULL;
14925 do {
14926 retFacet = 0;
14927 for (facetLink = tmpType->facetSet; facetLink != NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014928 facetLink = facetLink->next) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014929 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
14930 continue;
14931 retFacet = xmlSchemaValidateFacet(biType, facetLink->facet,
14932 value, ctxt->value);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014933 if (retFacet == 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +000014934 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014935 else if (retFacet < 0) {
14936 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
14937 "Internal error: xmlSchemaValidateFacetsInternal, "
14938 "validating 'pattern' facet '%s' of type '%s'.\n",
14939 facetLink->facet->value, tmpType->name);
14940 ret = -1;
14941 break;
14942 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +000014943 /* Save the last non-validating facet. */
14944 facet = facetLink->facet;
14945 }
14946 if (retFacet != 0)
14947 break;
14948 tmpType = tmpType->baseType;
14949 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014950 if (retFacet > 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014951 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
14952 if (fireErrors) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014953 xmlSchemaVFacetErr(ctxt, ret, node, value, 0, type, facet,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014954 NULL, NULL, NULL, NULL);
14955 }
14956 }
14957 }
14958
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014959 return (ret);
14960}
14961
Daniel Veillard4255d502002-04-16 15:50:10 +000014962/************************************************************************
14963 * *
14964 * Simple type validation *
14965 * *
14966 ************************************************************************/
Daniel Veillard377e1a92004-04-16 16:30:05 +000014967
Daniel Veillard4255d502002-04-16 15:50:10 +000014968
14969/************************************************************************
14970 * *
14971 * DOM Validation code *
14972 * *
14973 ************************************************************************/
14974
Daniel Veillard4255d502002-04-16 15:50:10 +000014975static int xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014976 xmlNodePtr elem,
Daniel Veillard3646d642004-06-02 19:19:14 +000014977 xmlSchemaTypePtr type);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014978static int xmlSchemaValidateElementByType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014979 xmlSchemaTypePtr type,
14980 int valSimpleContent);
Daniel Veillard4255d502002-04-16 15:50:10 +000014981
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000014982static void xmlSchemaBeginElement(xmlSchemaValidCtxtPtr vctxt);
14983static void xmlSchemaEndElement(xmlSchemaValidCtxtPtr vctxt);
14984
14985#ifdef ELEM_INFO_ENABLED
14986/**
14987 * xmlSchemaGetFreshElemInfo:
14988 * @vctxt: the schema validation context
14989 *
14990 * Creates/reuses and initializes the element info item for
14991 * the currect tree depth.
14992 *
14993 * Returns the element info item or NULL on API or internal errors.
14994 */
14995static xmlSchemaElemInfoPtr
14996xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)
14997{
14998 xmlSchemaElemInfoPtr info = NULL;
14999
15000 if (vctxt->depth > vctxt->sizeElemInfos) {
15001 xmlSchemaVErr(vctxt, NULL, XML_SCHEMAV_INTERNAL,
15002 "Internal error: xmlSchemaPushDepthInfo, "
15003 "an inconsistent depth encountered.\n",
15004 NULL, NULL);
15005 return (NULL);
15006 }
15007 if (vctxt->elemInfos == NULL) {
15008 vctxt->elemInfos = (xmlSchemaElemInfoPtr *)
15009 xmlMalloc(10 * sizeof(xmlSchemaElemInfoPtr));
15010 if (vctxt->elemInfos == NULL) {
15011 xmlSchemaVErrMemory(vctxt,
15012 "allocating the element info array", NULL);
15013 return (NULL);
15014 }
15015 memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaElemInfoPtr));
15016 vctxt->sizeElemInfos = 10;
15017 } else if (vctxt->sizeElemInfos == vctxt->depth) {
15018 int i = vctxt->sizeElemInfos;
15019
15020 vctxt->sizeElemInfos *= 2;
15021 vctxt->elemInfos = (xmlSchemaElemInfoPtr *)
15022 xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
15023 sizeof(xmlSchemaElemInfoPtr));
15024 if (vctxt->elemInfos == NULL) {
15025 xmlSchemaVErrMemory(vctxt,
15026 "re-allocating the element info array", NULL);
15027 return (NULL);
15028 }
15029 /*
15030 * We need the new memory to be NULLed.
15031 * TODO: Use memset instead?
15032 */
15033 for (; i < vctxt->sizeElemInfos; i++)
15034 vctxt->elemInfos[i] = NULL;
15035 } else
15036 info = vctxt->elemInfos[vctxt->depth];
15037
15038 if (info == NULL) {
15039 info = (xmlSchemaElemInfoPtr)
15040 xmlMalloc(sizeof(xmlSchemaElemInfo));
15041 if (info == NULL) {
15042 xmlSchemaVErrMemory(vctxt,
15043 "allocating an element info", NULL);
15044 return (NULL);
15045 }
15046 vctxt->elemInfos[vctxt->depth] = info;
15047 }
15048 memset(info, 0, sizeof(xmlSchemaElemInfo));
15049 info->depth = vctxt->depth;
15050
15051 return (info);
15052}
15053#endif /* ELEM_INFO_ENABLED */
15054
Daniel Veillard3646d642004-06-02 19:19:14 +000015055
15056/**
15057 * xmlSchemaFreeAttrStates:
15058 * @state: a list of attribute states
15059 *
15060 * Free the given list of attribute states
15061 *
15062 */
15063static void
15064xmlSchemaFreeAttributeStates(xmlSchemaAttrStatePtr state)
15065{
15066 xmlSchemaAttrStatePtr tmp;
15067 while (state != NULL) {
15068 tmp = state;
15069 state = state->next;
15070 xmlFree(tmp);
15071 }
15072}
15073
Daniel Veillard4255d502002-04-16 15:50:10 +000015074/**
15075 * xmlSchemaRegisterAttributes:
15076 * @ctxt: a schema validation context
15077 * @attrs: a list of attributes
15078 *
15079 * Register the list of attributes as the set to be validated on that element
15080 *
15081 * Returns -1 in case of error, 0 otherwise
15082 */
15083static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015084xmlSchemaRegisterAttributes(xmlSchemaValidCtxtPtr ctxt, xmlAttrPtr attrs)
15085{
Daniel Veillard3646d642004-06-02 19:19:14 +000015086 xmlSchemaAttrStatePtr tmp;
15087
15088 ctxt->attr = NULL;
15089 ctxt->attrTop = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000015090 while (attrs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015091 if ((attrs->ns != NULL) &&
15092 (xmlStrEqual(attrs->ns->href, xmlSchemaInstanceNs))) {
15093 attrs = attrs->next;
15094 continue;
15095 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000015096 tmp = (xmlSchemaAttrStatePtr)
15097 xmlMalloc(sizeof(xmlSchemaAttrState));
15098 if (tmp == NULL) {
15099 xmlSchemaVErrMemory(ctxt, "registering attributes", NULL);
15100 return (-1);
15101 }
Daniel Veillard3646d642004-06-02 19:19:14 +000015102 tmp->attr = attrs;
15103 tmp->state = XML_SCHEMAS_ATTR_UNKNOWN;
15104 tmp->next = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015105 tmp->decl = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000015106 if (ctxt->attr == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015107 ctxt->attr = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000015108 else
15109 ctxt->attrTop->next = tmp;
15110 ctxt->attrTop = tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015111 attrs = attrs->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000015112 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015113 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000015114}
15115
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015116#if 0 /* Currently not used */
Daniel Veillard4255d502002-04-16 15:50:10 +000015117/**
Daniel Veillard4255d502002-04-16 15:50:10 +000015118 * xmlSchemaValidateCheckNodeList
15119 * @nodelist: the list of nodes
15120 *
15121 * Check the node list is only made of text nodes and entities pointing
15122 * to text nodes
15123 *
15124 * Returns 1 if true, 0 if false and -1 in case of error
15125 */
15126static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015127xmlSchemaValidateCheckNodeList(xmlNodePtr nodelist)
15128{
Daniel Veillard4255d502002-04-16 15:50:10 +000015129 while (nodelist != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015130 if (nodelist->type == XML_ENTITY_REF_NODE) {
15131 TODO /* implement recursion in the entity content */
15132 }
15133 if ((nodelist->type != XML_TEXT_NODE) &&
15134 (nodelist->type != XML_COMMENT_NODE) &&
15135 (nodelist->type != XML_PI_NODE) &&
William M. Bracke7091952004-05-11 15:09:58 +000015136 (nodelist->type != XML_CDATA_SECTION_NODE)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015137 return (0);
15138 }
15139 nodelist = nodelist->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000015140 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015141 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +000015142}
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015143#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000015144
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015145static void
15146xmlSchemaPostSchemaAssembleFixup(xmlSchemaParserCtxtPtr ctxt)
15147{
15148 int i, nbItems;
15149 xmlSchemaTypePtr item, *items;
15150
15151
15152 /*
15153 * During the Assemble of the schema ctxt->curItems has
15154 * been filled with the relevant new items. Fix those up.
15155 */
15156 nbItems = ctxt->assemble->nbItems;
15157 items = (xmlSchemaTypePtr *) ctxt->assemble->items;
15158
15159 for (i = 0; i < nbItems; i++) {
15160 item = items[i];
15161 switch (item->type) {
15162 case XML_SCHEMA_TYPE_ATTRIBUTE:
15163 xmlSchemaAttrFixup((xmlSchemaAttributePtr) item, ctxt, NULL);
15164 break;
15165 case XML_SCHEMA_TYPE_ELEMENT:
15166 xmlSchemaRefFixupCallback((xmlSchemaElementPtr) item, ctxt,
15167 NULL, NULL, NULL);
15168 break;
15169 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
15170 xmlSchemaAttrGrpFixup((xmlSchemaAttributeGroupPtr) item,
15171 ctxt, NULL);
15172 break;
15173 case XML_SCHEMA_TYPE_GROUP:
15174 xmlSchemaGroupDefFixup(item, ctxt, NULL);
15175 default:
15176 break;
15177 }
15178 }
15179 /*
15180 * Circularity checks.
15181 */
15182 for (i = 0; i < nbItems; i++) {
15183 item = items[i];
15184 switch (item->type) {
15185 case XML_SCHEMA_TYPE_GROUP:
15186 xmlSchemaCheckGroupDefCircular(item, ctxt, NULL);
15187 break;
15188 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
15189 xmlSchemaCheckAttributeGroupCircular(
15190 (xmlSchemaAttributeGroupPtr) item, ctxt, NULL);
15191 break;
15192 default:
15193 break;
15194 }
15195 }
15196 /*
15197 * Fixup for all other item.
15198 * TODO: Hmm, not sure if starting from complex/simple types,
15199 * all subsequent items will be reached.
15200 */
15201 for (i = 0; i < nbItems; i++) {
15202 item = items[i];
15203 switch (item->type) {
15204 case XML_SCHEMA_TYPE_SIMPLE:
15205 case XML_SCHEMA_TYPE_COMPLEX:
15206 xmlSchemaTypeFixup(item, ctxt, NULL);
15207 break;
15208 default:
15209 break;
15210 }
15211 }
15212 /*
15213 * Check facet values. Note that facets are
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000015214 * hold by simple type components only (and
15215 * by complex types in the current implementation).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015216 */
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000015217 /* OLD:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015218 for (i = 0; i < nbItems; i++) {
15219 item = items[i];
15220 switch (item->type) {
15221 case XML_SCHEMA_TYPE_SIMPLE:
15222 case XML_SCHEMA_TYPE_COMPLEX:
15223 xmlSchemaCheckDefaults(item, ctxt, NULL);
15224 break;
15225 default:
15226 break;
15227 }
15228 }
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000015229 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015230 /*
15231 * Build the content model for complex types.
15232 */
15233 for (i = 0; i < nbItems; i++) {
15234 item = items[i];
15235 switch (item->type) {
15236 case XML_SCHEMA_TYPE_COMPLEX:
15237 xmlSchemaBuildContentModel(item, ctxt, NULL);
15238 break;
15239 default:
15240 break;
15241 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015242 }
15243 /*
15244 * Validate value contraint values.
15245 */
15246 for (i = 0; i < nbItems; i++) {
15247 item = items[i];
15248 switch (item->type) {
15249 case XML_SCHEMA_TYPE_ATTRIBUTE:
15250 xmlSchemaCheckAttrValConstr((xmlSchemaAttributePtr) item, ctxt, NULL);
15251 break;
15252 case XML_SCHEMA_TYPE_ELEMENT:
15253 xmlSchemaCheckElemValConstr((xmlSchemaElementPtr) item, ctxt, NULL);
15254 break;
15255 default:
15256 break;
15257 }
15258 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015259}
15260
15261/**
15262 * xmlSchemaAssembleByLocation:
15263 * @pctxt: a schema parser context
15264 * @vctxt: a schema validation context
15265 * @schema: the existing schema
15266 * @node: the node that fired the assembling
15267 * @nsName: the namespace name of the new schema
15268 * @location: the location of the schema
15269 *
15270 * Expands an existing schema by an additional schema.
15271 *
15272 * Returns 0 if the new schema is correct, a positive error code
15273 * number otherwise and -1 in case of an internal or API error.
15274 */
15275static int
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015276xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
15277 xmlSchemaPtr schema,
15278 xmlNodePtr node,
15279 const xmlChar *nsName,
15280 const xmlChar *location)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015281{
15282 const xmlChar *targetNs, *oldtns;
15283 xmlDocPtr doc, olddoc;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015284 int oldflags, ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015285 xmlNodePtr docElem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015286 xmlSchemaParserCtxtPtr pctxt;
15287
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015288 /*
15289 * This should be used:
15290 * 1. on <import>(s)
15291 * 2. if requested by the validated instance
15292 * 3. if requested via the API
15293 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015294 if ((vctxt == NULL) || (schema == NULL))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015295 return (-1);
15296 /*
15297 * Create a temporary parser context.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015298 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015299 if ((vctxt->pctxt == NULL) &&
15300 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1)) {
15301 xmlSchemaVErr(vctxt, node,
15302 XML_SCHEMAV_INTERNAL,
15303 "Internal error: xmlSchemaAssembleByLocation, "
15304 "failed to create a temp. parser context.\n",
15305 NULL, NULL);
15306 return (-1);
15307 }
15308 pctxt = vctxt->pctxt;
15309 /*
15310 * Set the counter to produce unique names for anonymous items.
15311 */
15312 pctxt->counter = schema->counter;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015313 /*
15314 * Acquire the schema document.
15315 */
15316 ret = xmlSchemaAcquireSchemaDoc(pctxt, schema, node,
15317 nsName, location, &doc, &targetNs, 0);
15318 if (ret != 0) {
15319 if (doc != NULL)
15320 xmlFreeDoc(doc);
15321 } else if (doc != NULL) {
15322 docElem = xmlDocGetRootElement(doc);
15323 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015324 * Create new assemble info.
15325 */
15326 if (pctxt->assemble == NULL) {
15327 pctxt->assemble = xmlSchemaNewAssemble();
15328 if (pctxt->assemble == NULL) {
15329 xmlSchemaVErrMemory(vctxt,
15330 "Memory error: xmlSchemaAssembleByLocation, "
15331 "allocating assemble info", NULL);
15332 xmlFreeDoc(doc);
15333 return (-1);
15334 }
15335 }
15336 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015337 * Save and reset the context & schema.
15338 */
15339 oldflags = schema->flags;
15340 oldtns = schema->targetNamespace;
15341 olddoc = schema->doc;
15342
15343 xmlSchemaClearSchemaDefaults(schema);
15344 schema->targetNamespace = targetNs;
15345 /* schema->nbCurItems = 0; */
15346 pctxt->schema = schema;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015347 pctxt->ctxtType = NULL;
15348 pctxt->parentItem = NULL;
15349
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015350 xmlSchemaParseSchemaDefaults(pctxt, schema, docElem);
15351 xmlSchemaParseSchemaTopLevel(pctxt, schema, docElem->children);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015352 xmlSchemaPostSchemaAssembleFixup(pctxt);
15353 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015354 * Set the counter of items.
15355 */
15356 schema->counter = pctxt->counter;
15357 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015358 * Free the list of assembled components.
15359 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015360 pctxt->assemble->nbItems = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015361 /*
15362 * Restore the context & schema.
15363 */
15364 schema->flags = oldflags;
15365 schema->targetNamespace = oldtns;
15366 schema->doc = olddoc;
15367 ret = pctxt->err;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015368 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015369 return (ret);
15370}
15371
15372/**
15373 * xmlSchemaAssembleByXSIAttr:
15374 * @vctxt: a schema validation context
15375 * @xsiAttr: an xsi attribute
15376 * @noNamespace: whether a schema with no target namespace is exptected
15377 *
15378 * Expands an existing schema by an additional schema using
15379 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
15380 * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
15381 * must be set to 1.
15382 *
15383 * Returns 0 if the new schema is correct, a positive error code
15384 * number otherwise and -1 in case of an internal or API error.
15385 */
15386static int
15387xmlSchemaAssembleByXSIAttr(xmlSchemaValidCtxtPtr vctxt,
15388 xmlAttrPtr xsiAttr,
15389 int noNamespace)
15390{
15391 xmlChar *value;
15392 const xmlChar *cur, *end;
15393 const xmlChar *nsname = NULL, *location;
15394 int count = 0;
15395 int ret = 0;
15396
15397 if (xsiAttr == NULL) {
15398 xmlSchemaVCustomErr(vctxt, XML_SCHEMAV_INTERNAL,
15399 NULL, NULL,
15400 "Internal error: xmlSchemaAssembleByXSIAttr, "
15401 "bad arguments", NULL);
15402 return (-1);
15403 }
15404 /*
15405 * Parse the value; we will assume an even number of values
15406 * to be given (this is how Xerces and XSV work).
15407 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015408 value = xmlNodeGetContent((xmlNodePtr) xsiAttr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015409 cur = value;
15410 do {
15411 if (noNamespace != 1) {
15412 /*
15413 * Get the namespace name.
15414 */
15415 while (IS_BLANK_CH(*cur))
15416 cur++;
15417 end = cur;
15418 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
15419 end++;
15420 if (end == cur)
15421 break;
15422 count++;
15423 nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
15424 cur = end;
15425 }
15426 /*
15427 * Get the URI.
15428 */
15429 while (IS_BLANK_CH(*cur))
15430 cur++;
15431 end = cur;
15432 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
15433 end++;
15434 if (end == cur)
15435 break;
15436 count++;
15437 location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015438 cur = end;
15439 ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015440 xsiAttr->parent, nsname, location);
15441 if (ret == -1) {
15442 xmlSchemaVCustomErr(vctxt,
15443 XML_SCHEMAV_INTERNAL,
15444 (xmlNodePtr) xsiAttr, NULL,
15445 "Internal error: xmlSchemaAssembleByXSIAttr, "
15446 "assembling schemata", NULL);
15447 if (value != NULL)
15448 xmlFree(value);
15449 return (-1);
15450 }
15451 } while (*cur != 0);
15452 if (value != NULL)
15453 xmlFree(value);
15454 return (ret);
15455}
15456
15457/**
15458 * xmlSchemaAssembleByXSIElem:
15459 * @vctxt: a schema validation context
15460 * @elem: an element node possibly holding xsi attributes
15461 * @noNamespace: whether a schema with no target namespace is exptected
15462 *
15463 * Assembles an existing schema by an additional schema using
15464 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attributes
15465 * of the given @elem.
15466 *
15467 * Returns 0 if the new schema is correct, a positive error code
15468 * number otherwise and -1 in case of an internal or API error.
15469 */
15470static int
15471xmlSchemaAssembleByXSIElem(xmlSchemaValidCtxtPtr vctxt,
15472 xmlNodePtr elem)
15473{
15474 int ret = 0, retNs = 0;
15475 xmlAttrPtr attr;
15476
15477 attr = xmlHasNsProp(elem, BAD_CAST "schemaLocation", xmlSchemaInstanceNs);
15478 if (attr != NULL) {
15479 retNs = xmlSchemaAssembleByXSIAttr(vctxt, attr, 0);
15480 if (retNs == -1)
15481 return (-1);
15482 }
15483 attr = xmlHasNsProp(elem, BAD_CAST "noNamespaceSchemaLocation", xmlSchemaInstanceNs);
15484 if (attr != NULL) {
15485 ret = xmlSchemaAssembleByXSIAttr(vctxt, attr, 1);
15486 if (ret == -1)
15487 return (-1);
15488 }
15489 if (retNs != 0)
15490 return (retNs);
15491 else
15492 return (ret);
15493}
15494
Daniel Veillard4255d502002-04-16 15:50:10 +000015495/**
Daniel Veillard4255d502002-04-16 15:50:10 +000015496 * xmlSchemaValidateCallback:
15497 * @ctxt: a schema validation context
15498 * @name: the name of the element detected (might be NULL)
15499 * @type: the type
15500 *
15501 * A transition has been made in the automata associated to an element
15502 * content model
15503 */
15504static void
15505xmlSchemaValidateCallback(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015506 const xmlChar * name ATTRIBUTE_UNUSED,
15507 xmlSchemaTypePtr type, xmlNodePtr node)
15508{
Daniel Veillard4255d502002-04-16 15:50:10 +000015509 xmlSchemaTypePtr oldtype = ctxt->type;
15510 xmlNodePtr oldnode = ctxt->node;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015511
Daniel Veillard4255d502002-04-16 15:50:10 +000015512#ifdef DEBUG_CONTENT
Daniel Veillard8651f532002-04-17 09:06:27 +000015513 xmlGenericError(xmlGenericErrorContext,
15514 "xmlSchemaValidateCallback: %s, %s, %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015515 name, type->name, node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +000015516#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015517 /*
15518 * @type->type will be XML_SCHEMA_TYPE_ANY or XML_SCHEMA_TYPE_ELEMENT.
15519 */
Daniel Veillard4255d502002-04-16 15:50:10 +000015520 ctxt->type = type;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015521 ctxt->node = node;
15522 ctxt->cur = node->children;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015523
15524#ifdef ELEM_INFO_ENABLED
15525 xmlSchemaBeginElement(ctxt);
15526#endif
15527
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015528 /*
15529 * Assemble new schemata using xsi.
15530 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015531 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015532 int ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015533
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015534 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
15535 if (ret == -1) {
15536 xmlSchemaVCustomErr(ctxt,
15537 XML_SCHEMAV_INTERNAL,
15538 ctxt->node, NULL,
15539 "Internal error: xmlSchemaValidateElement, "
15540 "assembling schema by xsi", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015541 goto leave;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015542 }
15543 /*
15544 * NOTE: We won't react on schema parser errors here.
15545 * TODO: But a warning would be nice.
15546 */
15547 }
15548 switch (type->type) {
15549 case XML_SCHEMA_TYPE_ELEMENT: {
15550 /*
15551 * NOTE: The build of the content model
15552 * (xmlSchemaBuildAContentModel) ensures that the element
15553 * declaration (and not a reference to it) will be given.
15554 */
15555 if (((xmlSchemaElementPtr) ctxt->type)->ref != NULL) {
15556 /*
15557 * This is paranoid coding ;-)... it should not
15558 * happen here any more.
15559 */
15560 xmlSchemaVCustomErr(ctxt,
15561 XML_SCHEMAV_INTERNAL,
15562 node, NULL,
15563 "Internal error: xmlSchemaValidateCallback, "
15564 "element declaration 'reference' encountered, "
15565 "but an element declaration was expected",
15566 NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015567 goto leave;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015568 }
15569 xmlSchemaValidateElementByDeclaration(ctxt,
15570 (xmlSchemaElementPtr) type);
15571 break;
15572 }
15573 case XML_SCHEMA_TYPE_ANY:
15574 xmlSchemaValidateElementByWildcard(ctxt, type);
15575 break;
15576 default:
15577 break;
15578 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015579leave:
15580
15581#ifdef ELEM_INFO_ENABLED
15582 xmlSchemaEndElement(ctxt);
15583 /*
15584 xmlSchemaDebugDumpIDCTable(stdout,
15585 NULL,
15586 ctxt->node->name,
15587 ctxt->elemInfo->idcTable);
15588 */
15589#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000015590 ctxt->type = oldtype;
15591 ctxt->node = oldnode;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015592}
Daniel Veillard4255d502002-04-16 15:50:10 +000015593
Daniel Veillard01fa6152004-06-29 17:04:39 +000015594/**
15595 * xmlSchemaValidateSimpleTypeValue:
15596 * @ctxt: a schema validation context
15597 * @value: the value to be validated
15598 * @fireErrors: shall errors be reported?
15599 * @applyFacets: shall facets be applied?
Daniel Veillardc0826a72004-08-10 14:17:33 +000015600 * @normalize: shall the value be normalized?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015601 * @checkNodes: shall the content nodes be checked?
Daniel Veillard01fa6152004-06-29 17:04:39 +000015602 *
15603 * Validates a value by the given type (user derived or built-in).
15604 *
15605 * Returns 0 if the value is valid, a positive error code
15606 * number otherwise and -1 in case of an internal or API error.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015607 */
15608static int
15609xmlSchemaValidateSimpleTypeValue(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015610 xmlSchemaTypePtr type,
15611 const xmlChar *value,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015612 int fireErrors,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015613 int applyFacets,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015614 int normalize,
15615 int checkNodes)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015616{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015617 xmlNodePtr node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015618 int ret = 0;
15619 xmlChar *normValue = NULL;
15620 int wtsp;
15621
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015622 node = ctxt->node;
15623 /* Save the current whitespace normalization type. */
Daniel Veillardc0826a72004-08-10 14:17:33 +000015624 wtsp = ctxt->valueWS;
15625 /*
15626 * Normalize the value.
15627 */
15628 if (normalize &&
15629 (ctxt->valueWS != XML_SCHEMAS_VAL_WTSP_COLLAPSE)) {
15630 int norm = xmlSchemaGetWhiteSpaceFacetValue(type);
15631
15632 if ((norm != -1) && (norm > ctxt->valueWS)) {
15633 if (norm == XML_SCHEMAS_VAL_WTSP_COLLAPSE)
15634 normValue = xmlSchemaCollapseString(value);
15635 else
15636 normValue = xmlSchemaWhiteSpaceReplace(value);
15637 ctxt->valueWS = norm;
15638 if (normValue != NULL)
15639 value = (const xmlChar *) normValue;
15640 }
15641 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015642 /*
15643 * The nodes of a content must be checked only once,
15644 * this is not working since list types will fire this
15645 * multiple times.
15646 */
15647 if ((checkNodes == 1) && (ctxt->cur != NULL)) {
15648 xmlNodePtr cur = ctxt->cur;
15649
15650 do {
15651 switch (cur->type) {
15652 case XML_TEXT_NODE:
15653 case XML_CDATA_SECTION_NODE:
15654 case XML_PI_NODE:
15655 case XML_COMMENT_NODE:
15656 case XML_XINCLUDE_START:
15657 case XML_XINCLUDE_END:
15658 break;
15659 case XML_ENTITY_REF_NODE:
15660 case XML_ENTITY_NODE:
15661 /* TODO: Scour the entities for illegal nodes. */
15662 TODO break;
15663 case XML_ELEMENT_NODE: {
15664 /* NOTE: Changed to an internal error, since the
15665 * existence of an element node will be already checked in
15666 * xmlSchemaValidateElementBySimpleType and in
15667 * xmlSchemaValidateElementByComplexType.
15668 */
15669 xmlSchemaVCustomErr(ctxt,
15670 XML_SCHEMAV_INTERNAL,
15671 /* XML_SCHEMAS_ERR_INVALIDELEM, */
15672 node, type,
15673 "Element '%s' found in simple type content",
15674 cur->name);
15675 return (XML_SCHEMAV_INTERNAL);
15676 }
15677 case XML_ATTRIBUTE_NODE:
15678 case XML_DOCUMENT_NODE:
15679 case XML_DOCUMENT_TYPE_NODE:
15680 case XML_DOCUMENT_FRAG_NODE:
15681 case XML_NOTATION_NODE:
15682 case XML_HTML_DOCUMENT_NODE:
15683 case XML_DTD_NODE:
15684 case XML_ELEMENT_DECL:
15685 case XML_ATTRIBUTE_DECL:
15686 case XML_ENTITY_DECL:
15687 case XML_NAMESPACE_DECL:
15688#ifdef LIBXML_DOCB_ENABLED
15689 case XML_DOCB_DOCUMENT_NODE:
15690#endif
15691 xmlSchemaVCustomErr(ctxt,
15692 XML_SCHEMAV_INTERNAL,
15693 /* XML_SCHEMAS_ERR_INVALIDELEM, */
15694 node, NULL,
15695 "Node of unexpected type found in simple type content",
15696 NULL);
15697 return (XML_SCHEMAV_INTERNAL);
15698 }
15699 cur = cur->next;
15700 } while (cur != NULL);
15701 }
15702
William M. Brack2f2a6632004-08-20 23:09:47 +000015703 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
15704 xmlSchemaTypePtr base, anyType;
15705
15706 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
15707
15708 base = type->baseType;
15709 while ((base != NULL) &&
15710 (base->type != XML_SCHEMA_TYPE_SIMPLE) &&
15711 (base->type != XML_SCHEMA_TYPE_BASIC) &&
15712 (base != anyType)) {
15713 base = base->baseType;
15714 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015715 ret = xmlSchemaValidateSimpleTypeValue(ctxt, base, value, 1, 0, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000015716 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015717 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000015718 "Internal error: xmlSchemaValidateSimpleTypeValue, "
15719 "validating complex type '%s'\n",
15720 type->name, NULL);
15721 } else if ((ret == 0) && (applyFacets) && (type->facetSet != NULL)) {
15722 /*
15723 * Check facets.
15724 */
15725 /*
15726 * This is somehow not nice, since if an error occurs
15727 * the reported type will be the complex type; the spec
15728 * wants a simple type to be created on the complex type
15729 * if it has a simple content. For now we have to live with
15730 * it.
15731 */
15732 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
15733 value, 0, fireErrors);
15734 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015735 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000015736 "Internal error: xmlSchemaValidateSimpleTypeValue, "
15737 "validating facets of complex type '%s'\n",
15738 type->name, NULL);
15739 } else if (ret > 0) {
15740 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
William M. Brack2f2a6632004-08-20 23:09:47 +000015741 if (fireErrors)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015742 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
William M. Brack2f2a6632004-08-20 23:09:47 +000015743 }
15744 }
15745 } else if (type->type == XML_SCHEMA_TYPE_BASIC) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015746
15747 if (ctxt->value != NULL) {
15748 xmlSchemaFreeValue(ctxt->value);
15749 ctxt->value = NULL;
15750 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015751 /*
15752 * STREAM-READ-CHILDREN.
15753 */
15754 ret = xmlSchemaValPredefTypeNodeNoNorm(type, value, &(ctxt->value), node);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015755 if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015756 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
15757 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
15758 else
15759 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015760 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015761 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015762 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015763 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015764 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000015765 "validating built-in type '%s'\n", type->name, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015766 }
15767 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
15768 /* 1.2.1 if {variety} is ·atomic· then the string must ·match·
15769 * a literal in the ·lexical space· of {base type definition}
15770 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015771 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type->baseType, value, 0, 0, 0, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015772 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015773 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015774 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000015775 "validating atomic simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000015776 type->name, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015777 } else if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015778 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015779 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015780 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015781 } else if ((applyFacets) && (type->facetSet != NULL)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015782 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000015783 * Check facets.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015784 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000015785 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
15786 value, 0, fireErrors);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015787 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015788 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015789 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000015790 "validating facets of atomic simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000015791 type->name, NULL);
15792 } else if (ret > 0) {
15793 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015794 /*
15795 Disabled, since the facet validation already reports errors.
15796 if (fireErrors)
15797 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
15798 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015799 }
15800 }
15801 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
15802
15803 xmlSchemaTypePtr tmpType;
15804 const xmlChar *cur, *end;
15805 xmlChar *tmp;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015806 unsigned long len = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015807
15808 /* 1.2.2 if {variety} is ·list· then the string must be a sequence
15809 * of white space separated tokens, each of which ·match·es a literal
15810 * in the ·lexical space· of {item type definition}
15811 */
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +000015812
Kasimier T. Buchcikde938cd2005-01-13 12:25:57 +000015813 if (value == NULL)
15814 value = BAD_CAST "";
Daniel Veillardc0826a72004-08-10 14:17:33 +000015815 tmpType = xmlSchemaGetListSimpleTypeItemType(type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015816 cur = value;
15817 do {
15818 while (IS_BLANK_CH(*cur))
15819 cur++;
15820 end = cur;
15821 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
15822 end++;
15823 if (end == cur)
15824 break;
15825 tmp = xmlStrndup(cur, end - cur);
15826 len++;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015827 ret = xmlSchemaValidateSimpleTypeValue(ctxt, tmpType, tmp, 0, 1, 0, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015828 xmlFree(tmp);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015829 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015830 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015831 "Internal error: xmlSchemaValidateSimpleTypeValue, "
15832 "validating an item of list simple type '%s'\n",
15833 type->name, NULL);
15834 break;
15835 } else if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015836 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015837 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015838 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015839 break;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015840 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015841 cur = end;
15842 } while (*cur != 0);
15843 /*
15844 * Check facets.
15845 */
15846 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015847 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015848 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000015849 "validating list simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000015850 type->name, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015851 } else if ((ret == 0) && (applyFacets)) {
15852 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
15853 value, len, fireErrors);
15854 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015855 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015856 "Internal error: xmlSchemaValidateSimpleTypeValue, "
15857 "validating facets of list simple type '%s'\n",
15858 type->name, NULL);
15859 } else if (ret > 0) {
15860 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015861 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000015862 Disabled, since the facet validation already reports errors.
15863 if (fireErrors)
15864 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015865 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000015866 }
15867
Daniel Veillard01fa6152004-06-29 17:04:39 +000015868 }
15869 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
15870 xmlSchemaTypeLinkPtr memberLink;
15871
15872 /*
15873 * TODO: For all datatypes ·derived· by ·union· whiteSpace does
15874 * not apply directly; however, the normalization behavior of ·union·
15875 * types is controlled by the value of whiteSpace on that one of the
15876 * ·memberTypes· against which the ·union· is successfully validated.
15877 *
15878 * This means that the value is normalized by the first validating
15879 * member type, then the facets of the union type are applied. This
15880 * needs changing of the value!
15881 */
15882
15883 /*
15884 * 1.2.3 if {variety} is ·union· then the string must ·match· a
15885 * literal in the ·lexical space· of at least one member of
15886 * {member type definitions}
15887 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000015888#ifdef DEBUG_UNION_VALIDATION
15889 printf("Union ST : '%s'\n", (const char *) type->name);
15890 printf(" fireErrors : %d\n", fireErrors);
15891 printf(" applyFacets: %d\n", applyFacets);
15892#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +000015893 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
15894 if (memberLink == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015895 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015896 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000015897 "union simple type '%s' has no member types\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000015898 type->name, NULL);
15899 ret = -1;
15900 }
15901 if (ret == 0) {
15902 while (memberLink != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015903 ret = xmlSchemaValidateSimpleTypeValue(ctxt, memberLink->type,
15904 value, 0, 1, 1, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015905 if ((ret <= 0) || (ret == 0))
15906 break;
15907 memberLink = memberLink->next;
15908 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015909 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015910 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015911 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000015912 "validating members of union simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000015913 type->name, NULL);
15914 } else if (ret > 0) {
15915 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015916 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015917 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015918 }
15919 }
15920 /*
15921 * Apply facets (pattern, enumeration).
15922 */
15923 if ((ret == 0) && (applyFacets) && (type->facetSet != NULL)) {
15924 int mws;
15925 /*
15926 * The normalization behavior of ·union· types is controlled by
15927 * the value of whiteSpace on that one of the ·memberTypes·
15928 * against which the ·union· is successfully validated.
15929 */
15930 if (normValue != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015931 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015932 "Internal error: xmlSchemaValidateSimpleTypeValue, "
15933 "the value was already normalized for the union simple "
15934 "type '%s'.\n", type->name, NULL);
15935 }
15936 mws = xmlSchemaGetWhiteSpaceFacetValue(memberLink->type);
15937 if (mws > ctxt->valueWS) {
15938 if (mws == XML_SCHEMAS_VAL_WTSP_COLLAPSE)
15939 normValue = xmlSchemaCollapseString(value);
15940 else
15941 normValue = xmlSchemaWhiteSpaceReplace(value);
15942 if (normValue != NULL)
15943 value = (const xmlChar *) normValue;
15944 }
15945
15946 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
15947 value, 0, fireErrors);
15948 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015949 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015950 "Internal error: xmlSchemaValidateSimpleTypeValue, "
15951 "validating facets of union simple type '%s'\n",
15952 type->name, NULL);
15953 } else if (ret > 0) {
15954 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
15955 /*
15956 if (fireErrors)
15957 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
15958 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015959 }
15960 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000015961 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000015962 ctxt->valueWS = wtsp;
15963 if (normValue != NULL)
15964 xmlFree(normValue);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015965 return (ret);
15966}
15967
15968/**
15969 * xmlSchemaValidateSimpleTypeElement:
15970 * @ctxt: a schema validation context
15971 * @node: the element node to be validated.
15972 *
15973 * Validate the element against a simple type.
15974 *
15975 * Returns 0 if the element is valid, a positive error code
15976 * number otherwise and -1 in case of an internal or API error.
15977 */
15978static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015979xmlSchemaValidateElementBySimpleType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015980 xmlSchemaTypePtr type,
15981 int valSimpleContent)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015982{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015983 xmlSchemaTypePtr oldtype;
15984 xmlNodePtr node;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015985 xmlAttrPtr attr;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015986 xmlNodePtr cur;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015987 int ret = 0, retval = 0;
15988
Daniel Veillard01fa6152004-06-29 17:04:39 +000015989 if ((ctxt == NULL) || (type == NULL)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015990 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_INTERNAL, NULL, NULL,
15991 "Internal error: xmlSchemaValidateElementBySimpleType, "
15992 "bad arguments", NULL);
15993 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015994 }
15995
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015996 oldtype = ctxt->type;
15997 node = ctxt->node;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015998 /*
15999 * cvc-type: 3.1.2 The element information item must have no element
16000 * information item [children].
16001 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016002 /*
16003 * STREAM: Child nodes are processed.
16004 */
16005 cur = node->children;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016006 while (cur != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016007 /*
16008 * TODO: Entities, will they produce elements as well?
16009 */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016010 if (cur->type == XML_ELEMENT_NODE) {
16011 xmlSchemaVCustomErr(ctxt,
16012 XML_SCHEMAV_CVC_TYPE_3_1_2,
16013 node, type,
16014 "No element content allowed", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016015 ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016016 }
16017 cur = cur->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016018 }
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016019
Daniel Veillard01fa6152004-06-29 17:04:39 +000016020 /*
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016021 * cvc-type 3.1.1:
16022 *
16023 * The attributes of must be empty, excepting those whose namespace name
16024 * is identical to http://www.w3.org/2001/XMLSchema-instance and whose local
16025 * name is one of type, nil, schemaLocation or noNamespaceSchemaLocation.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016026 */
16027 /*
16028 * STREAM: Attribute nodes are processed.
16029 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000016030 attr = node->properties;
16031 while (attr != NULL) {
16032 if ((attr->ns == NULL) ||
16033 (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
16034 ((!xmlStrEqual(attr->name, BAD_CAST "type")) &&
16035 (!xmlStrEqual(attr->name, BAD_CAST "nil")) &&
16036 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation")) &&
16037 (!xmlStrEqual
16038 (attr->name, BAD_CAST "noNamespaceSchemaLocation")))) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016039 xmlSchemaVIllegalAttrErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016040 XML_SCHEMAV_CVC_TYPE_3_1_1, attr);
16041 ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016042 }
16043 attr = attr->next;
16044 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016045 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016046 * This will skip validation if the type is 'anySimpleType' and
16047 * if the value was already validated (e.g. default values).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016048 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016049 if ((valSimpleContent == 1) &&
16050 ((type->type != XML_SCHEMA_TYPE_BASIC) ||
16051 (type->builtInType != XML_SCHEMAS_ANYSIMPLETYPE))) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016052 xmlChar *value;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016053
16054 value = xmlNodeGetContent(node);
16055 /*
16056 * NOTE: This call will not check the content nodes, since
16057 * this should be checked here already.
16058 */
16059 retval = xmlSchemaValidateSimpleTypeValue(ctxt, type, value,
16060 1, 1, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000016061 if (value != NULL)
16062 xmlFree(value);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016063 if (retval != 0)
16064 ret = retval;
William M. Brack2f2a6632004-08-20 23:09:47 +000016065 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016066 ctxt->type = oldtype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016067 return (ret);
16068}
Daniel Veillard4255d502002-04-16 15:50:10 +000016069
16070/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016071 * xmlSchemaValQNameAcquire:
16072 * @value: the lexical represantation of the QName value
16073 * @node: the node to search for the corresponding namespace declaration
16074 * @nsName: the resulting namespace name if found
16075 *
16076 * Checks that a value conforms to the lexical space of the type QName;
16077 * if valid, the corresponding namespace name is searched and retured
16078 * as a copy in @nsName. The local name is returned in @localName as
16079 * a copy.
16080 *
16081 * Returns 0 if valid, 1 if not valid by type, 2 if no corresponding
16082 * namespace declaration was found in scope; -1 in case of an internal or
16083 * API error.
16084 */
16085static int
16086xmlSchemaValQNameAcquire(const xmlChar *value, xmlNodePtr node,
16087 xmlChar **nsName, xmlChar **localName)
16088{
16089 int ret;
16090 xmlChar *local = NULL;
16091
16092 if ((nsName == NULL) || (localName == NULL) || (node == NULL))
16093 return (-1);
16094 *nsName = NULL;
16095 *localName = NULL;
16096 ret = xmlValidateQName(value, 1);
16097 if (ret == 0) {
16098 xmlChar *prefix;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016099 xmlNsPtr ns;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016100
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016101 /*
16102 * NOTE: xmlSplitQName2 will return a duplicated
16103 * string.
16104 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016105 local = xmlSplitQName2(value, &prefix);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016106 if (local == NULL)
16107 local = xmlStrdup(value);
16108 ns = xmlSearchNs(node->doc, node, prefix);
16109 /*
16110 * A namespace need not to be found if the prefix is NULL.
16111 */
16112 if (ns != NULL) {
16113 /*
16114 * TODO: Is it necessary to duplicate the URI here?
16115 */
16116 *nsName = xmlStrdup(ns->href);
16117 } else if (prefix != NULL) {
16118 xmlFree(prefix);
16119 if (local != NULL)
16120 xmlFree(local);
16121 return (2);
16122 }
16123 *localName = local;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016124 if (prefix != NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016125 xmlFree(prefix);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016126 } else
16127 return (1);
16128 return (ret);
16129}
16130
16131/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016132 * xmlSchemaHasElemContent:
16133 * @node: the node
16134 *
16135 * Scours the content of the given node for element
16136 * nodes.
16137 *
16138 * Returns 1 if an element node is found,
16139 * 0 otherwise.
16140 */
16141static int
16142xmlSchemaHasElemContent(xmlNodePtr node)
16143{
16144 if (node == NULL)
16145 return (0);
16146 node = node->children;
16147 while (node != NULL) {
16148 if (node->type == XML_ELEMENT_NODE)
16149 return (1);
16150 node = node->next;
16151 }
16152 return (0);
16153}
16154/**
16155 * xmlSchemaHasElemOrCharContent:
16156 * @node: the node
16157 *
16158 * Scours the content of the given node for element
16159 * and character nodes.
16160 *
16161 * Returns 1 if an element or character node is found,
16162 * 0 otherwise.
16163 */
16164static int
16165xmlSchemaHasElemOrCharContent(xmlNodePtr node)
16166{
16167 if (node == NULL)
16168 return (0);
16169 node = node->children;
16170 while (node != NULL) {
16171 switch (node->type) {
16172 case XML_ELEMENT_NODE:
16173 /*
16174 * TODO: Ask Daniel if these are all character nodes.
16175 */
16176 case XML_TEXT_NODE:
16177 case XML_CDATA_SECTION_NODE:
16178 /*
16179 * TODO: How XML_ENTITY_NODEs evaluated?
16180 */
16181 case XML_ENTITY_REF_NODE:
16182 case XML_ENTITY_NODE:
16183 return (1);
16184 break;
16185 default:
16186 break;
16187 }
16188 node = node->next;
16189 }
16190 return (0);
16191}
16192
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016193/************************************************************************
16194 * *
16195 * Identity-constraints (IDC) *
16196 * *
16197 ************************************************************************/
16198
16199#ifdef IDC_ENABLED
16200
16201/**
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016202 * xmlSchemaAugmentIDC:
16203 * @idcDef: the IDC definition
16204 *
16205 * Creates an augmented IDC definition item.
16206 *
16207 * Returns the item, or NULL on internal errors.
16208 */
16209static void
16210xmlSchemaAugmentIDC(xmlSchemaIDCPtr idcDef,
16211 xmlSchemaValidCtxtPtr vctxt)
16212{
16213 xmlSchemaIDCAugPtr aidc;
16214
16215 aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
16216 if (aidc == NULL) {
16217 xmlSchemaVErrMemory(vctxt,
16218 "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
16219 NULL);
16220 return;
16221 }
16222 aidc->bubbleDepth = -1;
16223 aidc->def = idcDef;
16224 aidc->next = NULL;
16225 if (vctxt->aidcs == NULL)
16226 vctxt->aidcs = aidc;
16227 else {
16228 aidc->next = vctxt->aidcs;
16229 vctxt->aidcs = aidc;
16230 }
16231}
16232
16233/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016234 * xmlSchemaIDCNewBinding:
16235 * @idcDef: the IDC definition of this binding
16236 *
16237 * Creates a new IDC binding.
16238 *
16239 * Returns the new binding in case of succeeded, NULL on internal errors.
16240 */
16241static xmlSchemaPSVIIDCBindingPtr
16242xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
16243{
16244 xmlSchemaPSVIIDCBindingPtr ret;
16245
16246 ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
16247 sizeof(xmlSchemaPSVIIDCBinding));
16248 if (ret == NULL) {
16249 xmlSchemaVErrMemory(NULL,
16250 "allocating a PSVI IDC binding item", NULL);
16251 return (NULL);
16252 }
16253 memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
16254 ret->definition = idcDef;
16255 return (ret);
16256}
16257
16258/**
16259 * xmlSchemaIDCStoreNodeTableItem:
16260 * @vctxt: the WXS validation context
16261 * @item: the IDC node table item
16262 *
16263 * The validation context is used to store an IDC node table items.
16264 * They are stored to avoid copying them if IDC node-tables are merged
16265 * with corresponding parent IDC node-tables (bubbling).
16266 *
16267 * Returns 0 if succeeded, -1 on internal errors.
16268 */
16269static int
16270xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
16271 xmlSchemaPSVIIDCNodePtr item)
16272{
16273 /*
16274 * Add to gobal list.
16275 */
16276 if (vctxt->idcNodes == NULL) {
16277 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
16278 xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
16279 if (vctxt->idcNodes == NULL) {
16280 xmlSchemaVErrMemory(vctxt,
16281 "allocating the IDC node table item list", NULL);
16282 return (-1);
16283 }
16284 vctxt->sizeIdcNodes = 20;
16285 } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
16286 vctxt->sizeIdcNodes *= 2;
16287 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
16288 xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
16289 sizeof(xmlSchemaPSVIIDCNodePtr));
16290 if (vctxt->idcNodes == NULL) {
16291 xmlSchemaVErrMemory(vctxt,
16292 "re-allocating the IDC node table item list", NULL);
16293 return (-1);
16294 }
16295 }
16296 vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
16297
16298 return (0);
16299}
16300
16301/**
16302 * xmlSchemaIDCStoreKey:
16303 * @vctxt: the WXS validation context
16304 * @item: the IDC key
16305 *
16306 * The validation context is used to store an IDC key.
16307 *
16308 * Returns 0 if succeeded, -1 on internal errors.
16309 */
16310static int
16311xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
16312 xmlSchemaPSVIIDCKeyPtr key)
16313{
16314 /*
16315 * Add to gobal list.
16316 */
16317 if (vctxt->idcKeys == NULL) {
16318 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
16319 xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
16320 if (vctxt->idcKeys == NULL) {
16321 xmlSchemaVErrMemory(vctxt,
16322 "allocating the IDC key storage list", NULL);
16323 return (-1);
16324 }
16325 vctxt->sizeIdcKeys = 40;
16326 } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
16327 vctxt->sizeIdcKeys *= 2;
16328 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
16329 xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
16330 sizeof(xmlSchemaPSVIIDCKeyPtr));
16331 if (vctxt->idcKeys == NULL) {
16332 xmlSchemaVErrMemory(vctxt,
16333 "re-allocating the IDC key storage list", NULL);
16334 return (-1);
16335 }
16336 }
16337 vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
16338
16339 return (0);
16340}
16341
16342/**
16343 * xmlSchemaIDCAppendNodeTableItem:
16344 * @bind: the IDC binding
16345 * @ntItem: the node-table item
16346 *
16347 * Appends the IDC node-table item to the binding.
16348 *
16349 * Returns 0 on success and -1 on internal errors.
16350 */
16351static int
16352xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
16353 xmlSchemaPSVIIDCNodePtr ntItem)
16354{
16355 if (bind->nodeTable == NULL) {
16356 bind->sizeNodes = 10;
16357 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
16358 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
16359 if (bind->nodeTable == NULL) {
16360 xmlSchemaVErrMemory(NULL,
16361 "allocating an array of IDC node-table items", NULL);
16362 return(-1);
16363 }
16364 } else if (bind->sizeNodes <= bind->nbNodes) {
16365 bind->sizeNodes *= 2;
16366 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
16367 xmlRealloc(bind->nodeTable, bind->sizeNodes *
16368 sizeof(xmlSchemaPSVIIDCNodePtr));
16369 if (bind->nodeTable == NULL) {
16370 xmlSchemaVErrMemory(NULL,
16371 "re-allocating an array of IDC node-table items", NULL);
16372 return(-1);
16373 }
16374 }
16375 bind->nodeTable[bind->nbNodes++] = ntItem;
16376 return(0);
16377}
16378
16379/**
16380 * xmlSchemaIDCAquireBinding:
16381 * @vctxt: the WXS validation context
16382 * @matcher: the IDC matcher
16383 *
16384 * Looks up an PSVI IDC binding, for the IDC definition and
16385 * of the given matcher. If none found, a new one is created
16386 * and added to the IDC table.
16387 *
16388 * Returns an IDC binding or NULL on internal errors.
16389 */
16390static xmlSchemaPSVIIDCBindingPtr
16391xmlSchemaIDCAquireBinding(xmlSchemaValidCtxtPtr vctxt,
16392 xmlSchemaIDCMatcherPtr matcher)
16393{
16394 xmlSchemaElemInfoPtr info;
16395
16396 info = vctxt->elemInfos[matcher->depth];
16397
16398 if (info->idcTable == NULL) {
16399 info->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
16400 if (info->idcTable == NULL)
16401 return (NULL);
16402 return(info->idcTable);
16403 } else {
16404 xmlSchemaPSVIIDCBindingPtr bind = NULL;
16405
16406 bind = info->idcTable;
16407 do {
16408 if (bind->definition == matcher->aidc->def)
16409 return(bind);
16410 if (bind->next == NULL) {
16411 bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
16412 if (bind->next == NULL)
16413 return (NULL);
16414 return(bind->next);
16415 }
16416 bind = bind->next;
16417 } while (bind != NULL);
16418 }
16419 return (NULL);
16420}
16421
16422/**
16423 * xmlSchemaIDCFreeKey:
16424 * @key: the IDC key
16425 *
16426 * Frees an IDC key together with its compiled value.
16427 */
16428static void
16429xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
16430{
16431 if (key->compValue != NULL)
16432 xmlSchemaFreeValue(key->compValue);
16433 xmlFree(key);
16434}
16435
16436/**
16437 * xmlSchemaIDCFreeBinding:
16438 *
16439 * Frees an IDC binding. Note that the node table-items
16440 * are not freed.
16441 */
16442xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
16443{
16444 if (bind->nodeTable != NULL) {
16445 xmlFree(bind->nodeTable);
16446 }
16447 xmlFree(bind);
16448}
16449
16450/**
16451 * xmlSchemaIDCFreeIDCTable:
16452 * @bind: the first IDC binding in the list
16453 *
16454 * Frees an IDC table, i.e. all the IDC bindings in the list.
16455 */
16456static void
16457xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
16458{
16459 xmlSchemaPSVIIDCBindingPtr prev;
16460
16461 while (bind != NULL) {
16462 prev = bind;
16463 bind = bind->next;
16464 xmlSchemaIDCFreeBinding(prev);
16465 }
16466}
16467
16468/**
16469 * xmlSchemaIDCFreeMatcherList:
16470 * @matcher: the first IDC matcher in the list
16471 *
16472 * Frees a list of IDC matchers.
16473 */
16474static void
16475xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
16476{
16477 xmlSchemaIDCMatcherPtr next;
16478
16479 while (matcher != NULL) {
16480 next = matcher->next;
16481 if (matcher->keySeqs != NULL) {
16482 int i;
16483 for (i = 0; i < matcher->sizeKeySeqs; i++)
16484 if (matcher->keySeqs[i] != NULL)
16485 xmlFree(matcher->keySeqs[i]);
16486 xmlFree(matcher->keySeqs);
16487 }
16488 xmlFree(matcher);
16489 matcher = next;
16490 }
16491}
16492
16493/**
16494 * xmlSchemaAreValuesEqual:
16495 * @ta: the first type
16496 * @a: the first value
16497 * @tb: the second type
16498 * @b: the second value
16499 *
16500 * Compares two values.
16501 *
16502 * Returns 1 if they are equal, 0 if not and -1 on internal errors.
16503 */
16504static int
16505xmlSchemaAreValuesEqual(xmlSchemaTypePtr ta,
16506 xmlSchemaValPtr a,
16507 xmlSchemaTypePtr tb,
16508 xmlSchemaValPtr b)
16509{
16510 int typeEqual = 0;
16511
16512 /* Same user derived/built-in derived/built-in primitive types. */
16513 if (ta == tb)
16514 goto compareValue;
16515
16516 /*
16517 * Comparison with anySimpleTypes is not supported by this implemention.
16518 */
16519 if ((ta->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
16520 (tb->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
16521 return(0);
16522
16523 /*
16524 * 4.2.1 equal (data-types)
16525 *
16526 * the ·value space·s of all ·primitive· datatypes are disjoint
16527 * (they do not share any values)
16528 */
16529 if ((ta->builtInType != 0) && (tb->builtInType != 0) &&
16530 (ta->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE) &&
16531 (tb->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
16532 return(0);
16533
16534 if ((ta->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
16535 (ta->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) ||
16536 (tb->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
16537 (tb->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)) {
16538 TODO
16539 return(0);
16540 }
16541 /*
16542 * (1) if a datatype T' is ·derived· by ·restriction· from an atomic datatype
16543 * T then the ·value space· of T' is a subset of the ·value space· of T.
16544 */
16545 /*
16546 * (2) if datatypes T' and T'' are ·derived· by ·restriction· from a common
16547 * atomic ancestor T then the ·value space·s of T' and T'' may overlap.
16548 */
16549
16550 {
16551 xmlSchemaTypePtr pta = ta, ptb = tb;
16552
16553 /* Note that we will compare the primitives here. */
16554 while ((pta->builtInType == 0) ||
16555 ((pta->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE) == 0))
16556 pta = pta->baseType;
16557 while ((ptb->builtInType == 0) ||
16558 ((ptb->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE) == 0))
16559 ptb = ptb->baseType;
16560 if (pta == ptb)
16561 goto compareValue;
16562 return(0);
16563 }
16564compareValue:
16565 {
16566#ifdef IDC_VALUE_SUPPORT
16567 int ret;
16568 ret = xmlSchemaCompareValuesOpt(a, b,
16569 XML_SCHEMA_VALUECOMP_STRISNORM);
16570 if (ret == 0)
16571 return(1);
16572 else if (ret == -2)
16573 return(-1);
16574 else
16575 return(0);
16576#else
16577 return (1);
16578#endif
16579 }
16580}
16581
16582/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016583 * xmlSchemaIDCAddStateObject:
16584 * @vctxt: the WXS validation context
16585 * @matcher: the IDC matcher
16586 * @sel: the XPath information
16587 * @parent: the parent "selector" state object if any
16588 * @type: "selector" or "field"
16589 *
16590 * Creates/reuses and activates state objects for the given
16591 * XPath information; if the XPath expression consists of unions,
16592 * multiple state objects are created for every unioned expression.
16593 *
16594 * Returns 0 on success and -1 on internal errors.
16595 */
16596static int
16597xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
16598 xmlSchemaIDCMatcherPtr matcher,
16599 xmlSchemaIDCSelectPtr sel,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016600 int type)
16601{
16602 xmlSchemaIDCStateObjPtr sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016603
16604 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016605 * Reuse the state objects from the pool.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016606 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016607 if (vctxt->xpathStatePool != NULL) {
16608 sto = vctxt->xpathStatePool;
16609 vctxt->xpathStatePool = sto->next;
16610 sto->next = NULL;
16611 } else {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016612 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016613 * Create a new state object.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016614 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016615 sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
16616 if (sto == NULL) {
16617 xmlSchemaVErrMemory(NULL,
16618 "allocating an IDC state object", NULL);
16619 return (-1);
16620 }
16621 memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
16622 }
16623 /*
16624 * Add to global list.
16625 */
16626 if (vctxt->xpathStates != NULL)
16627 sto->next = vctxt->xpathStates;
16628 vctxt->xpathStates = sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016629
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016630 /*
16631 * Free the old xpath validation context.
16632 */
16633 if (sto->xpathCtxt != NULL)
16634 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
16635
16636 /*
16637 * Create a new XPath (pattern) validation context.
16638 */
16639 sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
16640 (xmlPatternPtr) sel->xpathComp);
16641 if (sto->xpathCtxt == NULL) {
16642 xmlSchemaVErr(vctxt, vctxt->node,
16643 XML_SCHEMAV_INTERNAL,
16644 "Internal error: xmlSchemaIDCAddStateObject, "
16645 "failed to create the XPath validation context.\n",
16646 NULL, NULL);
16647 return (-1);
16648 }
16649 sto->type = type;
16650 sto->depth = vctxt->depth;
16651 sto->matcher = matcher;
16652 sto->sel = sel;
16653 sto->nbHistory = 0;
16654
16655#if DEBUG_IDC
16656 xmlGenericError(xmlGenericErrorContext, "IDC: STO push '%s'\n",
16657 sto->sel->xpath);
16658#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016659 return (0);
16660}
16661
16662/**
16663 * xmlSchemaXPathEvaluate:
16664 * @vctxt: the WXS validation context
16665 * @nodeType: the nodeType of the current node
16666 *
16667 * Evaluates all active XPath state objects.
16668 *
16669 * Returns the number of IC "field" state objects which resolved to
16670 * this node, 0 if none resolved and -1 on internal errors.
16671 */
16672static int
16673xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
16674 const xmlChar *namespaceName,
16675 const xmlChar *localName,
16676 xmlElementType nodeType)
16677{
16678 xmlSchemaIDCStateObjPtr sto, head = NULL, first;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016679 int res, resolved = 0;
16680
16681 if (vctxt->xpathStates == NULL)
16682 return (0);
16683#if DEBUG_IDC
16684 {
16685 xmlChar *str = NULL;
16686 xmlGenericError(xmlGenericErrorContext,
16687 "IDC: EVAL on %s, depth %d, type %d\n",
16688 xmlSchemaFormatNsUriLocal(&str, namespaceName,
16689 localName), vctxt->depth, nodeType);
16690 FREE_AND_NULL(str)
16691 }
16692#endif
16693 /*
16694 * Process all active XPath state objects.
16695 */
16696 first = vctxt->xpathStates;
16697 sto = first;
16698 while (sto != head) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016699#if DEBUG_IDC
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016700 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016701 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] selector '%s'\n",
16702 sto->matcher->aidc->def->name, sto->sel->xpath);
16703 else
16704 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] field '%s'\n",
16705 sto->matcher->aidc->def->name, sto->sel->xpath);
16706#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016707
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016708#ifdef IDC_XPATH_SUPPORT
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016709 res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
16710 localName, namespaceName);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016711#else
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016712 res = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016713#endif
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016714 if (res == -1) {
16715 xmlSchemaVErr(vctxt, vctxt->node,
16716 XML_SCHEMAV_INTERNAL,
16717 "Internal error: xmlSchemaXPathEvaluate, "
16718 "failed to evaluate a node.\n",
16719 NULL, NULL);
16720 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016721 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016722 if (res == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016723 goto next_sto;
16724 /*
16725 * Full match.
16726 */
16727#if DEBUG_IDC
16728 xmlGenericError(xmlGenericErrorContext, "IDC: "
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016729 "MATCH\n");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016730#endif
16731 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016732 * Register a match in the state object history.
16733 */
16734 if (sto->history == NULL) {
16735 sto->history = (int *) xmlMalloc(5 * sizeof(int));
16736 if (sto->history == NULL) {
16737 xmlSchemaVErrMemory(NULL,
16738 "allocating the state object history", NULL);
16739 return(-1);
16740 }
16741 sto->sizeHistory = 10;
16742 } else if (sto->sizeHistory <= sto->nbHistory) {
16743 sto->sizeHistory *= 2;
16744 sto->history = (int *) xmlRealloc(sto->history,
16745 sto->sizeHistory * sizeof(int));
16746 if (sto->history == NULL) {
16747 xmlSchemaVErrMemory(NULL,
16748 "re-allocating the state object history", NULL);
16749 return(-1);
16750 }
16751 }
16752 sto->history[sto->nbHistory++] = vctxt->depth;
16753
16754#ifdef DEBUG_IDC
16755 xmlGenericError(xmlGenericErrorContext, "IDC: push match '%d'\n",
16756 vctxt->depth);
16757#endif
16758
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016759 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
16760 xmlSchemaIDCSelectPtr sel;
16761 /*
16762 * Activate state objects for the IDC fields of
16763 * the IDC selector.
16764 */
16765#if DEBUG_IDC
16766 xmlGenericError(xmlGenericErrorContext, "IDC: "
16767 "activating field states\n");
16768#endif
16769 sel = sto->matcher->aidc->def->fields;
16770 while (sel != NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016771 if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
16772 sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
16773 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016774 sel = sel->next;
16775 }
16776 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
16777 /*
16778 * An IDC key node was found.
16779 */
16780#if DEBUG_IDC
16781 xmlGenericError(xmlGenericErrorContext,
16782 "IDC: key found\n");
16783#endif
16784 /*
16785 * Notify that the character value of this node is
16786 * needed.
16787 */
16788 if (resolved == 0)
16789 vctxt->elemInfo->flags |= XML_SCHEMA_ELEM_INFO_VALUE_NEEDED;
16790 resolved++;
16791 }
16792next_sto:
16793 if (sto->next == NULL) {
16794 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016795 * Evaluate field state objects created on this node as well.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016796 */
16797 head = first;
16798 sto = vctxt->xpathStates;
16799 } else
16800 sto = sto->next;
16801 }
16802 return (resolved);
16803}
16804
16805/**
16806 * xmlSchemaXPathProcessChanges:
16807 * @vctxt: the WXS validation context
16808 * @type: the simple/complex type of the current node if any at all
16809 *
16810 * Processes and pops the history items of the IDC state objects.
16811 * IDC key-sequences are validated/created on IDC bindings.
16812 *
16813 * Returns 0 on success and -1 on internal errors.
16814 */
16815static int
16816xmlSchemaXPathProcessChanges(xmlSchemaValidCtxtPtr vctxt,
16817 xmlSchemaTypePtr type)
16818{
16819 xmlSchemaIDCStateObjPtr sto, nextsto;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016820 int res, matchDepth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016821 xmlSchemaPSVIIDCKeyPtr key = NULL;
16822
16823 if (vctxt->xpathStates == NULL)
16824 return (0);
16825 sto = vctxt->xpathStates;
16826
16827#if DEBUG_IDC
16828 {
16829 xmlChar *str = NULL;
16830 xmlGenericError(xmlGenericErrorContext,
16831 "IDC: BACK on %s, depth %d\n",
16832 xmlSchemaFormatNsUriLocal(&str, vctxt->elemInfo->namespaceName,
16833 vctxt->elemInfo->localName), vctxt->depth);
16834 FREE_AND_NULL(str)
16835 }
16836#endif
16837
16838 /*
16839 * Evaluate the state objects.
16840 */
16841 while (sto != NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016842 if (sto->nbHistory == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016843 goto deregister_check;
16844
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016845 matchDepth = sto->history[sto->nbHistory -1];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016846
16847 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016848 * Only matches at the current depth are of interest.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016849 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016850 if (matchDepth != vctxt->depth) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016851 sto = sto->next;
16852 continue;
16853 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016854
16855 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
16856 if (! IS_SIMPLE_TYPE(type)) {
16857 /*
16858 * Not qualified if the field resolves to a node of non
16859 * simple type.
16860 */
16861 xmlSchemaVCustomErr(vctxt,
16862 XML_SCHEMAV_CVC_IDC,
16863 vctxt->node,
16864 (xmlSchemaTypePtr) sto->matcher->aidc->def,
16865 "The field '%s' does evaluate to a node of "
16866 "non-simple type", sto->sel->xpath);
16867
16868 sto->nbHistory--;
16869 goto deregister_check;
16870 }
16871 if ((key == NULL) && (vctxt->value == NULL)) {
16872 /*
16873 * Failed to provide the normalized value; maby
16874 * the value was invalid.
16875 */
16876 xmlSchemaVErr(vctxt, NULL,
16877 XML_SCHEMAV_INTERNAL,
16878 "Internal error: xmlSchemaIDCEvaluateMatches, "
16879 "normalized node value not available.\n",
16880 NULL, NULL);
16881 sto->nbHistory--;
16882 goto deregister_check;
16883 } else {
16884 xmlSchemaIDCMatcherPtr matcher = sto->matcher;
16885 xmlSchemaPSVIIDCKeyPtr *keySeq;
16886 int pos, index;
16887
16888 /*
16889 * The key will be anchored on the matcher's list of
16890 * key-sequences. The position in this list is determined
16891 * by the target node's depth relative to the matcher's
16892 * depth of creation (i.e. the depth of the scope element).
16893 */
16894 pos = sto->depth - matcher->depth;
16895 index = sto->sel->index;
16896
16897 /*
16898 * Create/grow the array of key-sequences.
16899 */
16900 if (matcher->keySeqs == NULL) {
16901 if (pos > 9)
16902 matcher->sizeKeySeqs = pos * 2;
16903 else
16904 matcher->sizeKeySeqs = 10;
16905 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
16906 xmlMalloc(matcher->sizeKeySeqs *
16907 sizeof(xmlSchemaPSVIIDCKeyPtr *));
16908 if (matcher->keySeqs == NULL) {
16909 xmlSchemaVErrMemory(NULL,
16910 "allocating an array of key-sequences",
16911 NULL);
16912 return(-1);
16913 }
16914 memset(matcher->keySeqs, 0,
16915 matcher->sizeKeySeqs *
16916 sizeof(xmlSchemaPSVIIDCKeyPtr *));
16917 } else if (pos >= matcher->sizeKeySeqs) {
16918 int i = matcher->sizeKeySeqs;
16919
16920 matcher->sizeKeySeqs *= 2;
16921 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
16922 xmlRealloc(matcher->keySeqs,
16923 matcher->sizeKeySeqs *
16924 sizeof(xmlSchemaPSVIIDCKeyPtr *));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016925 if (matcher->keySeqs == NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016926 xmlSchemaVErrMemory(NULL,
16927 "reallocating an array of key-sequences",
16928 NULL);
16929 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016930 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016931 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016932 * The array needs to be NULLed.
16933 * TODO: Use memset?
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016934 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016935 for (; i < matcher->sizeKeySeqs; i++)
16936 matcher->keySeqs[i] = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016937 }
16938
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016939 /*
16940 * Get/create the key-sequence.
16941 */
16942 keySeq = matcher->keySeqs[pos];
16943 if (keySeq == NULL) {
16944 goto create_sequence;
16945 } else {
16946 if (keySeq[index] != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016947 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016948 * cvc-identity-constraint:
16949 * 3 For each node in the ·target node set· all
16950 * of the {fields}, with that node as the context
16951 * node, evaluate to either an empty node-set or
16952 * a node-set with exactly one member, which must
16953 * have a simple type.
16954 *
16955 * The key was already set; report an error.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016956 */
16957 xmlSchemaVCustomErr(vctxt,
16958 XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016959 vctxt->node, (xmlSchemaTypePtr) matcher->aidc->def,
16960 "The field '%s' evaluates to a node-set "
16961 "with more than one member", sto->sel->xpath);
16962 sto->nbHistory--;
16963 goto deregister_check;
16964 } else {
16965 goto create_key;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016966 }
16967 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016968
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016969create_sequence:
16970 /*
16971 * Create a key-sequence.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016972 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016973 keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
16974 matcher->aidc->def->nbFields *
16975 sizeof(xmlSchemaPSVIIDCKeyPtr));
16976 if (keySeq == NULL) {
16977 xmlSchemaVErrMemory(NULL,
16978 "allocating an IDC key-sequence", NULL);
16979 return(-1);
16980 }
16981 memset(keySeq, 0, matcher->aidc->def->nbFields *
16982 sizeof(xmlSchemaPSVIIDCKeyPtr));
16983 matcher->keySeqs[pos] = keySeq;
16984create_key:
16985 /*
16986 * Created a key once per node only.
16987 */
16988 if (key == NULL) {
16989 key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
16990 sizeof(xmlSchemaPSVIIDCKey));
16991 if (key == NULL) {
16992 xmlSchemaVErrMemory(NULL,
16993 "allocating a IDC key", NULL);
16994 xmlFree(keySeq);
16995 matcher->keySeqs[pos] = NULL;
16996 return(-1);
16997 }
16998 /*
16999 * Consume the compiled value.
17000 */
17001 key->type = type;
17002 key->compValue = vctxt->value;
17003 vctxt->value = NULL;
17004 /*
17005 * Store the key in a global list.
17006 */
17007 if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
17008 xmlSchemaIDCFreeKey(key);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017009 return (-1);
17010 }
17011 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017012 keySeq[index] = key;
17013 }
17014 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017015
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017016 xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
17017 xmlSchemaPSVIIDCBindingPtr bind;
17018 xmlSchemaPSVIIDCNodePtr ntItem;
17019 xmlSchemaIDCMatcherPtr matcher;
17020 xmlSchemaIDCPtr idc;
17021 int pos, i, j, nbKeys;
17022 /*
17023 * Here we have the following scenario:
17024 * An IDC 'selector' state object resolved to a target node,
17025 * during the time this target node was in the
17026 * ancestor-or-self axis, the 'field' state object(s) looked
17027 * out for matching nodes to create a key-sequence for this
17028 * target node. Now we are back to this target node and need
17029 * to put the key-sequence, together with the target node
17030 * itself, into the node-table of the corresponding IDC
17031 * binding.
17032 */
17033 matcher = sto->matcher;
17034 idc = matcher->aidc->def;
17035 nbKeys = idc->nbFields;
17036 pos = vctxt->depth - matcher->depth;
17037 /*
17038 * Check if the matcher has any key-sequences at all, plus
17039 * if it has a key-sequence for the current target node.
17040 */
17041 if ((matcher->keySeqs == NULL) ||
17042 (matcher->sizeKeySeqs <= pos)) {
17043 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
17044 goto selector_key_error;
17045 else
17046 goto selector_leave;
17047 }
17048
17049 keySeq = &(matcher->keySeqs[pos]);
17050 if (*keySeq == NULL) {
17051 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
17052 goto selector_key_error;
17053 else
17054 goto selector_leave;
17055 }
17056
17057 for (i = 0; i < nbKeys; i++) {
17058 if ((*keySeq)[i] == NULL) {
17059 /*
17060 * Not qualified, if not all fields did resolve.
17061 */
17062 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
17063 /*
17064 * All fields of a "key" IDC must resolve.
17065 */
17066 goto selector_key_error;
17067 }
17068 goto selector_leave;
17069 }
17070 }
17071 /*
17072 * All fields did resolve.
17073 */
17074
17075 /*
17076 * 4.1 If the {identity-constraint category} is unique(/key),
17077 * then no two members of the ·qualified node set· have
17078 * ·key-sequences· whose members are pairwise equal, as
17079 * defined by Equal in [XML Schemas: Datatypes].
17080 *
17081 * Get the IDC binding from the matcher and check for
17082 * duplicate key-sequences.
17083 */
17084 bind = xmlSchemaIDCAquireBinding(vctxt, matcher);
17085 if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
17086 (bind->nbNodes != 0)) {
17087 xmlSchemaPSVIIDCKeyPtr key, bkey, *bkeySeq;
17088
17089 i = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017090 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017091 * Compare the key-sequences, key by key.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017092 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017093 do {
17094 bkeySeq = bind->nodeTable[i]->keys;
17095 for (j = 0; j < nbKeys; j++) {
17096 key = (*keySeq)[j];
17097 bkey = bkeySeq[j];
17098 res = xmlSchemaAreValuesEqual(key->type,
17099 key->compValue, bkey->type, bkey->compValue);
17100 if (res == -1) {
17101 return (-1);
17102 } else if (res == 0)
17103 break;
17104 }
17105 if (res == 1) {
17106 /*
17107 * Duplicate found.
17108 */
17109 break;
17110 }
17111 i++;
17112 } while (i < bind->nbNodes);
17113 if (i != bind->nbNodes) {
17114 /*
17115 * TODO: Try to report the key-sequence.
17116 */
17117 xmlSchemaVCustomErr(vctxt,
17118 XML_SCHEMAV_CVC_IDC,
17119 vctxt->node,
17120 (xmlSchemaTypePtr) idc,
17121 "Duplicate key-sequence found", NULL);
17122
17123 goto selector_leave;
17124 }
17125 }
17126 /*
17127 * Add a node-table item to the IDC binding.
17128 */
17129 ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
17130 sizeof(xmlSchemaPSVIIDCNode));
17131 if (ntItem == NULL) {
17132 xmlSchemaVErrMemory(NULL,
17133 "allocating an IDC node-table item", NULL);
17134 xmlFree(*keySeq);
17135 *keySeq = NULL;
17136 return(-1);
17137 }
17138 memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
17139
17140 /*
17141 * Store the node-table item on global list.
17142 */
17143 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
17144 if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
17145 xmlFree(ntItem);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017146 xmlFree(*keySeq);
17147 *keySeq = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017148 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017149 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017150 }
17151 /*
17152 * Init the node-table item. Consume the key-sequence.
17153 */
17154 ntItem->node = vctxt->node;
17155 ntItem->keys = *keySeq;
17156 *keySeq = NULL;
17157 if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1) {
17158 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
17159 /*
17160 * Free the item, since keyref items won't be
17161 * put on a global list.
17162 */
17163 xmlFree(ntItem->keys);
17164 xmlFree(ntItem);
17165 }
17166 return (-1);
17167 }
17168
17169 goto selector_leave;
17170selector_key_error:
17171 /*
17172 * 4.2.1 (KEY) The ·target node set· and the
17173 * ·qualified node set· are equal, that is, every
17174 * member of the ·target node set· is also a member
17175 * of the ·qualified node set· and vice versa.
17176 */
17177 xmlSchemaVCustomErr(vctxt,
17178 XML_SCHEMAV_CVC_IDC,
17179 vctxt->node,
17180 (xmlSchemaTypePtr) idc,
17181 "All 'key' fields must evaluate to a node",
17182 NULL);
17183selector_leave:
17184 /*
17185 * Free the key-sequence if not added to the IDC table.
17186 */
17187 if (*keySeq != NULL) {
17188 xmlFree(*keySeq);
17189 *keySeq = NULL;
17190 }
17191 } /* if selector */
17192
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017193 sto->nbHistory--;
17194
17195deregister_check:
17196 /*
17197 * Deregister state objects if they reach the depth of creation.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017198 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017199 if ((sto->nbHistory == 0) && (sto->depth == vctxt->depth)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017200#if DEBUG_IDC
17201 xmlGenericError(xmlGenericErrorContext, "IDC: STO pop '%s'\n",
17202 sto->sel->xpath);
17203#endif
17204 if (vctxt->xpathStates != sto) {
17205 xmlSchemaVErr(vctxt, vctxt->node,
17206 XML_SCHEMAV_INTERNAL,
17207 "Internal error: xmlSchemaXPathProcessChanges, "
17208 "The state object to be removed is not the first "
17209 "in the list.\n",
17210 NULL, NULL);
17211 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017212 nextsto = sto->next;
17213 /*
17214 * Unlink from the list of active XPath state objects.
17215 */
17216 vctxt->xpathStates = sto->next;
17217 sto->next = vctxt->xpathStatePool;
17218 /*
17219 * Link it to the pool of reusable state objects.
17220 */
17221 vctxt->xpathStatePool = sto;
17222 sto = nextsto;
17223 } else
17224 sto = sto->next;
17225 } /* while (sto != NULL) */
17226 return (0);
17227}
17228
17229/**
17230 * xmlSchemaIDCRegisterMatchers:
17231 * @vctxt: the WXS validation context
17232 * @elemDecl: the element declaration
17233 *
17234 * Creates helper objects to evaluate IDC selectors/fields
17235 * successively.
17236 *
17237 * Returns 0 if OK and -1 on internal errors.
17238 */
17239static int
17240xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
17241 xmlSchemaElementPtr elemDecl)
17242{
17243 xmlSchemaIDCMatcherPtr matcher, last = NULL;
17244 xmlSchemaIDCPtr idc, refIdc;
17245 xmlSchemaIDCAugPtr aidc;
17246
17247 idc = (xmlSchemaIDCPtr) elemDecl->idcs;
17248 if (idc == NULL)
17249 return (0);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017250
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017251#if DEBUG_IDC
17252 {
17253 xmlChar *str = NULL;
17254 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017255 "IDC: REGISTER on %s, depth %d\n",
17256 (char *) xmlSchemaFormatNsUriLocal(&str, vctxt->elemInfo->namespaceName,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017257 vctxt->elemInfo->localName), vctxt->depth);
17258 FREE_AND_NULL(str)
17259 }
17260#endif
17261 if (vctxt->elemInfo->idcMatchers != NULL) {
17262 xmlSchemaVErr(vctxt, vctxt->node,
17263 XML_SCHEMAV_INTERNAL,
17264 "Internal error: xmlSchemaIDCRegisterMatchers: "
17265 "The chain of IDC matchers is expected to be empty.\n",
17266 NULL, NULL);
17267 return (-1);
17268 }
17269 do {
17270 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
17271 /*
17272 * Since IDCs bubbles are expensive we need to know the
17273 * depth at which the bubbles should stop; this will be
17274 * the depth of the top-most keyref IDC. If no keyref
17275 * references a key/unique IDC, the bubbleDepth will
17276 * be -1, indicating that no bubbles are needed.
17277 */
17278 refIdc = (xmlSchemaIDCPtr) idc->ref->item;
17279 if (refIdc != NULL) {
17280 /*
17281 * Lookup the augmented IDC.
17282 */
17283 aidc = vctxt->aidcs;
17284 while (aidc != NULL) {
17285 if (aidc->def == refIdc)
17286 break;
17287 aidc = aidc->next;
17288 }
17289 if (aidc == NULL) {
17290 xmlSchemaVErr(vctxt, vctxt->node,
17291 XML_SCHEMAV_INTERNAL,
17292 "Internal error: xmlSchemaIDCRegisterMatchers: "
17293 "Could not find an augmented IDC item for an IDC "
17294 "definition.\n",
17295 NULL, NULL);
17296 return (-1);
17297 }
17298 if ((aidc->bubbleDepth == -1) ||
17299 (vctxt->depth < aidc->bubbleDepth))
17300 aidc->bubbleDepth = vctxt->depth;
17301 }
17302 }
17303 /*
17304 * Lookup the augmented IDC item for the IDC definition.
17305 */
17306 aidc = vctxt->aidcs;
17307 while (aidc != NULL) {
17308 if (aidc->def == idc)
17309 break;
17310 aidc = aidc->next;
17311 }
17312 if (aidc == NULL) {
17313 xmlSchemaVErr(vctxt, vctxt->node,
17314 XML_SCHEMAV_INTERNAL,
17315 "Internal error: xmlSchemaIDCRegisterMatchers: "
17316 "Could not find an augmented IDC item for an IDC definition.\n",
17317 NULL, NULL);
17318 return (-1);
17319 }
17320 /*
17321 * Create an IDC matcher for every IDC definition.
17322 */
17323 matcher = (xmlSchemaIDCMatcherPtr)
17324 xmlMalloc(sizeof(xmlSchemaIDCMatcher));
17325 if (matcher == NULL) {
17326 xmlSchemaVErrMemory(vctxt,
17327 "allocating an IDC matcher", NULL);
17328 return (-1);
17329 }
17330 memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
17331 if (last == NULL)
17332 vctxt->elemInfo->idcMatchers = matcher;
17333 else
17334 last->next = matcher;
17335 last = matcher;
17336
17337 matcher->type = IDC_MATCHER;
17338 matcher->depth = vctxt->depth;
17339 matcher->aidc = aidc;
17340#if DEBUG_IDC
17341 xmlGenericError(xmlGenericErrorContext, "IDC: register matcher\n");
17342#endif
17343 /*
17344 * Init the automaton state object.
17345 */
17346 if (xmlSchemaIDCAddStateObject(vctxt, matcher,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017347 idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017348 return (-1);
17349
17350 idc = idc->next;
17351 } while (idc != NULL);
17352 return (0);
17353}
17354
17355/**
17356 * xmlSchemaBubbleIDCNodeTables:
17357 * @depth: the current tree depth
17358 *
17359 * Merges IDC bindings of an element at @depth into the corresponding IDC
17360 * bindings of its parent element. If a duplicate note-table entry is found,
17361 * both, the parent node-table entry and child entry are discarded from the
17362 * node-table of the parent.
17363 *
17364 * Returns 0 if OK and -1 on internal errors.
17365 */
17366static int
17367xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
17368{
17369 xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
17370 xmlSchemaPSVIIDCBindingPtr *parTable, parBind, lastParBind; /* parent IDC bindings. */
17371 xmlSchemaPSVIIDCNodePtr node, parNode; /* node-table entries. */
17372 xmlSchemaPSVIIDCKeyPtr key, parKey; /* keys of in a key-sequence. */
17373 xmlSchemaIDCAugPtr aidc;
17374 int i, j, k, ret, oldNum, newDupls = 0;
17375 int duplTop;
17376
17377 /*
17378 * The node table has the following sections:
17379 *
17380 * O --> old node-table entries (first)
17381 * O
17382 * + --> new node-table entries
17383 * +
17384 * % --> new duplicate node-table entries
17385 * %
17386 * # --> old duplicate node-table entries
17387 * # (last)
17388 *
17389 */
17390 bind = vctxt->elemInfo->idcTable;
17391 if (bind == NULL) {
17392 /* Fine, no table, no bubbles. */
17393 return (0);
17394 }
17395
17396 parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
17397 /*
17398 * Walk all bindings; create new or add to existing bindings.
17399 * Remove duplicate key-sequences.
17400 */
17401start_binding:
17402 while (bind != NULL) {
17403 /*
17404 * Skip keyref IDCs.
17405 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017406 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
17407 bind = bind->next;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017408 continue;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017409 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017410 /*
17411 * Check if the key/unique IDC table needs to be bubbled.
17412 */
17413 aidc = vctxt->aidcs;
17414 do {
17415 if (aidc->def == bind->definition) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017416 if (aidc->bubbleDepth >= vctxt->depth) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017417 bind = bind->next;
17418 goto start_binding;
17419 }
17420 break;
17421 }
17422 aidc = aidc->next;
17423 } while (aidc != NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017424
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017425 if (parTable != NULL)
17426 parBind = *parTable;
17427 while (parBind != NULL) {
17428 /*
17429 * Search a matching parent binding for the
17430 * IDC definition.
17431 */
17432 if (parBind->definition == bind->definition) {
17433
17434 /*
17435 * Compare every node-table entry of the child node,
17436 * i.e. the key-sequence within, ...
17437 */
17438 oldNum = parBind->nbNodes; /* Skip newly added items. */
17439 duplTop = oldNum + parBind->nbDupls;
17440
17441 for (i = 0; i < bind->nbNodes; i++) {
17442 node = bind->nodeTable[i];
17443 if (node == NULL)
17444 continue;
17445 /*
17446 * ...with every key-sequence of the parent node, already
17447 * evaluated to be a duplicate key-sequence.
17448 */
17449 if (parBind->nbDupls != 0) {
17450 j = bind->nbNodes + newDupls;
17451 while (j < duplTop) {
17452 parNode = parBind->nodeTable[j];
17453 for (k = 0; k < bind->definition->nbFields; k++) {
17454 key = node->keys[k];
17455 parKey = parNode->keys[k];
17456 ret = xmlSchemaAreValuesEqual(key->type,
17457 key->compValue,
17458 parKey->type, parKey->compValue);
17459 if (ret == -1) {
17460 /* TODO: Internal error */
17461 return(-1);
17462 } else if (ret == 0)
17463 break;
17464
17465 }
17466 if (ret == 1)
17467 /* Duplicate found. */
17468 break;
17469 j++;
17470 }
17471 if (j != duplTop) {
17472 /* Duplicate found. */
17473 continue;
17474 }
17475 }
17476 /*
17477 * ... and with every key-sequence of the parent node.
17478 */
17479 j = 0;
17480 while (j < oldNum) {
17481 parNode = parBind->nodeTable[j];
17482 /*
17483 * Compare key by key.
17484 */
17485 for (k = 0; k < parBind->definition->nbFields; k++) {
17486 key = node->keys[k];
17487 parKey = parNode->keys[k];
17488
17489 ret = xmlSchemaAreValuesEqual(key->type,
17490 key->compValue,
17491 parKey->type, parKey->compValue);
17492 if (ret == -1) {
17493 /* TODO: Internal error */
17494 } else if (ret == 0)
17495 break;
17496
17497 }
17498 if (ret == 1)
17499 /*
17500 * The key-sequences are equal.
17501 */
17502 break;
17503 j++;
17504 }
17505 if (j != oldNum) {
17506 /*
17507 * Handle duplicates.
17508 */
17509 newDupls++;
17510 oldNum--;
17511 parBind->nbNodes--;
17512 /*
17513 * Move last old item to pos of duplicate.
17514 */
17515 parBind->nodeTable[j] =
17516 parBind->nodeTable[oldNum];
17517
17518 if (parBind->nbNodes != oldNum) {
17519 /*
17520 * If new items exist, move last new item to
17521 * last of old items.
17522 */
17523 parBind->nodeTable[oldNum] =
17524 parBind->nodeTable[parBind->nbNodes];
17525 }
17526 /*
17527 * Move duplicate to last pos of new/old items.
17528 */
17529 parBind->nodeTable[parBind->nbNodes] = parNode;
17530
17531 } else {
17532 /*
17533 * Add the node-table entry (node and key-sequence) of
17534 * the child node to the node table of the parent node.
17535 */
17536 if (parBind->nodeTable == NULL) {
17537 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
17538 xmlMalloc(1 * sizeof(xmlSchemaPSVIIDCNodePtr));
17539 if (parBind->nodeTable == NULL) {
17540 xmlSchemaVErrMemory(NULL,
17541 "allocating IDC list of node-table items", NULL);
17542 return(-1);
17543 }
17544 parBind->sizeNodes = 1;
17545 } else if (duplTop >= parBind->sizeNodes) {
17546 parBind->sizeNodes++;
17547 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
17548 xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
17549 sizeof(xmlSchemaPSVIIDCNodePtr));
17550 if (parBind->nodeTable == NULL) {
17551 xmlSchemaVErrMemory(NULL,
17552 "re-allocating IDC list of node-table items", NULL);
17553 return(-1);
17554 }
17555 }
17556
17557 /*
17558 * Move first old duplicate to last position
17559 * of old duplicates +1.
17560 */
17561 if (parBind->nbDupls != 0) {
17562 parBind->nodeTable[duplTop] =
17563 parBind->nodeTable[parBind->nbNodes + newDupls];
17564 }
17565 /*
17566 * Move first new duplicate to last position of
17567 * new duplicates +1.
17568 */
17569 if (newDupls != 0) {
17570 parBind->nodeTable[parBind->nbNodes + newDupls] =
17571 parBind->nodeTable[parBind->nbNodes];
17572 }
17573 /*
17574 * Append the new node-table entry to the 'new node-table
17575 * entries' section.
17576 */
17577 parBind->nodeTable[parBind->nbNodes] = node;
17578 parBind->nbNodes++;
17579 duplTop++;
17580 }
17581 }
17582 parBind->nbDupls += newDupls;
17583 break;
17584 }
17585 if (parBind->next == NULL)
17586 lastParBind = parBind;
17587 parBind = parBind->next;
17588 }
17589 if (parBind == NULL) {
17590 /*
17591 * No binding for the IDC was found: create a new one and
17592 * copy all node-tables.
17593 */
17594 parBind = xmlSchemaIDCNewBinding(bind->definition);
17595 if (parBind == NULL)
17596 return(-1);
17597
17598 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
17599 xmlMalloc(bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
17600 if (parBind->nodeTable == NULL) {
17601 xmlSchemaVErrMemory(NULL,
17602 "allocating an array of IDC node-table items", NULL);
17603 xmlSchemaIDCFreeBinding(parBind);
17604 return(-1);
17605 }
17606 parBind->sizeNodes = bind->nbNodes;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017607 parBind->nbNodes = bind->nbNodes;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017608 memcpy(parBind->nodeTable, bind->nodeTable,
17609 bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017610 if (*parTable == NULL)
17611 *parTable = parBind;
17612 else
17613 lastParBind->next = parBind;
17614 }
17615 bind = bind->next;
17616 }
17617 return (0);
17618}
17619
17620/**
17621 * xmlSchemaCheckCVCIDCKeyRef:
17622 * @vctxt: the WXS validation context
17623 * @elemDecl: the element declaration
17624 *
17625 * Check the cvc-idc-keyref constraints.
17626 */
17627static int
17628xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
17629{
17630 xmlSchemaPSVIIDCBindingPtr refbind, bind;
17631
17632 refbind = vctxt->elemInfo->idcTable;
17633 /*
17634 * Find a keyref.
17635 */
17636 while (refbind != NULL) {
17637 if (refbind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
17638 int i, j, k, res;
17639 xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
17640 xmlSchemaPSVIIDCKeyPtr refKey, key;
17641
17642 /*
17643 * Find the referred key/unique.
17644 */
17645 bind = vctxt->elemInfo->idcTable;
17646 do {
17647 if ((xmlSchemaIDCPtr) refbind->definition->ref->item ==
17648 bind->definition)
17649 break;
17650 bind = bind->next;
17651 } while (bind != NULL);
17652
17653 /*
17654 * Search for a matching key-sequences.
17655 */
17656 for (i = 0; i < refbind->nbNodes; i++) {
17657 res = 0;
17658 if (bind != NULL) {
17659 refKeys = refbind->nodeTable[i]->keys;
17660 for (j = 0; j < bind->nbNodes; j++) {
17661 keys = bind->nodeTable[j]->keys;
17662 for (k = 0; k < bind->definition->nbFields; k++) {
17663 refKey = refKeys[k];
17664 key = keys[k];
17665 res = xmlSchemaAreValuesEqual(key->type, key->compValue,
17666 refKey->type, refKey->compValue);
17667 if (res == 0)
17668 break;
17669 else if (res == -1) {
17670 return (-1);
17671 }
17672 }
17673 if (res == 1) {
17674 /*
17675 * Match found.
17676 */
17677 break;
17678 }
17679 }
17680 }
17681 if (res == 0) {
17682 /* TODO: Report the key-sequence. */
17683 xmlSchemaVCustomErr(vctxt,
17684 XML_SCHEMAV_CVC_IDC,
17685 refbind->nodeTable[i]->node,
17686 (xmlSchemaTypePtr) refbind->definition,
17687 "No matching key-sequence found", NULL);
17688 }
17689 }
17690 }
17691 refbind = refbind->next;
17692 }
17693 return (0);
17694}
17695#endif /* IDC_ENABLED */
17696
17697#ifdef ELEM_INFO_ENABLED
17698/**
17699 * xmlSchemaBeginElement:
17700 * @vctxt: the WXS validation context
17701 *
17702 * Just a temporary workaround to simulate streaming validation
17703 * a bit.
17704 */
17705static void
17706xmlSchemaBeginElement(xmlSchemaValidCtxtPtr vctxt)
17707{
17708 vctxt->depth++;
17709 vctxt->elemInfo = xmlSchemaGetFreshElemInfo(vctxt);
17710 vctxt->elemInfo->node = vctxt->node;
17711 vctxt->elemInfo->localName = vctxt->node->name;
17712 if (vctxt->node->ns != NULL)
17713 vctxt->elemInfo->namespaceName = vctxt->node->ns->href;
17714 else
17715 vctxt->elemInfo->namespaceName = NULL;
17716}
17717
17718/**
17719 * xmlSchemaEndElement:
17720 * @vctxt: the WXS validation context
17721 *
17722 * Just a temporary workaround to simulate streaming validation
17723 * a bit.
17724 */
17725static void
17726xmlSchemaEndElement(xmlSchemaValidCtxtPtr vctxt)
17727{
17728 if (vctxt->depth < 0) {
17729 /* TODO: raise error? */
17730 vctxt->depth--;
17731 return;
17732 }
17733#ifdef IDC_ENABLED
17734 /*
17735 * Evaluate the history of changes of active state objects.
17736 */
17737 xmlSchemaXPathProcessChanges(vctxt, vctxt->elemInfo->typeDef);
17738
17739 if (vctxt->elemInfo->value != NULL) {
17740 xmlSchemaFreeValue(vctxt->elemInfo->value);
17741 vctxt->elemInfo->value = NULL;
17742 }
17743 /*
17744 * TODO: 6 The element information item must be ·valid· with respect to each of
17745 * the {identity-constraint definitions} as per Identity-constraint
17746 * Satisfied (§3.11.4).
17747 */
17748 /*
17749 * Validate IDC keyrefs.
17750 */
17751 xmlSchemaCheckCVCIDCKeyRef(vctxt);
17752#endif
17753
17754 /*
17755 * Merge/free the IDC table.
17756 */
17757 if (vctxt->elemInfo->idcTable != NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017758#ifdef IDC_ENABLED
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017759#ifdef DEBUG_IDC
17760 xmlSchemaDebugDumpIDCTable(stdout,
17761 vctxt->elemInfo->namespaceName,
17762 vctxt->elemInfo->localName,
17763 vctxt->elemInfo->idcTable);
17764#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017765 if (vctxt->depth > 0) {
17766 /*
17767 * Merge the IDC node table with the table of the parent node.
17768 */
17769 xmlSchemaBubbleIDCNodeTables(vctxt);
17770 }
17771 /*
17772 * TODO: Don't free the PSVI IDC tables if they are
17773 * requested for the PSVI.
17774 */
17775 xmlSchemaIDCFreeIDCTable(vctxt->elemInfo->idcTable);
17776#endif
17777 vctxt->elemInfo->idcTable = NULL;
17778 }
17779
17780 /*
17781 * Cleanup IDC matchers.
17782 */
17783#ifdef IDC_ENABLED
17784 if (vctxt->elemInfo->idcMatchers != NULL) {
17785 xmlSchemaIDCFreeMatcherList(vctxt->elemInfo->idcMatchers);
17786 vctxt->elemInfo->idcMatchers = NULL;
17787 }
17788#endif
17789
17790 /*
17791 * Skip further processing if we are on the validation root.
17792 */
17793 if (vctxt->depth == 0) {
17794 vctxt->depth--;
17795 return;
17796 }
17797
17798 /*
17799 * Reset the bubbleDepth if needed.
17800 */
17801#ifdef IDC_ENABLED
17802 if (vctxt->aidcs != NULL) {
17803 xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
17804 do {
17805 if (aidc->bubbleDepth == vctxt->depth) {
17806 /*
17807 * A bubbleDepth of a key/unique IDC matches the current
17808 * depth, this means that we are leaving the scope of the
17809 * top-most keyref IDC.
17810 */
17811 aidc->bubbleDepth = -1;
17812 }
17813 aidc = aidc->next;
17814 } while (aidc != NULL);
17815 }
17816#endif
17817 vctxt->depth--;
17818 vctxt->elemInfo = vctxt->elemInfos[vctxt->depth];
17819 vctxt->node = vctxt->elemInfo->node;
17820}
17821
17822#endif /* ELEM_INFO_ENABLED */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017823
17824/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017825 * xmlSchemaValidateElementByDeclaration:
Daniel Veillard4255d502002-04-16 15:50:10 +000017826 * @ctxt: a schema validation context
17827 * @node: the top node.
17828 *
17829 * Validate the content of an element type.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017830 * Validation Rule: Element Locally Valid (Element)
Daniel Veillard4255d502002-04-16 15:50:10 +000017831 *
17832 * Returns 0 if the element is schemas valid, a positive error code
17833 * number otherwise and -1 in case of internal or API error.
17834 */
17835static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017836xmlSchemaValidateElementByDeclaration(xmlSchemaValidCtxtPtr ctxt,
17837 xmlSchemaElementPtr elemDecl)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017838{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017839 xmlNodePtr elem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017840 int ret = 0;
17841 xmlSchemaTypePtr actualType = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017842 xmlAttrPtr attr;
17843 xmlChar *attrValue;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017844 int nilled = 0, elemHasContent = -1;
Daniel Veillard3646d642004-06-02 19:19:14 +000017845
17846 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017847 * This one is called by xmlSchemaValidateElementByWildcardInternal,
17848 * xmlSchemaValidateElementByAnyType and xmlSchemaValidateElement.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017849 * Note that @elemDecl will be the declaration and never the
17850 * reference to a declaration.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017851 */
Daniel Veillard3646d642004-06-02 19:19:14 +000017852
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017853 if (ctxt == NULL) {
17854 xmlSchemaVErr(ctxt, NULL, XML_SCHEMAV_INTERNAL,
17855 "Internal error: xmlSchemaValidateElementByDeclaration, "
17856 "bad arguments.\n",
17857 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017858 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000017859 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017860
17861 elem = ctxt->node;
17862
17863 /*
17864 * cvc-elt (3.3.4) : 1
17865 */
17866 if (elemDecl == NULL) {
17867 xmlSchemaVCustomErr(ctxt,
17868 XML_SCHEMAV_CVC_ELT_1,
17869 elem, NULL,
17870 "No matching declaration available", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017871 /*
17872 * Evaluate IDCs even if an error occured.
17873 */
17874#ifdef IDC_ENABLED
17875 if (xmlSchemaXPathEvaluate(ctxt, ctxt->elemInfo->namespaceName,
17876 ctxt->elemInfo->localName, XML_ELEMENT_NODE) == -1)
17877 return (-1);
17878#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017879 return (ctxt->err);
17880 }
17881 /*
17882 * cvc-elt (3.3.4) : 2
17883 */
17884 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
17885 xmlSchemaVCustomErr(ctxt,
17886 XML_SCHEMAV_CVC_ELT_2,
17887 elem, NULL,
17888 "The element declaration is abstract", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017889 /*
17890 * Evaluate IDCs even if an error occured.
17891 */
17892#ifdef IDC_ENABLED
17893 if (xmlSchemaXPathEvaluate(ctxt, ctxt->elemInfo->namespaceName,
17894 ctxt->elemInfo->localName, XML_ELEMENT_NODE) == -1)
17895 return (-1);
17896#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017897 return (ctxt->err);
17898 }
17899
17900 /*
17901 * cvc-elt (3.3.4) : 3
17902 * Handle 'xsi:nil'.
17903 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017904
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017905 attr = xmlHasNsProp(elem, BAD_CAST "nil", xmlSchemaInstanceNs);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017906 if (attr != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017907 attrValue = xmlNodeGetContent((xmlNodePtr) attr);
17908 ctxt->node = (xmlNodePtr) attr;
17909 ctxt->cur = attr->children;
17910 ret = xmlSchemaValidateSimpleTypeValue(ctxt,
17911 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
17912 BAD_CAST attrValue, 1, 1, 1, 1);
17913 ctxt->node = elem;
17914 ctxt->type = (xmlSchemaTypePtr) elemDecl;
17915 if (ret < 0) {
17916 xmlSchemaVCustomErr(ctxt,
17917 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017918 (xmlNodePtr) attr, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017919 "Internal error: xmlSchemaValidateElementByDeclaration, "
17920 "validating the attribute 'xsi:nil'", NULL);
17921 if (attrValue != NULL)
17922 xmlFree(attrValue);
17923 return (-1);
17924 }
17925 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017926 /*
17927 * cvc-elt (3.3.4) : 3.1
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017928 */
17929 xmlSchemaVCustomErr(ctxt,
17930 XML_SCHEMAV_CVC_ELT_3_1,
17931 elem, NULL,
17932 "The element is not 'nillable'", NULL);
17933 } else {
17934 if (xmlStrEqual(BAD_CAST attrValue, BAD_CAST "true") ||
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017935 xmlStrEqual(BAD_CAST attrValue, BAD_CAST "1")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017936 ret = 0;
17937 /*
17938 * cvc-elt (3.3.4) : 3.2.1
17939 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017940 elemHasContent = xmlSchemaHasElemOrCharContent(elem);
17941 if (elemHasContent == 1) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017942 xmlSchemaVCustomErr(ctxt,
17943 XML_SCHEMAV_CVC_ELT_3_2_1,
17944 /* XML_SCHEMAS_ERR_NOTEMPTY, */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017945 elem, (xmlSchemaTypePtr) elemDecl,
17946 "The 'nilled' element must have no character or "
17947 "element content", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017948 ret = XML_SCHEMAV_CVC_ELT_3_2_1;
17949 }
17950 /*
17951 * cvc-elt (3.3.4) : 3.2.2
17952 */
17953 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
17954 (elemDecl->value != NULL)) {
17955 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_CVC_ELT_3_2_2,
17956 /* XML_SCHEMAS_ERR_HAVEDEFAULT, */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017957 elem, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017958 "There is a fixed value constraint defined for "
17959 "the 'nilled' element", NULL);
17960 ret = XML_SCHEMAV_CVC_ELT_3_2_2;
17961 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017962 if (ret == 0)
17963 nilled = 1;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017964 }
17965 }
17966 if (attrValue != NULL)
17967 xmlFree(attrValue);
17968 }
17969
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017970
17971 actualType = elemDecl->subtypes;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017972 /*
17973 * cvc-elt (3.3.4) : 4
17974 * Handle 'xsi:type'.
17975 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017976
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017977 attr = xmlHasNsProp(elem, BAD_CAST "type", xmlSchemaInstanceNs);
17978 if (attr != NULL) {
17979 xmlChar *nsName = NULL, *local = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017980
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017981 /*
17982 * TODO: We should report a *warning* that the type was overriden
17983 * by the instance.
17984 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017985
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017986 /*
17987 * cvc-elt (3.3.4) : 4.1
17988 */
17989 attrValue = xmlNodeGetContent((xmlNodePtr) attr);
17990 ret = xmlSchemaValQNameAcquire(attrValue, attr->parent,
17991 &nsName, &local);
17992 if (ret < 0) {
17993 xmlSchemaVCustomErr(ctxt,
17994 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017995 (xmlNodePtr) attr, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017996 "Internal error: xmlSchemaValidateElementByDeclaration, "
17997 "validating the attribute 'xsi:type'", NULL);;
17998 FREE_AND_NULL(attrValue)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017999 FREE_AND_NULL(nsName)
18000 FREE_AND_NULL(local)
18001 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018002 } else if (ret == 1) {
18003 xmlSchemaVSimpleTypeErr(ctxt,
18004 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
18005 (xmlNodePtr) attr, attrValue,
18006 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME));
18007 } else if (ret == 2) {
18008 xmlSchemaVCustomErr(ctxt,
18009 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
18010 (xmlNodePtr) attr,
18011 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
18012 "The QName value '%s' has no "
18013 "corresponding namespace declaration in scope",
18014 attrValue);
18015 } else {
18016 /*
18017 * cvc-elt (3.3.4) : 4.2
18018 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018019 actualType = xmlSchemaGetType(ctxt->schema, local, nsName);
18020 if (actualType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018021 xmlChar *strA = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018022
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018023 xmlSchemaVCustomErr(ctxt,
18024 XML_SCHEMAV_CVC_ELT_4_2,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018025 (xmlNodePtr) attr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018026 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
18027 "The value %s does not resolve to a type "
18028 "definition",
18029 xmlSchemaFormatNsUriLocal(&strA, nsName, local));
18030 FREE_AND_NULL(strA);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018031 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018032 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018033 * URGENT TODO: cvc-elt (3.3.4) : 4.3 (Type Derivation OK)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018034 */
18035 }
18036 }
18037 FREE_AND_NULL(attrValue)
18038 FREE_AND_NULL(nsName)
18039 FREE_AND_NULL(local)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018040 }
18041 /* TODO: Change the handling of missing types according to
18042 * the spec.
18043 */
18044 if (actualType == NULL) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018045 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018046 XML_SCHEMAV_CVC_TYPE_1,
18047 elem, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018048 "The type definition is absent", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018049 /*
18050 * Evaluate IDCs even if an error occured.
18051 */
18052#ifdef IDC_ENABLED
18053 if (xmlSchemaXPathEvaluate(ctxt, ctxt->elemInfo->namespaceName,
18054 ctxt->elemInfo->localName, XML_ELEMENT_NODE) == -1)
18055 return (-1);
18056#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018057 return (XML_SCHEMAV_CVC_TYPE_1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018058 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018059
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018060 /*
18061 * TODO: Since this should be already checked by the content model automaton,
18062 * and we want to get rid of the XML_SCHEMAS_ERR... types, the error code
18063 * has been changed to XML_SCHEMAV_INTERNAL.
18064 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018065 /*
Daniel Veillard4255d502002-04-16 15:50:10 +000018066 if (child == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000018067 if (decl->minOccurs > 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018068 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018069 XML_SCHEMAS_ERR_MISSING,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018070 "Element %s: missing child %s\n",
18071 node->name, decl->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018072 }
18073 return (ctxt->err);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018074 }
18075 */
Daniel Veillard4255d502002-04-16 15:50:10 +000018076 /*
18077 * Verify the element matches
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018078 * TODO, FIXME: Can this still happen here? Isn't this already checked
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018079 * by the content model automaton?
Daniel Veillardc0826a72004-08-10 14:17:33 +000018080 if (!xmlStrEqual(child->name, decl->name)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018081 xmlSchemaVErr3(ctxt, node, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018082 XML_SCHEMAS_ERR_WRONGELEM,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018083 "Element %s: missing child %s found %s\n",
18084 node->name, decl->name, child->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018085 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000018086 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018087 */
18088 if (elemHasContent == -1)
18089 elemHasContent = xmlSchemaHasElemOrCharContent(elem);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018090
18091 /*
18092 * IDC: Register identity-constraint XPath matchers.
18093 */
18094#ifdef IDC_ENABLED
18095 if (elemDecl->idcs != NULL)
18096 xmlSchemaIDCRegisterMatchers(ctxt, elemDecl);
18097 /*
18098 * Evaluate IDCs.
18099 */
18100 if (xmlSchemaXPathEvaluate(ctxt, ctxt->elemInfo->namespaceName,
18101 ctxt->elemInfo->localName, XML_ELEMENT_NODE) == -1)
18102 return (-1);
18103#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018104 /*
18105 * cvc-elt (3.3.4) : 5
18106 * The appropriate case among the following must be true:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018107 */
Daniel Veillard4255d502002-04-16 15:50:10 +000018108 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018109 * cvc-elt (3.3.4) : 5.1
18110 * If the declaration has a {value constraint},
18111 * the item has neither element nor character [children] and
18112 * clause 3.2 has not applied, then all of the following must be true:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018113 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018114 if ((elemHasContent == 0) && (nilled == 0) && (elemDecl->value != NULL)) {
18115 /*
18116 * cvc-elt (3.3.4) : 5.1.1
18117 * If the ·actual type definition· is a ·local type definition·
18118 * then the canonical lexical representation of the {value constraint}
18119 * value must be a valid default for the ·actual type definition· as
18120 * defined in Element Default Valid (Immediate) (§3.3.6).
18121 */
18122 /*
18123 * NOTE: 'local' above means types aquired by xsi:type.
18124 */
18125 ret = 0;
18126 if (actualType != elemDecl->subtypes) {
18127 xmlSchemaCreatePCtxtOnVCtxt(ctxt);
18128 ret = xmlSchemaCheckCOSValidDefault(ctxt->pctxt, ctxt, actualType,
18129 elemDecl->value, NULL);
18130 if (ret < 0) {
18131 xmlSchemaVCustomErr(ctxt,
18132 XML_SCHEMAV_INTERNAL,
18133 elem, actualType,
18134 "Internal error: xmlSchemaValidateElementByDeclaration, "
18135 "validating a default value", NULL);
18136 return (-1);
18137 }
18138 }
18139 /*
18140 * cvc-elt (3.3.4) : 5.1.2
18141 * The element information item with the canonical lexical
18142 * representation of the {value constraint} value used as its
18143 * ·normalized value· must be ·valid· with respect to the
18144 * ·actual type definition· as defined by Element Locally Valid (Type)
18145 * (§3.3.4).
18146 */
18147 /*
18148 * Disable validation of the simple content, since it was already
18149 * done above.
18150 */
18151 if (ret == 0) {
18152 if (actualType != elemDecl->subtypes)
18153 ret = xmlSchemaValidateElementByType(ctxt, actualType, 0);
18154 else
18155 ret = xmlSchemaValidateElementByType(ctxt, actualType, 0);
18156 ctxt->node = elem;
18157 if (ret < 0) {
18158 xmlSchemaVCustomErr(ctxt,
18159 XML_SCHEMAV_INTERNAL,
18160 elem, actualType,
18161 "Internal error: xmlSchemaValidateElementByDeclaration, "
18162 "validating against the type", NULL);
18163 return (-1);
18164 }
18165 /*
18166 * PSVI: Create a text node on the instance element.
18167 */
18168 if (ctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
18169 xmlNodePtr textChild;
18170
18171 textChild = xmlNewText(elemDecl->value);
18172 if (textChild == NULL) {
18173 xmlSchemaVCustomErr(ctxt,
18174 XML_SCHEMAV_INTERNAL,
18175 elem, actualType,
18176 "Internal error: xmlSchemaValidateElementByDeclaration, "
18177 "could not create a default text node for the instance",
18178 NULL);
18179 } else
18180 xmlAddChild(elem, textChild);
18181 }
18182 }
18183
18184 } else {
18185 /*
18186 * 5.2.1 The element information item must be ·valid· with respect
18187 * to the ·actual type definition· as defined by Element Locally
18188 * Valid (Type) (§3.3.4).
18189 */
18190 ret = xmlSchemaValidateElementByType(ctxt, actualType, 1);
18191 ctxt->node = elem;
18192 if (ret < 0) {
18193 xmlSchemaVCustomErr(ctxt,
18194 XML_SCHEMAV_INTERNAL,
18195 elem, actualType,
18196 "Internal error: xmlSchemaValidateElementByDeclaration, "
18197 "validating a default value", NULL);
18198 return (-1);
18199 }
18200 /*
18201 * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
18202 * not applied, all of the following must be true:
18203 */
18204
18205 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) && (nilled == 0)) {
18206 /*
18207 * 5.2.2.1 The element information item must have no element
18208 * information item [children].
18209 *
18210 * TODO REDUNDANT: If the actual type exists, the above call to
18211 * xmlSchemaValidateElementByType will already check for element
18212 * nodes.
18213 */
18214 if (xmlSchemaHasElemContent(elem)) {
18215 xmlSchemaVCustomErr(ctxt,
18216 XML_SCHEMAV_CVC_ELT_5_2_2_1,
18217 elem, (xmlSchemaTypePtr) elemDecl,
18218 "Elements in the content are not allowed if it is "
18219 "constrained by a fixed value", NULL);
18220 } else {
18221 /*
18222 * 5.2.2.2 The appropriate case among the following must
18223 * be true:
18224 */
18225
18226 if (actualType->contentType == XML_SCHEMA_CONTENT_MIXED) {
18227 xmlChar *value;
18228 /*
18229 * 5.2.2.2.1 If the {content type} of the ·actual type
18230 * definition· is mixed, then the *initial value* of the
18231 * item must match the canonical lexical representation
18232 * of the {value constraint} value.
18233 *
18234 * ... the *initial value* of an element information
18235 * item is the string composed of, in order, the
18236 * [character code] of each character information item in
18237 * the [children] of that element information item.
18238 */
18239 value = xmlNodeListGetString(elem->doc, elem->children, 1);
18240 if (! xmlStrEqual(BAD_CAST value, elemDecl->value)) {
18241 /*
18242 * TODO: Report invalid & expected values as well.
18243 * TODO: Implement the cononical stuff.
18244 */
18245 xmlSchemaVCustomErr(ctxt,
18246 XML_SCHEMAV_CVC_ELT_5_2_2_2_1,
18247 elem, (xmlSchemaTypePtr) elemDecl,
18248 "The value does not match the cononical "
18249 "lexical representation of the fixed constraint",
18250 NULL);
18251 }
18252 if (value != NULL)
18253 xmlFree(value);
18254 } else if ((actualType->contentType ==
18255 XML_SCHEMA_CONTENT_SIMPLE) ||
18256 (actualType->contentType == XML_SCHEMA_CONTENT_BASIC)) {
18257 xmlChar *value;
18258
18259 /*
18260 * 5.2.2.2.2 If the {content type} of the ·actual type
18261 * definition· is a simple type definition, then the
18262 * *actual value* of the item must match the canonical
18263 * lexical representation of the {value constraint} value.
18264 */
18265 /*
18266 * TODO: *actual value* is the normalized value, impl. this.
18267 * TODO: Report invalid & expected values as well.
18268 * TODO: Implement the cononical stuff.
18269 *
18270 */
18271 value = xmlNodeListGetString(elem->doc, elem->children, 1);
18272 if (! xmlStrEqual(BAD_CAST value, elemDecl->value)) {
18273 xmlSchemaVCustomErr(ctxt,
18274 XML_SCHEMAV_CVC_ELT_5_2_2_2_2,
18275 elem, (xmlSchemaTypePtr) elemDecl,
18276 "The normalized value does not match the cononical "
18277 "lexical representation of the fixed constraint",
18278 NULL);
18279 }
18280 if (value != NULL)
18281 xmlFree(value);
18282
18283 }
18284 /*
18285 * TODO: What if the content type is not 'mixed' or simple?
18286 */
18287
18288 }
18289
18290 }
18291 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018292 /*
18293 * TODO: 7 If the element information item is the ·validation root·, it must be
18294 * ·valid· per Validation Root Valid (ID/IDREF) (§3.3.4).
18295 */
18296
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018297 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000018298}
18299
Daniel Veillard4255d502002-04-16 15:50:10 +000018300/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018301 * xmlSchemaValidateElementByWildcardInternal:
Daniel Veillardc0826a72004-08-10 14:17:33 +000018302 * @ctxt: a schema validation context
18303 * @node: the top node.
18304 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018305 * Represents the recursive portion of xmlSchemaValidateElementByWildcard.
18306 * Not intended to be used by other functions.
Daniel Veillardc0826a72004-08-10 14:17:33 +000018307 *
18308 * Returns 0 if the element is valid, a positive error code
18309 * number otherwise and -1 in case of an internal error.
18310 */
18311static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018312xmlSchemaValidateElementByWildcardInternal(xmlSchemaValidCtxtPtr ctxt,
18313 xmlSchemaWildcardPtr wild,
18314 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +000018315{
18316 const xmlChar *uri;
18317 int ret = 0;
18318 xmlNodePtr child;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018319
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018320 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018321 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
18322 if (ret == -1) {
18323 xmlSchemaVCustomErr(ctxt,
18324 XML_SCHEMAV_INTERNAL,
18325 ctxt->node, NULL,
18326 "Internal error: xmlSchemaValidateElement, "
18327 "assembling schema by xsi", NULL);
18328 return (-1);
18329 }
18330 /*
18331 * NOTE: We won't react on schema parser errors here.
18332 * TODO: But a warning would be nice.
18333 */
18334 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000018335 if (wild->processContents != XML_SCHEMAS_ANY_SKIP) {
18336 xmlSchemaElementPtr decl = NULL;
18337
18338 if (node->ns != NULL)
18339 decl = xmlHashLookup3(ctxt->schema->elemDecl,
18340 node->name, node->ns->href, NULL);
18341 else
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018342 decl = xmlHashLookup3(ctxt->schema->elemDecl, node->name,
18343 NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018344 if (decl != NULL) {
18345 ctxt->node = node;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018346 ret = xmlSchemaValidateElementByDeclaration(ctxt, decl);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018347 if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018348 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000018349 "Internal error: xmlSchemaValidateAnyInternal, "
18350 "validating an element in the context of a wildcard.",
18351 NULL, NULL);
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +000018352 }
18353 return (ret);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018354 } else if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
18355 /* TODO: Change to proper error code. */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018356 xmlSchemaVWildcardErr(ctxt, XML_SCHEMAV_CVC_ELT_1,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018357 node, wild, "No matching global declaration available");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018358 /*
18359 * Evaluate IDCs even if a validation error occured.
18360 */
18361#ifdef IDC_ENABLED
18362 if (xmlSchemaXPathEvaluate(ctxt, ctxt->elemInfo->namespaceName,
18363 ctxt->elemInfo->localName, XML_ELEMENT_NODE) == -1)
18364 return(-1);
18365#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +000018366 return (ctxt->err);
18367 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018368 /*
18369 * Evaluate IDCs; we need to know if an IDC field resolves to
18370 * such a node. This node has no type definition and will
18371 * definitely result in an IDC validation error if an IDC field
18372 * resolves.
18373 */
18374#ifdef IDC_ENABLED
18375 if (xmlSchemaXPathEvaluate(ctxt, ctxt->elemInfo->namespaceName,
18376 ctxt->elemInfo->localName, XML_ELEMENT_NODE) == -1)
18377 return(-1);
18378#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +000018379 }
18380 if (node->children != NULL) {
18381 child = node->children;
18382 do {
18383 if (child->type == XML_ELEMENT_NODE) {
18384 if (child->ns != NULL)
18385 uri = child->ns->href;
18386 else
18387 uri = NULL;
18388 if (xmlSchemaMatchesWildcardNs(wild, uri) == 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018389 /* TODO: error code. */
18390 xmlSchemaVWildcardErr(ctxt, XML_SCHEMAV_ELEMENT_CONTENT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000018391 child, wild,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018392 "The namespace of the element is not allowed");
Daniel Veillardc0826a72004-08-10 14:17:33 +000018393 return (ctxt->err);
18394 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018395#ifdef ELEM_INFO_ENABLED
18396 ctxt->node = child;
18397 xmlSchemaBeginElement(ctxt);
18398#endif
18399 /*
18400 * Recurse over the children.
18401 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018402 ret = xmlSchemaValidateElementByWildcardInternal(ctxt,
18403 wild, child);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018404#ifdef ELEM_INFO_ENABLED
18405 xmlSchemaEndElement(ctxt);
18406#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +000018407 if (ret != 0)
18408 return (ret);
18409 }
18410 child = child->next;
18411 } while (child != NULL);
18412 }
18413 return (0);
18414}
18415
18416/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018417 * xmlSchemaValidateElementContByWildcard:
Daniel Veillardc0826a72004-08-10 14:17:33 +000018418 * @ctxt: a schema validation context
18419 *
18420 * Returns 0 if the element is valid, a positive error code
18421 * number otherwise and -1 in case of an internal or API error.
18422 */
18423static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018424xmlSchemaValidateElementByWildcard(xmlSchemaValidCtxtPtr ctxt,
18425 xmlSchemaTypePtr type)
Daniel Veillardc0826a72004-08-10 14:17:33 +000018426{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018427 if ((type == NULL) || (type->type != XML_SCHEMA_TYPE_ANY) ||
18428 (ctxt->node == NULL)) {
18429 xmlSchemaVCustomErr(ctxt,
18430 XML_SCHEMAV_INTERNAL, ctxt->node, NULL,
18431 "Internal error: xmlSchemaValidateElementByWildcard, "
18432 "bad arguments", NULL);
18433 return (-1);
18434 }
18435 return(xmlSchemaValidateElementByWildcardInternal(ctxt,
18436 type->attributeWildcard, ctxt->node));
Daniel Veillardc0826a72004-08-10 14:17:33 +000018437}
18438
18439/**
William M. Brack2f2a6632004-08-20 23:09:47 +000018440 * xmlSchemaValidateAnyTypeContent:
18441 * @ctxt: a schema validation context
18442 * @node: the current element
18443 *
18444 * This one validates the content of an element of the type
18445 * 'anyType'. The process contents of the wildcard of 'anyType' is "lax",
18446 * thus elements in the subtree will be validated, if a corresponding
18447 * declaration in the schema exists.
18448 *
18449 * Returns 0 if the element and its subtree is valid, a positive error code
18450 * otherwise and -1 in case of an internal or API error.
18451 */
18452static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018453xmlSchemaValidateElementByAnyType(xmlSchemaValidCtxtPtr ctxt,
18454 xmlSchemaTypePtr type)
William M. Brack2f2a6632004-08-20 23:09:47 +000018455{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018456 xmlSchemaTypePtr oldtype;
18457 xmlNodePtr top, cur;
18458 xmlSchemaElementPtr decl;
William M. Brack2f2a6632004-08-20 23:09:47 +000018459 int skipContent, ret;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018460
18461 if ((type == NULL) || (ctxt->node == NULL))
18462 return (-1);
18463
18464 if (ctxt->node->children == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +000018465 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018466
18467 oldtype = ctxt->type;
18468 top = ctxt->node;
18469 /*
18470 * STREAM: Child nodes are processed.
18471 */
18472 cur = ctxt->node->children;
18473 while (cur != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +000018474 skipContent = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018475 if (cur->type == XML_ELEMENT_NODE) {
William M. Brack2f2a6632004-08-20 23:09:47 +000018476 /*
18477 * The process contents of the wildcard is "lax", thus
18478 * we need to validate the element if a declaration
18479 * exists.
18480 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018481 if (cur->ns != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +000018482 decl = xmlHashLookup3(ctxt->schema->elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018483 cur->name, cur->ns->href, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000018484 else
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018485 decl = xmlHashLookup3(ctxt->schema->elemDecl, cur->name, NULL, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000018486 if (decl != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018487 ctxt->node = cur;
18488 ret = xmlSchemaValidateElementByDeclaration(ctxt, decl);
18489 ctxt->node = top;
William M. Brack2f2a6632004-08-20 23:09:47 +000018490 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018491 xmlSchemaVErr(ctxt, cur, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000018492 "Internal error: xmlSchemaValidateAnyTypeContent, "
18493 "validating an element in the context of a wildcard.",
18494 NULL, NULL);
18495 return (ret);
18496 } else if (ret > 0)
18497 return (ret);
18498 skipContent = 1;
18499 }
18500 }
18501 /*
18502 * Browse the full subtree, deep first.
18503 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018504 if ((skipContent == 0) && (cur->children != NULL)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000018505 /* deep first */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018506 cur = cur->children;
18507 } else if ((cur != top) && (cur->next != NULL)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000018508 /* then siblings */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018509 cur = cur->next;
18510 } else if (cur != top) {
William M. Brack2f2a6632004-08-20 23:09:47 +000018511 /* go up to parents->next if needed */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018512 while (cur != top) {
18513 if (cur->parent != NULL)
18514 cur = cur->parent;
18515 if ((cur != top) && (cur->next != NULL)) {
18516 cur = cur->next;
William M. Brack2f2a6632004-08-20 23:09:47 +000018517 break;
18518 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018519 if (cur->parent == NULL) {
18520 cur = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000018521 break;
18522 }
18523 }
18524 /* exit condition */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018525 if (cur == top)
18526 cur = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000018527 } else
18528 break;
18529 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018530 ctxt->type = oldtype;
William M. Brack2f2a6632004-08-20 23:09:47 +000018531 return (0);
18532}
18533
18534/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018535 * xmlSchemaValidateElementByComplexType:
Daniel Veillard4255d502002-04-16 15:50:10 +000018536 * @ctxt: a schema validation context
18537 * @node: the top node.
18538 *
18539 * Validate the content of an element expected to be a complex type type
18540 * xmlschema-1.html#cvc-complex-type
18541 * Validation Rule: Element Locally Valid (Complex Type)
18542 *
18543 * Returns 0 if the element is schemas valid, a positive error code
Daniel Veillard01fa6152004-06-29 17:04:39 +000018544 * number otherwise and -1 in case of internal or API error.
18545 * Note on reported errors: Although it might be nice to report
18546 * the name of the simple/complex type, used to validate the content
18547 * of a node, it is quite unnecessary: for global defined types
18548 * the local name of the element is equal to the NCName of the type,
18549 * for local defined types it makes no sense to output the internal
18550 * computed name of the type. TODO: Instead, one should attach the
18551 * struct of the type involved to the error handler - this allows
18552 * the report of any additional information by the user.
Daniel Veillard4255d502002-04-16 15:50:10 +000018553 */
18554static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018555xmlSchemaValidateElementByComplexType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018556 xmlSchemaTypePtr type,
18557 int valSimpleContent)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018558{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018559 xmlSchemaTypePtr oldtype;
18560 xmlNodePtr elem, child;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018561 int ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +000018562 const xmlChar *nsUri;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018563 xmlSchemaAttrStatePtr attrs = NULL, attrTop = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000018564
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018565 if ((ctxt == NULL) || (type->type != XML_SCHEMA_TYPE_COMPLEX))
18566 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000018567
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018568 oldtype = ctxt->type;
18569 ctxt->type = type;
18570 elem = ctxt->node;
18571
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018572 /*
18573 * Verify the attributes
18574 */
18575 /*
18576 * TODO: This "attrTop" thing is not needed any more.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018577 */
18578 /* NOTE: removed, since a check for abstract is
18579 * done in the cvc-type constraint.
18580 *
18581 *
18582 * if (type->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
18583 * xmlSchemaVComplexTypeErr(ctxt,
18584 * XML_SCHEMAV_CVC_COMPLEX_TYPE_1,
18585 * elem, type,
18586 * "The type definition is abstract");
18587 * return (XML_SCHEMAV_CVC_COMPLEX_TYPE_1);
18588 *}
18589 */
18590
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018591 attrs = ctxt->attr;
18592 attrTop = ctxt->attrTop;
18593 /*
18594 * STREAM: Attribute nodes are processed.
18595 */
18596 xmlSchemaRegisterAttributes(ctxt, elem->properties);
18597 xmlSchemaValidateAttributes(ctxt, elem, type);
18598 if (ctxt->attr != NULL)
18599 xmlSchemaFreeAttributeStates(ctxt->attr);
18600 ctxt->attr = attrs;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018601 ctxt->attrTop = attrTop;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018602
18603 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018604 * TODO: This one creates a regexp even if no content
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018605 * model was defined. Somehow ->contModel is always not NULL
18606 * for complex types, even if they are empty.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018607 * TODO: Check if the obove still occurs.
18608 */
Daniel Veillard4255d502002-04-16 15:50:10 +000018609 switch (type->contentType) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000018610 case XML_SCHEMA_CONTENT_EMPTY: {
18611 /*
18612 * 1 If the {content type} is empty, then the element information
18613 * item has no character or element information item [children].
Daniel Veillard3646d642004-06-02 19:19:14 +000018614 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000018615 /*
18616 * TODO: Is the entity stuff correct?
18617 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018618 if (xmlSchemaHasElemOrCharContent(elem) == 1) {
William M. Brack2f2a6632004-08-20 23:09:47 +000018619 xmlSchemaVComplexTypeErr(ctxt,
18620 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018621 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000018622 "Character or element content is not allowed, "
18623 "because the content type is empty");
Daniel Veillard01fa6152004-06-29 17:04:39 +000018624 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018625 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018626 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018627 case XML_SCHEMA_CONTENT_MIXED:
18628 if ((type->subtypes == NULL) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018629 (type->baseType->builtInType == XML_SCHEMAS_ANYTYPE)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018630 /*
18631 * The type has 'anyType' as its base and no content model
18632 * is defined -> use 'anyType' as the type to validate
18633 * against.
18634 */
18635 ret = xmlSchemaValidateElementByAnyType(ctxt, type->baseType);
18636 /* TODO: Handle -1. */
18637 break;
18638 }
18639 /* No break on purpose. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000018640 case XML_SCHEMA_CONTENT_ELEMENTS:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018641 {
18642 xmlRegExecCtxtPtr oldregexp = NULL;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000018643 xmlChar *values[10];
18644 int terminal, nbval = 10, nbneg;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018645
18646 /*
18647 * Content model check initialization.
18648 */
18649 if (type->contModel != NULL) {
18650 oldregexp = ctxt->regexp;
18651 ctxt->regexp = xmlRegNewExecCtxt(type->contModel,
18652 (xmlRegExecCallbacks)
18653 xmlSchemaValidateCallback, ctxt);
18654#ifdef DEBUG_AUTOMATA
18655 xmlGenericError(xmlGenericErrorContext, "====> %s\n", elem->name);
18656#endif
18657 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018658 /*
18659 * STREAM: Children are processed.
18660 */
18661 child = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018662 while (child != NULL) {
18663 if (child->type == XML_ELEMENT_NODE) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000018664 if (child->ns != NULL)
18665 nsUri = child->ns->href;
18666 else
18667 nsUri = NULL;
18668 ret = xmlRegExecPushString2(ctxt->regexp,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018669 child->name, nsUri, child);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018670 /*
18671 * URGENT TODO: Could we anchor an error report
18672 * here to notify of invalid elements?
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000018673 * TODO: Perhaps it would be better to report
18674 * only the first erroneous element and then break.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018675 */
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000018676#ifdef DEBUG_AUTOMATA
Daniel Veillard01fa6152004-06-29 17:04:39 +000018677 if (ret < 0)
18678 xmlGenericError(xmlGenericErrorContext,
18679 " --> %s Error\n", child->name);
William M. Bracke7091952004-05-11 15:09:58 +000018680 else
18681 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard01fa6152004-06-29 17:04:39 +000018682 " --> %s\n", child->name);
18683#endif
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018684 if (ret < 0) {
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000018685 xmlRegExecErrInfo(ctxt->regexp, NULL, &nbval, &nbneg,
18686 &values[0], &terminal);
18687 xmlSchemaVComplexTypeElemErr(ctxt,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018688 XML_SCHEMAV_ELEMENT_CONTENT,
18689 child, NULL/* type */,
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000018690 "This element is not expected",
18691 nbval, nbneg, values);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018692 ret = 1;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000018693 /*
18694 * Note that this will skip further validation of the
18695 * content.
18696 */
18697 break;
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018698 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000018699 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) &&
18700 /*
18701 * TODO: Ask Daniel if this are all character nodes.
18702 */
18703 (((child->type == XML_TEXT_NODE) && (!IS_BLANK_NODE(child))) ||
18704 (child->type == XML_ENTITY_NODE) ||
18705 (child->type == XML_ENTITY_REF_NODE) ||
18706 (child->type == XML_CDATA_SECTION_NODE))) {
18707 /*
18708 * 2.3 If the {content type} is element-only, then the
18709 * element information item has no character information
18710 * item [children] other than those whose [character
18711 * code] is defined as a white space in [XML 1.0 (Second
18712 * Edition)].
18713 */
William M. Brack2f2a6632004-08-20 23:09:47 +000018714 xmlSchemaVComplexTypeErr(ctxt,
18715 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018716 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000018717 "Character content is not allowed, "
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018718 "because the content type is element-only");
18719 ret = 1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018720 break;
18721 }
18722 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018723 }
18724 /*
18725 * Content model check finalization.
18726 */
18727 if (type->contModel != NULL) {
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000018728 if (ret == 0) {
18729 xmlRegExecNextValues(ctxt->regexp, &nbval, &nbneg,
18730 &values[0], &terminal);
18731 if (nbval + nbneg != 0) {
18732 /*
18733 * If a next value still exists, I does not have to
18734 * mean that there's an element missing, since it
18735 * might be an optional element. So double check it.
18736 */
18737 ret = xmlRegExecPushString(ctxt->regexp,
18738 NULL, NULL);
18739 if (ret <= 0) {
18740 ret = 1;
18741 xmlSchemaVComplexTypeElemErr(ctxt,
18742 XML_SCHEMAV_ELEMENT_CONTENT,
18743 elem, type, "Missing child element(s)",
18744 nbval, nbneg, values);
18745 } else
18746 ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018747#ifdef DEBUG_AUTOMATA
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000018748 xmlGenericError(xmlGenericErrorContext,
18749 "====> %s : %d\n", elem->name, ret);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018750#endif
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000018751 }
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018752#ifdef DEBUG_CONTENT
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000018753 if (ret == 0)
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018754 xmlGenericError(xmlGenericErrorContext,
18755 "Element %s content check succeeded\n",
18756 elem->name);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018757#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018758 }
18759 xmlRegFreeExecCtxt(ctxt->regexp);
18760 ctxt->regexp = oldregexp;
18761 }
18762 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000018763 break;
18764 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018765 case XML_SCHEMA_CONTENT_BASIC:
18766 /*
18767 * If the simple content was already validated
18768 * (e.g. a default value), the content need not
18769 * to be validated again.
18770 */
18771 if (valSimpleContent == 1) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000018772 xmlChar *value = NULL;
18773 /*
18774 * We hit a complexType with a simpleContent resolving
18775 * to a user derived or built-in simple type.
William M. Brack2f2a6632004-08-20 23:09:47 +000018776 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000018777 /*
18778 * 2.2 If the {content type} is a simple type definition,
18779 * then the element information item has no element
18780 * information item [children], and the ·normalized value·
18781 * of the element information item is ·valid· with respect
18782 * to that simple type definition as defined by String
18783 * Valid (§3.14.4).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018784 */
18785 /*
18786 * STREAM: Children are processed.
18787 */
18788 child = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018789 while (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018790 /*
18791 * TODO: Could the entity stuff produce elements
18792 * as well?
18793 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000018794 if (child->type == XML_ELEMENT_NODE) {
William M. Brack2f2a6632004-08-20 23:09:47 +000018795 xmlSchemaVComplexTypeErr(ctxt,
18796 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018797 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000018798 "Element content is not allowed, because "
18799 "the content type is a simple type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000018800 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
18801 break;
18802 }
18803 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018804 }
18805 ctxt->node = elem;
18806 ctxt->cur = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018807 if (ret == 0) {
18808 /*
18809 * Validate the character content against a simple type.
Daniel Veillard3646d642004-06-02 19:19:14 +000018810 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018811 /*
18812 * STREAM: Children are processed.
18813 */
18814 if (elem->children == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000018815 value = NULL;
18816 else
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018817 value = xmlNodeGetContent(elem);
18818 /*
18819 * URGENT TODO: Should facets for the simple type validation be
18820 * disabled, if the derivation of facets for complex types
18821 * is implemented?
18822 */
18823 /*
18824 * NOTE: This call won't check the correct types of the
18825 * content nodes, since this should be done here.
18826 */
18827 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type, value, 1, 1, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000018828 if (ret > 0) {
18829 /*
18830 * NOTE: Although an error will be reported by
18831 * xmlSchemaValidateSimpleTypeValue, the spec wants
18832 * a specific complex type error to be reported
18833 * additionally.
18834 */
18835 xmlSchemaVComplexTypeErr(ctxt,
18836 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018837 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000018838 "The character content is not valid");
Daniel Veillard01fa6152004-06-29 17:04:39 +000018839 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
18840 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018841 xmlSchemaVErr(ctxt, elem, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000018842 "Internal error: xmlSchemaValidateComplexType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000018843 "Element '%s': Error while validating character "
18844 "content against complex type '%s'.\n",
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018845 elem->name, type->name);
18846 if (value != NULL)
18847 xmlFree(value);
18848 ctxt->type = oldtype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018849 return (-1);
18850 }
William M. Brack2f2a6632004-08-20 23:09:47 +000018851 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000018852 if (ret == 0) {
18853 /*
18854 * Apply facets of the complexType. Be sure to pass the
18855 * built-in type to xmlSchemaValidateFacetsInternal.
18856 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018857 /* URGENT TODO: I don't know yet if the facets of the simple type
Daniel Veillard01fa6152004-06-29 17:04:39 +000018858 * are used, or if the facets, defined by this complex type,
18859 * are to be used only. This here applies both facet sets.
18860 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000018861
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018862 ret = xmlSchemaValidateFacetsInternal(ctxt,
18863 type, value, 0, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000018864 if (ret > 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +000018865 xmlSchemaVComplexTypeErr(ctxt,
18866 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018867 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000018868 "The character content is not valid");
Daniel Veillard01fa6152004-06-29 17:04:39 +000018869 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
18870 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018871 xmlSchemaVErr(ctxt, elem, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000018872 "Internal error: xmlSchemaValidateComplexType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000018873 "Element '%s': Error while validating character "
18874 "content against complex type '%s'; failed to "
Daniel Veillard01fa6152004-06-29 17:04:39 +000018875 "apply facets.\n",
18876 type->name, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018877 if (value != NULL)
18878 xmlFree(value);
18879 ctxt->type = oldtype;
18880 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000018881 }
18882 }
18883 if (value != NULL)
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000018884 xmlFree(value);
18885
Daniel Veillard01fa6152004-06-29 17:04:39 +000018886 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018887 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018888 default:
18889 TODO xmlGenericError(xmlGenericErrorContext,
18890 "unimplemented content type %d\n",
18891 type->contentType);
Daniel Veillard4255d502002-04-16 15:50:10 +000018892 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018893 ctxt->type = oldtype;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018894 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000018895}
18896
18897/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018898 * xmlSchemaValidateElementByType:
Daniel Veillard4255d502002-04-16 15:50:10 +000018899 * @ctxt: a schema validation context
18900 * @elem: an element
18901 * @type: the list of type declarations
18902 *
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018903 * Validation Rule: Element Locally Valid (Type).
Daniel Veillard4255d502002-04-16 15:50:10 +000018904 *
18905 * Returns 0 if the element is schemas valid, a positive error code
18906 * number otherwise and -1 in case of internal or API error.
18907 */
18908static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018909xmlSchemaValidateElementByType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018910 xmlSchemaTypePtr type,
18911 int valSimpleContent)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018912{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018913 int ret;
Daniel Veillard4255d502002-04-16 15:50:10 +000018914
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018915
18916 if ((ctxt == NULL) || (type == NULL)) {
18917 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_INTERNAL, NULL, NULL,
18918 "Internal error: xmlSchemaValidateElementByType, "
18919 "bad arguments", NULL);
18920 return (-1);
18921 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018922 /*
18923 * This one is called by "xmlSchemaValidateElementByDeclaration".
18924 * It will forward to the proper validation
18925 * procedures for the given type.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018926 */
18927 if (type == NULL) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018928 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018929 XML_SCHEMAV_CVC_TYPE_1,
18930 ctxt->node, NULL,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018931 "The type definition is absent", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018932 return (XML_SCHEMAV_CVC_TYPE_1);
18933 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018934
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018935 if (type->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018936 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018937 XML_SCHEMAV_CVC_TYPE_2,
18938 ctxt->node, type,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018939 "The type definition is abstract", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018940 return (XML_SCHEMAV_CVC_TYPE_2);
18941 }
18942
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018943#ifdef ELEM_INFO_ENABLED
18944 ctxt->elemInfo->typeDef = type;
18945#endif
18946
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018947 switch (type->type) {
18948 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018949 ret = xmlSchemaValidateElementByComplexType(ctxt, type,
18950 valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018951 break;
18952 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018953 ret = xmlSchemaValidateElementBySimpleType(ctxt, type,
18954 valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018955 break;
18956 case XML_SCHEMA_TYPE_BASIC:
18957 if (type->builtInType == XML_SCHEMAS_ANYTYPE)
18958 ret = xmlSchemaValidateElementByAnyType(ctxt, type);
18959 else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018960 ret = xmlSchemaValidateElementBySimpleType(ctxt, type,
18961 valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018962 break;
18963 default:
18964 ret = -1;
18965 break;
18966 }
18967 if (ret == -1)
18968 return (-1);
18969 else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018970 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000018971}
18972
18973
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018974static int
18975xmlSchemaCheckAttrLocallyValid(xmlSchemaValidCtxtPtr ctxt,
18976 xmlSchemaAttributePtr decl,
18977 xmlSchemaAttrStatePtr state,
18978 xmlAttrPtr attr)
18979{
18980 xmlChar *value;
18981 const xmlChar *defValue;
18982 xmlSchemaValPtr defVal;
18983 int fixed;
18984 int ret;
18985
18986 if (decl->subtypes == NULL) {
18987 state->state = XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED;
18988 return (XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED);
18989 }
18990 value = xmlNodeListGetString(attr->doc, attr->children, 1);
18991 ctxt->node = (xmlNodePtr) attr;
18992 ctxt->cur = attr->children;
18993 /*
18994 * NOTE: This call also checks the content nodes for correct type.
18995 */
18996 ret = xmlSchemaValidateSimpleTypeValue(ctxt, decl->subtypes,
18997 value, 1, 1, 1, 1);
18998
18999 /*
19000 * Handle 'fixed' attributes.
19001 */
19002 if (ret > 0) {
19003 state->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
19004 /*
19005 * NOTE: Fixed value constraints will be not
19006 * applied if the value was invalid, because:
19007 * 1. The validation process does not return a precomputed
19008 * value.
19009 * 2. An invalid value implies a violation of a fixed
19010 * value constraint.
19011 */
19012 } else if (ret == 0) {
19013 state->state = XML_SCHEMAS_ATTR_CHECKED;
19014 if (xmlSchemaGetEffectiveValueConstraint(decl,
19015 &fixed, &defValue, &defVal) && (fixed == 1)) {
19016 /*
19017 * cvc-au : Attribute Locally Valid (Use)
19018 * For an attribute information item to be·valid·
19019 * with respect to an attribute use its ·normalized
19020 * value· must match the canonical lexical representation
19021 * of the attribute use's {value constraint} value, if it
19022 * is present and fixed.
19023 */
19024 /*
19025 * NOTE: the validation context holds in ctxt->value the
19026 * precomputed value of the attribute; well for some types,
19027 * fallback to string comparison if no computed value
19028 * exists.
19029 */
19030 if (((ctxt->value != NULL) &&
19031 (xmlSchemaCompareValues(ctxt->value, defVal) != 0)) ||
19032 ((ctxt->value == NULL) &&
19033 (! xmlStrEqual(defValue, BAD_CAST value)))) {
19034 state->state =
19035 XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE;
19036 }
19037 }
19038 }
19039 if (value != NULL) {
19040 xmlFree(value);
19041 }
19042 return (ret);
19043}
19044
Daniel Veillard4255d502002-04-16 15:50:10 +000019045/**
19046 * xmlSchemaValidateAttributes:
19047 * @ctxt: a schema validation context
19048 * @elem: an element
Daniel Veillard3646d642004-06-02 19:19:14 +000019049 * @type: the complexType holding the attribute uses
Daniel Veillard4255d502002-04-16 15:50:10 +000019050 *
19051 * Validate the attributes of an element.
19052 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000019053 * 1. Existent, invalid attributes are reported in the form
19054 * "prefix:localName".
19055 * Reason: readability - it is easier to find the actual XML
19056 * representation of the attributes QName.
19057 * 2. Missing attributes are reported in the form
19058 * {"URI", "localName"}.
19059 * This is necessary, since the the prefix need not to be declared
19060 * at all, and thus is not computable.
19061 *
Daniel Veillard4255d502002-04-16 15:50:10 +000019062 * Returns 0 if the element is schemas valid, a positive error code
19063 * number otherwise and -1 in case of internal or API error.
19064 */
19065static int
Daniel Veillard3646d642004-06-02 19:19:14 +000019066xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem, xmlSchemaTypePtr type)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019067{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019068 const xmlChar *nsURI;
Daniel Veillard3646d642004-06-02 19:19:14 +000019069 int ret;
19070 xmlAttrPtr attr; /* An attribute on the element. */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019071 const xmlChar *defValue;
19072 xmlSchemaValPtr defVal;
19073 int fixed;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019074 xmlSchemaAttributeLinkPtr attrUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000019075 xmlSchemaAttributePtr attrDecl;
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000019076 int found;
William M. Brack803812b2004-06-03 02:11:24 +000019077 xmlSchemaAttrStatePtr curState, reqAttrStates = NULL, reqAttrStatesTop = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019078 xmlSchemaAttrStatePtr defAttrStates = NULL, defAttrStatesTop = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019079 xmlNodePtr oldnode;
Daniel Veillard3646d642004-06-02 19:19:14 +000019080#ifdef DEBUG_ATTR_VALIDATION
19081 int redundant = 0;
19082#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000019083
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019084
Daniel Veillardc0826a72004-08-10 14:17:33 +000019085 /*
19086 * Allow all attributes if the type is anyType.
19087 */
19088 if (type == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE))
19089 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019090
19091 oldnode = ctxt->node;
19092 if (type != NULL)
19093 attrUse = type->attributeUses;
Daniel Veillard3646d642004-06-02 19:19:14 +000019094 while (attrUse != NULL) {
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000019095 found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000019096 attrDecl = attrUse->attr;
19097#ifdef DEBUG_ATTR_VALIDATION
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019098 printf("attr use - name: %s\n", xmlSchemaGetAttrName(attrDecl));
Daniel Veillard3646d642004-06-02 19:19:14 +000019099 printf("attr use - use: %d\n", attrDecl->occurs);
19100#endif
19101 for (curState = ctxt->attr; curState != NULL; curState = curState->next) {
19102
19103 if (curState->decl == attrUse->attr) {
19104#ifdef DEBUG_ATTR_VALIDATION
19105 redundant = 1;
19106#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019107 }
Daniel Veillard3646d642004-06-02 19:19:14 +000019108 attr = curState->attr;
19109#ifdef DEBUG_ATTR_VALIDATION
19110 printf("attr - name: %s\n", attr->name);
19111 if (attr->ns != NULL)
19112 printf("attr - ns: %s\n", attr->ns->href);
19113 else
19114 printf("attr - ns: none\n");
19115#endif
19116 /* TODO: Can this ever happen? */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019117 if (attr == NULL)
19118 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000019119 if (attrDecl->ref != NULL) {
19120 if (!xmlStrEqual(attr->name, attrDecl->ref))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019121 continue;
19122 if (attr->ns != NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000019123 if ((attrDecl->refNs == NULL) ||
19124 (!xmlStrEqual(attr->ns->href, attrDecl->refNs)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019125 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000019126 } else if (attrDecl->refNs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019127 continue;
19128 }
19129 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000019130 if (!xmlStrEqual(attr->name, attrDecl->name))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019131 continue;
19132 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +000019133 * handle the namespaces checks here
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019134 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000019135 if (attr->ns == NULL) {
19136 /*
William M. Bracke7091952004-05-11 15:09:58 +000019137 * accept an unqualified attribute only if the target
19138 * namespace of the declaration is absent.
Daniel Veillardbe9c6322003-11-22 20:37:51 +000019139 */
Daniel Veillard3646d642004-06-02 19:19:14 +000019140 if (attrDecl->targetNamespace != NULL)
William M. Bracke7091952004-05-11 15:09:58 +000019141 /*
19142 * This check was removed, since the target namespace
19143 * was evaluated during parsing and already took
19144 * "attributeFormDefault" into account.
19145 */
19146 /* ((attributes->flags & XML_SCHEMAS_ATTR_NSDEFAULT) == 0)) */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000019147 continue;
19148 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000019149 if (attrDecl->targetNamespace == NULL)
Daniel Veillardbe9c6322003-11-22 20:37:51 +000019150 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000019151 if (!xmlStrEqual(attrDecl->targetNamespace,
Daniel Veillardbe9c6322003-11-22 20:37:51 +000019152 attr->ns->href))
19153 continue;
19154 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019155 }
Daniel Veillard3646d642004-06-02 19:19:14 +000019156#ifdef DEBUG_ATTR_VALIDATION
19157 printf("found\n");
19158#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019159 found = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +000019160 curState->decl = attrDecl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019161 ret = xmlSchemaCheckAttrLocallyValid(ctxt, attrDecl, curState, attr);
Daniel Veillard3646d642004-06-02 19:19:14 +000019162 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019163 if (!found) {
19164 if (attrDecl->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
19165 xmlSchemaAttrStatePtr tmp;
19166
Daniel Veillard3646d642004-06-02 19:19:14 +000019167#ifdef DEBUG_ATTR_VALIDATION
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019168 printf("required attr not found\n");
Daniel Veillard3646d642004-06-02 19:19:14 +000019169#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019170 /*
19171 * Add a new dummy attribute state.
19172 */
19173 tmp = (xmlSchemaAttrStatePtr) xmlMalloc(sizeof(xmlSchemaAttrState));
19174 if (tmp == NULL) {
19175 xmlSchemaVErrMemory(ctxt, "registering required attributes", NULL);
19176 ctxt->node = oldnode;
19177 return (-1);
19178 }
19179 tmp->attr = NULL;
19180 tmp->state = XML_SCHEMAS_ATTR_MISSING;
19181 tmp->decl = attrDecl;
19182 tmp->next = NULL;
19183
19184 if (reqAttrStates == NULL) {
19185 reqAttrStates = tmp;
19186 reqAttrStatesTop = tmp;
19187 } else {
19188 reqAttrStatesTop->next = tmp;
19189 reqAttrStatesTop = tmp;
19190 }
19191 } else if ((attrDecl->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
19192 (xmlSchemaGetEffectiveValueConstraint(attrDecl,
19193 &fixed, &defValue, &defVal))) {
19194 xmlSchemaAttrStatePtr tmp;
19195 /*
19196 * Handle non existent default/fixed attributes.
19197 */
19198 tmp = (xmlSchemaAttrStatePtr)
19199 xmlMalloc(sizeof(xmlSchemaAttrState));
19200 if (tmp == NULL) {
19201 xmlSchemaVErrMemory(ctxt,
19202 "registering schema specified attributes", NULL);
19203 ctxt->node = oldnode;
19204 return (-1);
19205 }
19206 tmp->attr = NULL;
19207 tmp->state = XML_SCHEMAS_ATTR_DEFAULT;
19208 tmp->decl = attrDecl;
19209 tmp->value = defValue;
19210 tmp->next = NULL;
19211
19212 if (defAttrStates == NULL) {
19213 defAttrStates = tmp;
19214 defAttrStates = tmp;
19215 } else {
19216 defAttrStates->next = tmp;
19217 defAttrStatesTop = tmp;
19218 }
19219 }
Daniel Veillard3646d642004-06-02 19:19:14 +000019220 }
19221 attrUse = attrUse->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000019222 }
Daniel Veillard3646d642004-06-02 19:19:14 +000019223 /*
19224 * Add required attributes to the attribute states of the context.
19225 */
19226 if (reqAttrStates != NULL) {
19227 if (ctxt->attr == NULL) {
19228 ctxt->attr = reqAttrStates;
19229 } else {
19230 ctxt->attrTop->next = reqAttrStates;
19231 }
19232 ctxt->attrTop = reqAttrStatesTop;
Daniel Veillardc0826a72004-08-10 14:17:33 +000019233 }
Daniel Veillard3646d642004-06-02 19:19:14 +000019234 /*
19235 * Process wildcards.
19236 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019237
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019238 if ((type != NULL) && (type->attributeWildcard != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000019239#ifdef DEBUG_ATTR_VALIDATION
19240 xmlSchemaWildcardNsPtr ns;
19241 printf("matching wildcard: [%d] of complexType: %s\n", type->attributeWildcard, type->name);
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019242 if (type->attributeWildcard->processContents ==
19243 XML_SCHEMAS_ANY_LAX)
19244 printf("processContents: lax\n");
19245 else if (type->attributeWildcard->processContents ==
19246 XML_SCHEMAS_ANY_STRICT)
19247 printf("processContents: strict\n");
19248 else
19249 printf("processContents: skip\n");
Daniel Veillard3646d642004-06-02 19:19:14 +000019250 if (type->attributeWildcard->any)
19251 printf("type: any\n");
19252 else if (type->attributeWildcard->negNsSet != NULL) {
19253 printf("type: negated\n");
19254 if (type->attributeWildcard->negNsSet->value == NULL)
19255 printf("ns: (absent)\n");
19256 else
19257 printf("ns: %s\n", type->attributeWildcard->negNsSet->value);
19258 } else if (type->attributeWildcard->nsSet != NULL) {
19259 printf("type: set\n");
19260 ns = type->attributeWildcard->nsSet;
19261 while (ns != NULL) {
19262 if (ns->value == NULL)
19263 printf("ns: (absent)\n");
19264 else
19265 printf("ns: %s\n", ns->value);
19266 ns = ns->next;
19267 }
19268 } else
19269 printf("empty\n");
19270
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019271
19272#endif
Daniel Veillard3646d642004-06-02 19:19:14 +000019273 curState = ctxt->attr;
19274 while (curState != NULL) {
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019275 if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
19276 if (curState->attr->ns != NULL)
19277 nsURI = curState->attr->ns->href;
19278 else
19279 nsURI = NULL;
19280 if (xmlSchemaMatchesWildcardNs(type->attributeWildcard,
19281 nsURI)) {
19282 /*
19283 * Handle processContents.
19284 */
19285 if ((type->attributeWildcard->processContents ==
19286 XML_SCHEMAS_ANY_LAX) ||
19287 (type->attributeWildcard->processContents ==
19288 XML_SCHEMAS_ANY_STRICT)) {
19289
19290 attr = curState->attr;
19291 attrDecl = xmlSchemaGetAttribute(ctxt->schema,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019292 attr->name, nsURI);
19293 curState->decl = attrDecl;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019294 if (attrDecl != NULL) {
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019295 curState->decl = attrDecl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019296 ret = xmlSchemaCheckAttrLocallyValid(ctxt, attrDecl, curState, attr);
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019297 } else if (type->attributeWildcard->processContents ==
19298 XML_SCHEMAS_ANY_LAX) {
19299 curState->state = XML_SCHEMAS_ATTR_CHECKED;
19300 }
19301 } else
Daniel Veillard3646d642004-06-02 19:19:14 +000019302 curState->state = XML_SCHEMAS_ATTR_CHECKED;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019303 }
19304 }
Daniel Veillard3646d642004-06-02 19:19:14 +000019305 curState = curState->next;
19306 }
19307 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019308
Daniel Veillardc0826a72004-08-10 14:17:33 +000019309 /*
19310 * Report missing and illegal attributes.
19311 */
19312 if (ctxt->attr != NULL) {
19313 curState = ctxt->attr;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019314 while ((curState != NULL) && (curState != ctxt->attrTop->next)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000019315 if (curState->state != XML_SCHEMAS_ATTR_CHECKED) {
19316 attr = curState->attr;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019317 if (curState->decl != NULL) {
19318 if (curState->decl->ref != NULL)
19319 attrDecl = curState->decl->refDecl;
19320 else
19321 attrDecl = curState->decl;
19322 } else
19323 attrDecl = NULL;
19324 if (curState->state == XML_SCHEMAS_ATTR_MISSING) {
19325 xmlSchemaVMissingAttrErr(ctxt, elem, attrDecl);
19326 } else if (curState->state ==
19327 XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED) {
19328 xmlSchemaVCustomErr(ctxt,
19329 XML_SCHEMAV_CVC_ATTRIBUTE_2,
19330 (xmlNodePtr) attr,
19331 (xmlSchemaTypePtr) attrDecl,
19332 "The type definition is absent",
19333 NULL);
19334 } else if (curState->state ==
19335 XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE) {
19336 xmlSchemaVCustomErr(ctxt,
19337 XML_SCHEMAV_CVC_AU,
19338 (xmlNodePtr) attr, (xmlSchemaTypePtr) attrDecl,
19339 "The value does not match the fixed value "
19340 "constraint", NULL);
19341 } else if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000019342 /* TODO: "prohibited" won't ever be touched here!.
19343 (curState->state == XML_SCHEMAS_ATTR_PROHIBITED))
19344 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019345 /*
19346 * TODO: One might report different error messages
19347 * for the following errors.
19348 */
19349 if ((type == NULL) || (type->attributeWildcard == NULL)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000019350 xmlSchemaVIllegalAttrErr(ctxt,
19351 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, attr);
19352 } else {
19353 xmlSchemaVIllegalAttrErr(ctxt,
19354 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, attr);
19355 }
19356 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000019357 }
19358 curState = curState->next;
19359 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019360 }
19361
19362 /*
19363 * Add missing default/fixed attributes.
19364 */
19365 if (ctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
19366 curState = defAttrStates;
19367 while (curState != NULL) {
19368 attrDecl = curState->decl;
19369 if (attrDecl->ref != NULL)
19370 attrDecl = attrDecl->refDecl;
19371 /*
19372 * PSVI: Add a new attribute node to the current element.
19373 */
19374 if (attrDecl->targetNamespace == NULL) {
19375 xmlNewProp(elem, attrDecl->name, curState->value);
19376 } else {
19377 xmlNsPtr ns;
19378
19379 ns = xmlSearchNsByHref(elem->doc, elem,
19380 attrDecl->targetNamespace);
19381 if (ns == NULL) {
19382 xmlChar prefix[12];
19383 int counter = 1;
19384
19385 attr = curState->attr;
19386 /*
19387 * Create a namespace declaration on the validation
19388 * root node if no namespace declaration is in scope.
19389 */
19390 snprintf((char *) prefix, sizeof(prefix), "p");
19391 /*
19392 * This is somehow not performant, since the ancestor
19393 * axis beyond @elem will be searched as well.
19394 */
19395 ns = xmlSearchNs(elem->doc, elem, BAD_CAST prefix);
19396 while (ns != NULL) {
19397 if (counter > 1000) {
19398 xmlSchemaVErr(ctxt, (xmlNodePtr) attr,
19399 XML_SCHEMAV_INTERNAL,
19400 "Internal error: xmlSchemaValidateAttributes, "
19401 "could not compute a ns prefix for "
19402 "default/fixed attribute '%s'.\n",
19403 attrDecl->name, NULL);
19404
19405 break;
19406 }
19407 snprintf((char *) prefix,
19408 sizeof(prefix), "p%d", counter++);
19409 ns = xmlSearchNs(elem->doc, elem,
19410 BAD_CAST prefix);
19411 }
19412 if (ns == NULL) {
19413 ns = xmlNewNs(ctxt->validationRoot,
19414 attrDecl->targetNamespace, BAD_CAST prefix);
19415 xmlNewNsProp(elem, ns, attrDecl->name,
19416 curState->value);
19417 }
19418 } else {
19419 xmlNewNsProp(elem, ns, attrDecl->name,
19420 curState->value);
19421 }
19422 }
19423 curState = curState->next;
19424 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000019425 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019426 if (defAttrStates != NULL)
19427 xmlSchemaFreeAttributeStates(defAttrStates);
19428
Daniel Veillard3646d642004-06-02 19:19:14 +000019429#ifdef DEBUG_ATTR_VALIDATION
19430 if (redundant)
19431 xmlGenericError(xmlGenericErrorContext,
19432 "xmlSchemaValidateAttributes: redundant call by type: %s\n",
19433 type->name);
19434#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019435 ctxt->node = oldnode;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019436 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000019437}
19438
19439/**
19440 * xmlSchemaValidateElement:
19441 * @ctxt: a schema validation context
19442 * @elem: an element
19443 *
19444 * Validate an element in a tree
19445 *
19446 * Returns 0 if the element is schemas valid, a positive error code
19447 * number otherwise and -1 in case of internal or API error.
19448 */
19449static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019450xmlSchemaValidateElement(xmlSchemaValidCtxtPtr ctxt)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019451{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019452 xmlSchemaElementPtr elemDecl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019453 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000019454
Daniel Veillardc0826a72004-08-10 14:17:33 +000019455 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019456 * This one is called by xmlSchemaValidateDocument and
19457 * xmlSchemaValidateOneElement.
19458 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019459 if (ctxt->schema == NULL) {
19460 /*
19461 * No schema was specified at time of creation of the validation
19462 * context. Use xsi:schemaLocation and xsi:noNamespaceSchemaLocation
19463 * of the instance to build a schema.
19464 */
19465 if (ctxt->pctxt == NULL)
19466 ctxt->pctxt = xmlSchemaNewParserCtxt("*");
19467 if (ctxt->pctxt == NULL)
19468 return (-1);
19469 ctxt->schema = xmlSchemaNewSchema(ctxt->pctxt);
19470 if (ctxt->schema == NULL)
19471 return (-1);
19472 /* TODO: assign user data. */
19473 ctxt->pctxt->error = ctxt->error;
19474 ctxt->pctxt->warning = ctxt->warning;
19475 ctxt->xsiAssemble = 1;
19476 } else
19477 ctxt->xsiAssemble = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019478 /*
19479 * Assemble new schemata using xsi.
Daniel Veillardc0826a72004-08-10 14:17:33 +000019480 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019481 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019482 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
19483 if (ret == -1) {
19484 xmlSchemaVCustomErr(ctxt,
19485 XML_SCHEMAV_INTERNAL,
19486 ctxt->node, NULL,
19487 "Internal error: xmlSchemaValidateElement, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019488 "assembling schema by xsi", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019489 }
19490 /*
19491 * NOTE: We won't react on schema parser errors here.
19492 * TODO: But a warning would be nice.
19493 */
19494 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019495 if (ret != -1) {
19496 if (ctxt->node->ns != NULL)
19497 elemDecl = xmlSchemaGetElem(ctxt->schema, ctxt->node->name,
19498 ctxt->node->ns->href);
19499 else
19500 elemDecl = xmlSchemaGetElem(ctxt->schema, ctxt->node->name, NULL);
19501
19502 if (elemDecl == NULL) {
19503 xmlSchemaVCustomErr(ctxt,
19504 XML_SCHEMAV_CVC_ELT_1,
19505 ctxt->node, NULL,
19506 "No matching global declaration available", NULL);
19507 ret = XML_SCHEMAV_CVC_ELT_1;
19508 } else {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019509#ifdef IDC_ENABLED
19510 /*
19511 * Augment the IDC definitions.
19512 */
19513 if (ctxt->schema->idcDef != NULL) {
19514 xmlHashScan(ctxt->schema->idcDef,
19515 (xmlHashScanner) xmlSchemaAugmentIDC, ctxt);
19516 }
19517#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019518#ifdef ELEM_INFO_ENABLED
19519 ctxt->depth = -1;
19520 xmlSchemaBeginElement(ctxt);
19521#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019522 ret = xmlSchemaValidateElementByDeclaration(ctxt, elemDecl);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019523#ifdef ELEM_INFO_ENABLED
19524 xmlSchemaEndElement(ctxt);
19525#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019526 if (ret < 0) {
19527 xmlSchemaVCustomErr(ctxt,
19528 XML_SCHEMAV_INTERNAL, ctxt->node, NULL,
19529 "Internal error: xmlSchemaValidateElement, "
19530 "calling validation by declaration", NULL);
19531 }
19532 }
19533 }
19534 /* ctxt->xsiAssemble = 0; */
19535 if (ctxt->xsiAssemble) {
19536 if (ctxt->schema != NULL) {
19537 xmlSchemaFree(ctxt->schema);
19538 ctxt->schema = NULL;
19539 }
Daniel Veillard4255d502002-04-16 15:50:10 +000019540 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019541 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000019542}
19543
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019544
Daniel Veillard4255d502002-04-16 15:50:10 +000019545/**
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000019546 * xmlSchemaValidateOneElement:
19547 * @ctxt: a schema validation context
19548 * @elem: an element node
19549 *
19550 * Validate a branch of a tree, starting with the given @elem.
19551 *
19552 * Returns 0 if the element and its subtree is valid, a positive error
19553 * code number otherwise and -1 in case of an internal or API error.
19554 */
19555int
19556xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
19557{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019558 if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000019559 return (-1);
19560
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019561 if (ctxt->schema == NULL) {
19562 xmlSchemaVErr(ctxt, NULL,
19563 XML_SCHEMAV_INTERNAL,
19564 "API error: xmlSchemaValidateOneElement, "
19565 "no schema specified.\n", NULL, NULL);
19566 return (-1);
19567 }
19568
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000019569 ctxt->doc = elem->doc;
19570 ctxt->err = 0;
19571 ctxt->nberrors = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019572 ctxt->node = elem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019573 ctxt->validationRoot = elem;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019574 return (xmlSchemaValidateElement(ctxt));
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000019575}
19576
19577/**
Daniel Veillard4255d502002-04-16 15:50:10 +000019578 * xmlSchemaValidateDocument:
19579 * @ctxt: a schema validation context
19580 * @doc: a parsed document tree
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019581 * @xsiAssemble: should schemata be added if requested by the instance?
Daniel Veillard4255d502002-04-16 15:50:10 +000019582 *
19583 * Validate a document tree in memory.
19584 *
19585 * Returns 0 if the document is schemas valid, a positive error code
19586 * number otherwise and -1 in case of internal or API error.
19587 */
19588static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019589xmlSchemaValidateDocument(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
19590{
Daniel Veillard4255d502002-04-16 15:50:10 +000019591 xmlNodePtr root;
Daniel Veillard01fa6152004-06-29 17:04:39 +000019592
Daniel Veillard4255d502002-04-16 15:50:10 +000019593 root = xmlDocGetRootElement(doc);
19594 if (root == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000019595 xmlSchemaVCustomErr(ctxt,
19596 XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
19597 (xmlNodePtr) doc, NULL,
19598 "The document has no document element", NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019599 return (ctxt->err);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019600 }
Daniel Veillard4255d502002-04-16 15:50:10 +000019601 /*
19602 * Okay, start the recursive validation
19603 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019604 ctxt->node = root;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019605 ctxt->validationRoot = root;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019606 xmlSchemaValidateElement(ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000019607
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019608 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000019609}
19610
19611/************************************************************************
19612 * *
19613 * SAX Validation code *
19614 * *
19615 ************************************************************************/
19616
19617/************************************************************************
19618 * *
19619 * Validation interfaces *
19620 * *
19621 ************************************************************************/
19622
19623/**
19624 * xmlSchemaNewValidCtxt:
19625 * @schema: a precompiled XML Schemas
19626 *
19627 * Create an XML Schemas validation context based on the given schema
19628 *
19629 * Returns the validation context or NULL in case of error
19630 */
19631xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019632xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
19633{
Daniel Veillard4255d502002-04-16 15:50:10 +000019634 xmlSchemaValidCtxtPtr ret;
19635
19636 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
19637 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019638 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000019639 return (NULL);
19640 }
19641 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
Daniel Veillardc0826a72004-08-10 14:17:33 +000019642 ret->schema = schema;
Daniel Veillard3646d642004-06-02 19:19:14 +000019643 ret->attrTop = NULL;
19644 ret->attr = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000019645 return (ret);
19646}
19647
19648/**
19649 * xmlSchemaFreeValidCtxt:
19650 * @ctxt: the schema validation context
19651 *
19652 * Free the resources associated to the schema validation context
19653 */
19654void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019655xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
19656{
Daniel Veillard4255d502002-04-16 15:50:10 +000019657 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019658 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000019659 if (ctxt->attr != NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000019660 xmlSchemaFreeAttributeStates(ctxt->attr);
Daniel Veillard88c58912002-04-23 07:12:20 +000019661 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019662 xmlSchemaFreeValue(ctxt->value);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019663 if (ctxt->pctxt != NULL) {
19664 xmlSchemaFreeParserCtxt(ctxt->pctxt);
19665 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019666
19667#ifdef IDC_ENABLED
19668 if (ctxt->idcNodes != NULL) {
19669 int i;
19670 xmlSchemaPSVIIDCNodePtr item;
19671
19672 for (i = 0; i < ctxt->nbIdcNodes; i++) {
19673 item = ctxt->idcNodes[i];
19674 xmlFree(item->keys);
19675 xmlFree(item);
19676 }
19677 xmlFree(ctxt->idcNodes);
19678 }
19679
19680 if (ctxt->idcKeys != NULL) {
19681 int i;
19682 for (i = 0; i < ctxt->nbIdcKeys; i++)
19683 xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
19684 xmlFree(ctxt->idcKeys);
19685 }
19686
19687 if (ctxt->xpathStates != NULL)
19688 xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
19689 if (ctxt->xpathStatePool != NULL)
19690 xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
19691
19692 /*
19693 * Augmented IDC information.
19694 */
19695 if (ctxt->aidcs != NULL) {
19696 xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
19697 do {
19698 next = cur->next;
19699 xmlFree(cur);
19700 cur = next;
19701 } while (cur != NULL);
19702 }
19703#endif /* IDC_ENABLED */
19704#ifdef ELEM_INFO_ENABLED
19705 if (ctxt->elemInfos != NULL) {
19706 int i;
19707 xmlSchemaElemInfoPtr info;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019708
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019709 for (i = 0; i < ctxt->sizeElemInfos; i++) {
19710 info = ctxt->elemInfos[i];
19711 if (info == NULL)
19712 continue;
19713 if (info->value != NULL)
19714 xmlSchemaFreeValue(info->value);
19715#ifdef IDC_ENABLED
19716 if (info->idcMatchers != NULL)
19717 xmlSchemaIDCFreeMatcherList(info->idcMatchers);
19718#endif
19719 /*
19720 * TODO: Free the IDC table if still existent.
19721 */
19722
19723 /*
19724 xmlFree(info->localName);
19725 if (info->namespaceName != NULL)
19726 xmlFree(info->namespaceName);
19727 */
19728 xmlFree(info);
19729 }
19730 xmlFree(ctxt->elemInfos);
19731 }
19732#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000019733 xmlFree(ctxt);
19734}
19735
19736/**
19737 * xmlSchemaSetValidErrors:
19738 * @ctxt: a schema validation context
19739 * @err: the error function
19740 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +000019741 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +000019742 *
William M. Brack2f2a6632004-08-20 23:09:47 +000019743 * Set the error and warning callback informations
Daniel Veillard4255d502002-04-16 15:50:10 +000019744 */
19745void
19746xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019747 xmlSchemaValidityErrorFunc err,
19748 xmlSchemaValidityWarningFunc warn, void *ctx)
19749{
Daniel Veillard4255d502002-04-16 15:50:10 +000019750 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019751 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000019752 ctxt->error = err;
19753 ctxt->warning = warn;
19754 ctxt->userData = ctx;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019755 if (ctxt->pctxt != NULL)
19756 xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
Daniel Veillard4255d502002-04-16 15:50:10 +000019757}
19758
19759/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000019760 * xmlSchemaGetValidErrors:
19761 * @ctxt: a XML-Schema validation context
19762 * @err: the error function result
19763 * @warn: the warning function result
19764 * @ctx: the functions context result
19765 *
19766 * Get the error and warning callback informations
19767 *
19768 * Returns -1 in case of error and 0 otherwise
19769 */
19770int
19771xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
19772 xmlSchemaValidityErrorFunc * err,
19773 xmlSchemaValidityWarningFunc * warn, void **ctx)
19774{
19775 if (ctxt == NULL)
19776 return (-1);
19777 if (err != NULL)
19778 *err = ctxt->error;
19779 if (warn != NULL)
19780 *warn = ctxt->warning;
19781 if (ctx != NULL)
19782 *ctx = ctxt->userData;
19783 return (0);
19784}
19785
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019786
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019787/**
Daniel Veillard6927b102004-10-27 17:29:04 +000019788 * xmlSchemaSetValidOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019789 * @ctxt: a schema validation context
19790 * @options: a combination of xmlSchemaValidOption
19791 *
19792 * Sets the options to be used during the validation.
19793 *
19794 * Returns 0 in case of success, -1 in case of an
19795 * API error.
19796 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019797int
19798xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
19799 int options)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019800
19801{
19802 int i;
19803
19804 if (ctxt == NULL)
19805 return (-1);
19806 /*
19807 * WARNING: Change the start value if adding to the
19808 * xmlSchemaValidOption.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019809 * TODO: Is there an other, more easy to maintain,
19810 * way?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019811 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019812 for (i = 1; i < (int) sizeof(int) * 8; i++) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019813 if (options & 1<<i) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019814 xmlSchemaVErr(ctxt, NULL,
19815 XML_SCHEMAV_INTERNAL,
19816 "Internal error: xmlSchemaSetValidOptions, "
19817 "invalid option argument.\n", NULL, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019818 return (-1);
19819 }
19820 }
19821 ctxt->options = options;
19822 return (0);
19823}
19824
19825/**
Daniel Veillard6927b102004-10-27 17:29:04 +000019826 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019827 * @ctxt: a schema validation context
19828 *
William M. Brack21e4ef22005-01-02 09:53:13 +000019829 * Get the validation context options.
19830 *
19831 * Returns the option combination or -1 on error.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019832 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019833int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019834xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
19835
19836{
19837 if (ctxt == NULL)
19838 return (-1);
19839 else
19840 return (ctxt->options);
19841}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019842
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019843
Daniel Veillard259f0df2004-08-18 09:13:18 +000019844/**
Daniel Veillard4255d502002-04-16 15:50:10 +000019845 * xmlSchemaValidateDoc:
19846 * @ctxt: a schema validation context
19847 * @doc: a parsed document tree
19848 *
19849 * Validate a document tree in memory.
19850 *
19851 * Returns 0 if the document is schemas valid, a positive error code
19852 * number otherwise and -1 in case of internal or API error.
19853 */
19854int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019855xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
19856{
Daniel Veillard4255d502002-04-16 15:50:10 +000019857 int ret;
19858
19859 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019860 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000019861
19862 ctxt->doc = doc;
William M. Brack2f2a6632004-08-20 23:09:47 +000019863 ctxt->err = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019864 ctxt->nberrors = 0;
19865
19866 /*
19867 if (ctxt->schema == NULL) {
19868 xmlSchemaVErr(ctxt, NULL,
19869 XML_SCHEMAV_INTERNAL,
19870 "API error: xmlSchemaValidateDoc, "
19871 "no schema specified and assembling of schemata "
19872 "using xsi:schemaLocation and xsi:noNamespaceSchemaLocation "
19873 "is not enabled.\n", NULL, NULL);
19874 return (-1);
19875 }
19876 */
Daniel Veillard4255d502002-04-16 15:50:10 +000019877 ret = xmlSchemaValidateDocument(ctxt, doc);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019878 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000019879}
19880
19881/**
19882 * xmlSchemaValidateStream:
19883 * @ctxt: a schema validation context
19884 * @input: the input to use for reading the data
19885 * @enc: an optional encoding information
19886 * @sax: a SAX handler for the resulting events
19887 * @user_data: the context to provide to the SAX handler.
19888 *
19889 * Validate a document tree in memory.
19890 *
19891 * Returns 0 if the document is schemas valid, a positive error code
19892 * number otherwise and -1 in case of internal or API error.
19893 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019894int
Daniel Veillard4255d502002-04-16 15:50:10 +000019895xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019896 xmlParserInputBufferPtr input, xmlCharEncoding enc,
19897 xmlSAXHandlerPtr sax, void *user_data)
19898{
Daniel Veillard4255d502002-04-16 15:50:10 +000019899 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019900 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000019901 ctxt->input = input;
19902 ctxt->enc = enc;
19903 ctxt->sax = sax;
19904 ctxt->user_data = user_data;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019905 TODO return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000019906}
19907
19908#endif /* LIBXML_SCHEMAS_ENABLED */